Commit Graph

21 Commits

Author SHA1 Message Date
Artem Bilan
e434a4625c Cancel subscription for MPS.subscribeToPublisher
The `Flux.takeWhile()` only works if there is data in the `Publisher`
to consume.
We still need to be able to cancel subscription and stop producing even if
there is no data at the moment.

* Change `takeWhile()` to the `doOnSubscribe()` and store `subscription`
in the `volatile` property of the `MessageProducerSupport`
* Cancel such a subscription in the `doStop()` impl
* Propagate `doStop()` to super in the `ZeroMqMessageProducer`
which is only one reactive channel adapter overriding `doStop()`
* Verify in the `ReactiveMessageProducerTests` that subscription is cancelled
for delayed data in the `Publisher`

**Cherry-pick to `5.5.x`**
2022-03-16 14:51:47 -04:00
Artem Bilan
c661d7925e Remove SocketUtils usage
* Remove usage of non-stable `org.springframework.util.SocketUtils`
* Replace it with `0` for those tests where it is possible to select OS port
* Remove the mentioning of the `SocketUtils` from the `testing.adoc`
* Use `TransportConstants.DEFAULT_STOMP_PORT` for `StompServerIntegrationTests`.
We may disable this test in the future for CI if it is not going to be stable
* Introduce `Supplier<String> connectUrl` variants for `ZeroMqMessageHandler`
to let it defer connection evaluation until subscription to the socket `Mono`
in the `ZeroMqMessageHandler`.
* Move connection logic in the `ZeroMqMessageHandler` to `Lifecycle.start()`

Related to https://github.com/spring-projects/spring-framework/issues/28054

**Cherry-pick to `5.4.x`**
2022-02-16 09:10:08 -05:00
Artem Bilan
39c3acb042 Fix ZMQMessageHandlerTests race condition
Use `receiveTimeOut = 0` on SUB socket and rely
on the retries from the `await().atMost()`.
Also resubscribe in the retry callback before publishing the next attempt
2021-07-09 11:38:03 -04:00
Artem Bilan
920b8ae744 ZeroMQ test: Add sleep between SUB & PUB 2021-07-07 15:57:44 -04:00
Artem Bilan
60b355bc38 Move subscription to PUB after connection
Looks like `subSocket.subscribe("test");` is lost when there is no
other side of PUB/SUB connection
2021-06-23 10:33:28 -04:00
Artem Bilan
353e99aa80 Rework ZeroMqMessageProducerTests for XPUB
* Use an `XPUB` socket to receive subscriptions before publishing.
This makes the test more robust and less blocked for that `Thread.sleep()`
2021-06-22 17:05:46 -04:00
Artem Bilan
7072cf1ab0 Increase timeout in ZeroMqMessageHandlerTests 2021-06-22 12:05:04 -04:00
Artem Bilan
cd7465a370 Rework ZeroMQMH test for Awaitility
Turns out PUB socket doesn't care if there are subscribers to it or not.
The sent message may be just lost in between.

* Resend message in the test until it is received by subscriber
* Use `await().untilAsserted()` to iterate the logic at most 10 seconds
2021-06-22 11:36:27 -04:00
Artem Bilan
d7dfea7bd0 Optimize ZeroMqMessageHandlerTests for ZMQ.Poller
* Fix unused import in the `IntegrationDynamicWebSocketHandlerMapping`
2021-06-17 11:21:57 -04:00
Artem Bilan
e70e15c310 Add ZeroMqChannel test with Curve Auth
Related to https://stackoverflow.com/questions/67214907/zeromq-with-spring-spring-integration-zeromq

* Fix typos in `ZeroMqChannel` JavaDocs
2021-04-29 16:09:49 -04:00
Artem Bilan
0ea9d700de Fix ZeroMQ components initialization
SO: https://stackoverflow.com/questions/67214907/zeromq-with-spring-spring-integration-zeromq

The `Mono` is created in several places in ZeroMQ components from their constructors.
That leads to the reactive stream to be configured just after ctor, which will ignore
any changes to the options which are used from that `Mono` definition.
For example this code `.doOnNext(this.sendSocketConfigurer)` is done once during
reactive stream definition.

* Fix all the ZeroMQ components to defer usage of the options which could be changed
after ctor initialization
* Cover affected option changes in the tests

**Cherry-pick to `5.4.x`**
2021-04-22 12:44:42 -04:00
Artem Bilan
73d9b8cccd Increase receive timeout in ZeroMqMHTests 2021-01-29 12:43:08 -05:00
Artem Bilan
8763c95622 GH-3469 New Sonar smell & volatile busyWaitMillis
Fixes https://github.com/spring-projects/spring-integration/issues/3469

* Fix new Sonar smells
* Mark `LockRegistryLeaderInitiator.busyWaitMillis` as `volatile`
so runtime changes (e.g. `RedisLockRegistryLeaderInitiatorTests`)
will make an immediate effect
2021-01-21 14:55:14 -05:00
Artem Bilan
0331933c16 Rely on MProducerSupport.active for Flux (#3423)
* Rely on `MProducerSupport.active` for `Flux`

* Fix `MessageProducerSupport` to extract an `active` flag and set it before
`isRunning` - the `Flux` subscription relies on the `takeWhile()`
where in case of `autoStartup = false` we will never start consume because
it is set to `true` already after `doStart()`
* Refactor all the `MessageProducerSupport` implementation with similar
`active` state to use already one from the super class

**Cherry-pick to 5.3.x**

* * Remove `MessageProducerSupport.setActive()`
to not let to mutate it from the implementations
* Set `active` to `false` in the `destroy()`
* Clean up and fix typos in the affected `JmsMessageDrivenEndpoint`

* * Pull `active` flag down to the `AbstractEndpoint`
* Set `active = true` in the `start()` before calling `doStart()`
* Do same for `active = false` in the `stop()`
* Clean up `AbstractEndpoint` impls to not call `doStart/doStop` for nothing
* Refactor endpoints to rely on the `active` state from the `AbstractEndpoint`
not their own
2020-11-06 13:51:03 -05:00
Artem Bilan
80d3c67847 * Add @NonNullApi to ZeroMQ packages 2020-10-26 16:11:44 -04:00
Artem Bilan
c7ff99a4e8 Use LogAccessor from SF
* Change main classes to use a `LogAccessor` API to simplify code flow
* Fix tests according `LogAccessor` property
* Fix some Sonar smells
2020-10-06 13:56:50 -04:00
Artem Bilan
c934adbd1b Various fixes
* Adapt to WebFlux deprecations: https://github.com/spring-projects/spring-framework/issues/25751
* Back to SNAPSHOTs
* Fix new Sonar smells
2020-09-28 15:38:16 -04:00
Artem Bilan
a62a7d1ddd INT-3045: Add in & out ZeroMq channel adapters (#3388)
* INT-3045: Add in & out ZeroMq channel adapters

JIRA: https://jira.spring.io/browse/INT-3045

* Add `ZeroMqMessageHandler` to produce messages into one-way ZeroMq sockets
* Add `ZeroMqMessageProducer` to consumer messages from one-way ZeroMq sockets
* Add `ConvertingBytesMessageMapper` impl for the `BytesMessageMapper` to
delegate an actual conversion into the provided `MessageConverter`
* Add `ZeroMqHeaders` for message headers constants representing ZeroMq message attributes
* Fix `ZeroMqChannel` for the proper deferred `zeroMqProxy` evaluation
* Add more JavaDocs
* Fix `ZeroMqChannelTests.testPubSubBind()` to be sure that really all the
subscribed channels get the same message from the `PUB` socket

* * Fix typo in the `ConvertingBytesMessageMapper`
* Add `this` for `doOnError()` in the `ZeroMqChannel` & `ZeroMqMessageProducer`
* Change the bind logic in the `ZeroMqMessageProducer` to `port` and let it to
bind to random port.
The actual port is available later via `getBoundPort()`
* Introduce a `ZeroMqMessageProducer.receiveRaw()` to let received `ZMsg` to
be produce as a `payload`
* Add a logic into `ZeroMqMessageHandler` to treat `ZMsg` in the payload of
request message as is without any conversion
* Fix race condition in the `ZeroMqMessageProducer` to destroy `consumerScheduler`
when the main `Flux` is complete

* * Add Java DSL for ZeroMq components
* Extract `ReactiveMessageHandlerSpec` for `ReactiveMessageHandler` impls
* Add debug message into `EmbeddedJsonHeadersMessageMapper` when cannot `decodeNativeFormat()`
* Make `ReactiveMongoDbMessageHandlerSpec` extending `ReactiveMessageHandlerSpec`
* Make `ZeroMqProxy` `autoStartup` by default
* Add `ZeroMqDslTests` to cover all the Java DSL for ZeroMq
* Introduce a `MimeTypeSerializer`  to serialize a `MimeType` into JSON as a plain string;
use it as extra serializer in the `JacksonJsonUtils.messagingAwareMapper()`
* Fix typo for the `AllowListTypeResolverBuilder` inner class

* * Add some docs
* Fix Checkstyle violations

* * More docs

* Fix language in Docs

Co-authored-by: Gary Russell <grussell@vmware.com>

Co-authored-by: Gary Russell <grussell@vmware.com>
2020-09-25 13:46:01 -04:00
Artem Bilan
5c2af845d5 Simplify complexity in ZeroMqChannel constructor
* Upgrade to Spring AMQP `2.3.0-M2`
2020-08-12 11:35:16 -04:00
Artem Bilan
77936b9251 Add zeromq.adoc to index files
* Fix Sonar smells for new ZeroMQ components
* Upgrade to Spring Data `2020.0.0-M2`
2020-08-12 11:09:32 -04:00
Artem Bilan
a76bb24965 INT-3045: Add ZeroMqChannel support (#3355)
* INT-3045: Add `ZeroMqChannel` support

JIRA: https://jira.spring.io/browse/INT-3045

Provide a `SubscribableChannel` implementation for ZeroMQ

The general idea is to let to have a distributed channel implementation
where every client can connect to a single server backed by the channel.

The logic in the channel is fully transparent for end-user and there is just
enough to send message to it and subscribe for receiving on the other side.
If PUB/SUB model is used, all the subscribes (even over the network) going to
receive the same published message.
In case of PUSH/PULL only one subscriber in the whole cluster is going to get
the published message

* Use Reactor for better threading control
* JeroMQ is not interruptible-friendly: use control sockets to stop proxy loop
* Name Reactor's schedulers to avoid daemon threads

* * Use try-catch-with-resource to close sockets automatically
* Fix Checkstyle violations
* Use `Mono.handle()` to receive data from the socket

* * Optimize local for just a couple of PAIR sockets
* Implement TCP binding
* Add PUB/SUB tests

* * Fix subscriber scheduler name
* Optimize socket create logic
* Add PUSH/PULL over TCP test

* * Fix subscriber scheduler name
* Optimize socket create logic
* Add PUSH/PULL over TCP test
* Implement PUB/SUB over TCP

* * Introduce `ZeroMqProxy` - Spring-friendly component to configure and manage ZeroMq proxy
* Use this `ZeroMqProxy` logic as an external component for `ZeroMqChannel` testing

* * Fix Checkstyle
* Apply docs polishing
* Expose a capture socket on the proxy
* Implement `DisposableBean` in the `ZeroMqProxy` to destroy an internal executor service
* Add JavaDocs to `ZeroMqChannel`
* Add one more `ZeroMqChannel` to TCP test to be sure that proxy distribution works well

* * Add `hamcrest-core` dependency for Awatility

* * Add more JavaDocs to `ZeroMqProxy` and `ZeroMqChannel`
* Expose `ZeroMqChannel.setZeroMqProxy()` option for easier
configuration within the same application context
* Make `ZeroMqChannel` sockets configuration and connection
dependant on provided `ZeroMqProxy` (if any)
* Add `Consumer<ZMQ.Socket>` configuration callbacks to the `ZeroMqChannel`
* Expose `ZeroMqChannel.consumeDelay` option

* * Add docs for ZeroMQ
* Some additions into a `reactive-streams.adoc`
* Fix typo in the `xmpp.adoc`

* * Add `optional` `jackson-databind` since `ZeroMqChannel` uses it by default
* More words into docs

* * Fix language in docs according review

* Fix language in docs according review

Co-authored-by: Gary Russell <grussell@vmware.com>

* Apply suggestions from code review

Co-authored-by: Oliver <oli-ver@users.noreply.github.com>

* * Fix threading using a `publishOn()` for specific scheduler after `cache()`

* * Remove unused import

* * Change proxy port check from static `Mono.just()` to `Mono.fromCallable()`
to really evaluate the current port state on every repeat
* Add finite `100` repeat number to avoid infinite blocking when proxy is not started at all
* Add `doOnError()` for proxy `Mono` to log `ERROR` when repeat is exhausted

* * Fix Checkstyle violation

Co-authored-by: Gary Russell <grussell@vmware.com>
Co-authored-by: Oliver <oli-ver@users.noreply.github.com>
2020-08-11 15:04:02 -04:00