use of io.smallrye.mutiny.Uni in project smallrye-reactive-messaging by smallrye.
the class RabbitMQConnector method getPublisherBuilder.
/**
* Creates a <em>channel</em> for the given configuration. The channel's configuration is associated with a
* specific {@code connector}, using the {@link Connector} qualifier's parameter indicating a key to
* which {@link IncomingConnectorFactory} to use.
*
* <p>
* Note that the connection to the <em>transport</em> or <em>broker</em> is generally postponed until the
* subscription occurs.
*
* @param config the configuration, must not be {@code null}, must contain the {@link #CHANNEL_NAME_ATTRIBUTE}
* attribute.
* @return the created {@link PublisherBuilder}, will not be {@code null}.
* @throws IllegalArgumentException if the configuration is invalid.
* @throws NoSuchElementException if the configuration does not contain an expected attribute.
*/
@Override
public PublisherBuilder<? extends Message<?>> getPublisherBuilder(final Config config) {
final RabbitMQConnectorIncomingConfiguration ic = new RabbitMQConnectorIncomingConfiguration(config);
incomingChannelStatus.put(ic.getChannel(), ChannelStatus.INITIALISING);
// Create a client
final RabbitMQClient client = RabbitMQClientHelper.createClient(this, ic, clientOptions, credentialsProviders);
final ConnectionHolder holder = new ConnectionHolder(client, ic, getVertx());
final RabbitMQFailureHandler onNack = createFailureHandler(ic);
final RabbitMQAckHandler onAck = createAckHandler(ic);
// Ensure we set the queue up
Uni<RabbitMQClient> uniQueue = holder.getOrEstablishConnection().onItem().call(connection -> establishQueue(connection, ic)).onItem().call(connection -> establishDLQ(connection, ic)).onItem().invoke(connection -> incomingChannelStatus.put(ic.getChannel(), ChannelStatus.CONNECTED));
// Once the queue is set up, set yp a consumer
final Integer interval = ic.getReconnectInterval();
final Integer attempts = ic.getReconnectAttempts();
Multi<? extends Message<?>> multi = uniQueue.onItem().transformToUni(connection -> client.basicConsumer(ic.getQueueName(), new QueueOptions().setAutoAck(ic.getAutoAcknowledgement()).setMaxInternalQueueSize(ic.getMaxIncomingInternalQueueSize()).setKeepMostRecent(ic.getKeepMostRecent()))).onItem().transformToMulti(consumer -> getStreamOfMessages(consumer, holder, ic, onNack, onAck)).plug(m -> {
if (attempts > 0) {
return m.onFailure().invoke(log::retrieveMessagesRetrying).onFailure().retry().withBackOff(ofSeconds(1), ofSeconds(interval)).atMost(attempts).onFailure().invoke(t -> {
incomingChannelStatus.put(ic.getChannel(), ChannelStatus.NOT_CONNECTED);
log.retrieveMessagesNoMoreRetrying(t);
});
}
return m;
});
if (Boolean.TRUE.equals(ic.getBroadcast())) {
multi = multi.broadcast().toAllSubscribers();
}
return ReactiveStreams.fromPublisher(multi);
}
use of io.smallrye.mutiny.Uni in project smallrye-reactive-messaging by smallrye.
the class RabbitMQConnector method establishQueue.
/**
* Uses a {@link RabbitMQClient} to ensure the required queue-exchange bindings are created.
*
* @param client the RabbitMQ client
* @param ic the incoming channel configuration
* @return a {@link Uni<String>} which yields the queue name
*/
private Uni<String> establishQueue(final RabbitMQClient client, final RabbitMQConnectorIncomingConfiguration ic) {
final String queueName = ic.getQueueName();
// Declare the queue (and its binding(s) to the exchange, and TTL) if we have been asked to do so
final JsonObject queueArgs = new JsonObject();
queueArgs.put("x-dead-letter-exchange", ic.getDeadLetterExchange());
queueArgs.put("x-dead-letter-routing-key", ic.getDeadLetterRoutingKey().orElse(queueName));
ic.getQueueSingleActiveConsumer().ifPresent(sac -> queueArgs.put("x-single-active-consumer", sac));
ic.getQueueTtl().ifPresent(queueTtl -> {
if (queueTtl >= 0) {
queueArgs.put("x-message-ttl", queueTtl);
} else {
throw ex.illegalArgumentInvalidQueueTtl();
}
});
return establishExchange(client, ic).onItem().transform(v -> Boolean.TRUE.equals(ic.getQueueDeclare()) ? null : queueName).onItem().ifNull().switchTo(() -> client.queueDeclare(queueName, ic.getQueueDurable(), ic.getQueueExclusive(), ic.getQueueAutoDelete(), queueArgs).onItem().invoke(() -> log.queueEstablished(queueName)).onFailure().invoke(ex -> log.unableToEstablishQueue(queueName, ex)).onItem().transformToMulti(v -> establishBindings(client, ic)).onCompletion().invoke(() -> Multi.createFrom().item("ignore")).onItem().ignoreAsUni().onItem().transform(v -> queueName));
}
use of io.smallrye.mutiny.Uni in project openk9 by smclab.
the class DatasourceProcessor method process.
@Incoming("ingestion")
@Outgoing("ingestion-datasource")
public Uni<IngestionDatasourcePayload> process(Object obj) {
JsonObject jsonObject = obj instanceof JsonObject ? (JsonObject) obj : new JsonObject(new String((byte[]) obj));
long datasourceId = jsonObject.getLong("datasourceId");
Uni<Datasource> datasourceUni = Datasource.findById(datasourceId);
return Panache.withTransaction(() -> datasourceUni.flatMap(datasource -> EnrichPipeline.findByDatasourceId(datasource.getDatasourceId()).onItem().ifNull().continueWith(EnrichPipeline::new).flatMap(enrichPipeline -> {
Uni<List<EnrichItem>> enrichItemUni;
if (enrichPipeline.getEnrichPipelineId() != null) {
enrichItemUni = EnrichItem.findByEnrichPipelineId(enrichPipeline.getEnrichPipelineId()).onItem().ifNull().continueWith(List::of);
} else {
enrichItemUni = Uni.createFrom().item(List.of());
}
return Uni.combine().all().unis(Tenant.findById(datasource.getTenantId()), enrichItemUni).combinedWith((tenantObj, enrichItemList) -> {
Tenant tenant = (Tenant) tenantObj;
IngestionPayload ingestionPayload = jsonObject.mapTo(IngestionPayload.class);
ingestionPayload.setTenantId(tenant.getTenantId());
DatasourceContext datasourceContext = DatasourceContext.of(datasource, tenant, enrichPipeline, enrichItemList);
return IngestionDatasourcePayload.of(ingestionPayload, datasourceContext);
});
})).eventually(() -> Datasource.<Datasource>findById(datasourceId).flatMap(datasource -> {
datasource.setLastIngestionDate(Instant.ofEpochMilli(jsonObject.getLong("parsingDate")));
return datasource.persist();
})));
}
use of io.smallrye.mutiny.Uni in project smallrye-reactive-messaging by smallrye.
the class AmqpConnector method getSubscriberBuilder.
@Override
public SubscriberBuilder<? extends Message<?>, Void> getSubscriberBuilder(Config config) {
AmqpConnectorOutgoingConfiguration oc = new AmqpConnectorOutgoingConfiguration(config);
String configuredAddress = oc.getAddress().orElseGet(oc::getChannel);
opened.put(oc.getChannel(), false);
AtomicReference<AmqpSender> sender = new AtomicReference<>();
AmqpClient client = AmqpClientHelper.createClient(this, oc, clientOptions);
String link = oc.getLinkName().orElseGet(oc::getChannel);
ConnectionHolder holder = new ConnectionHolder(client, oc, getVertx());
Uni<AmqpSender> getSender = Uni.createFrom().deferred(() -> {
// If we already have a sender, use it.
AmqpSender current = sender.get();
if (current != null && !current.connection().isDisconnected()) {
if (isLinkOpen(current)) {
return Uni.createFrom().item(current);
} else {
// link closed, close the sender, and recreate one.
current.closeAndForget();
}
}
return holder.getOrEstablishConnection().onItem().transformToUni(connection -> {
boolean anonymous = oc.getUseAnonymousSender().orElseGet(() -> ConnectionHolder.supportAnonymousRelay(connection));
if (anonymous) {
return connection.createAnonymousSender();
} else {
return connection.createSender(configuredAddress, new AmqpSenderOptions().setLinkName(link).setCapabilities(getClientCapabilities(oc)));
}
}).onItem().invoke(s -> {
AmqpSender orig = sender.getAndSet(s);
if (orig != null) {
// Close the previous one if any.
orig.closeAndForget();
}
opened.put(oc.getChannel(), true);
});
}).onFailure().invoke(t -> {
sender.set(null);
opened.put(oc.getChannel(), false);
}).onCancellation().invoke(() -> {
sender.set(null);
opened.put(oc.getChannel(), false);
});
AmqpCreditBasedSender processor = new AmqpCreditBasedSender(this, holder, oc, getSender);
processors.put(oc.getChannel(), processor);
return ReactiveStreams.<Message<?>>builder().via(processor).onError(t -> {
log.failureReported(oc.getChannel(), t);
opened.put(oc.getChannel(), false);
}).ignore();
}
use of io.smallrye.mutiny.Uni in project smallrye-reactive-messaging by smallrye.
the class KafkaThrottledLatestProcessedCommit method received.
/**
* Received a new record from Kafka.
* This method is called from a Vert.x event loop.
*
* @param record the record
* @param <K> the key
* @param <V> the value
* @return the record emitted once everything has been done
*/
@Override
public <K, V> Uni<IncomingKafkaRecord<K, V>> received(IncomingKafkaRecord<K, V> record) {
TopicPartition recordsTopicPartition = getTopicPartition(record);
OffsetStore offsetStore = offsetStores.get(recordsTopicPartition);
Uni<OffsetStore> uni;
if (offsetStore == null) {
uni = consumer.committed(recordsTopicPartition).emitOn(// Switch back to event loop
runnable -> context.runOnContext(x -> runnable.run())).onItem().transform(offsets -> {
OffsetAndMetadata lastCommitted = offsets.get(recordsTopicPartition);
OffsetStore store = new OffsetStore(recordsTopicPartition, unprocessedRecordMaxAge, lastCommitted == null ? -1 : lastCommitted.offset() - 1);
offsetStores.put(recordsTopicPartition, store);
return store;
});
} else {
uni = Uni.createFrom().item(offsetStore);
}
return uni.onItem().invoke(store -> {
store.received(record.getOffset());
if (timerId < 0) {
startFlushAndCheckHealthTimer();
}
}).onItem().transform(x -> record);
}
Aggregations