use of org.springframework.data.mongodb.core.messaging.ChangeStreamRequest.ChangeStreamRequestOptions in project spring-data-mongodb by spring-projects.
the class ChangeStreamTests method readsAndConvertsMessageBodyCorrectly.
// DATAMONGO-1803
@Test
void readsAndConvertsMessageBodyCorrectly() throws InterruptedException {
CollectingMessageListener<ChangeStreamDocument<Document>, User> messageListener = new CollectingMessageListener<>();
ChangeStreamRequest<User> request = new ChangeStreamRequest<>(messageListener, new ChangeStreamRequestOptions(null, "user", Duration.ofMillis(10), ChangeStreamOptions.builder().build()));
Subscription subscription = container.register(request, User.class);
awaitSubscription(subscription);
template.save(jellyBelly);
awaitMessages(messageListener, 1);
Message<ChangeStreamDocument<Document>, User> message1 = messageListener.getFirstMessage();
assertThat(message1.getRaw()).isNotNull();
assertThat(message1.getProperties()).isEqualTo(MessageProperties.builder().collectionName("user").databaseName("change-stream-tests").build());
assertThat(message1.getBody()).isEqualTo(jellyBelly);
}
use of org.springframework.data.mongodb.core.messaging.ChangeStreamRequest.ChangeStreamRequestOptions in project spring-data-mongodb by spring-projects.
the class ChangeStreamTests method resumesCorrectly.
// DATAMONGO-1803
@Test
void resumesCorrectly() throws InterruptedException {
CollectingMessageListener<ChangeStreamDocument<Document>, User> messageListener1 = new CollectingMessageListener<>();
Subscription subscription1 = container.register(new ChangeStreamRequest<>(messageListener1, new ChangeStreamRequestOptions(null, "user", Duration.ofMillis(10), ChangeStreamOptions.builder().build())), User.class);
awaitSubscription(subscription1);
template.save(jellyBelly);
template.save(sugarSplashy);
template.save(huffyFluffy);
awaitMessages(messageListener1, 3);
BsonDocument resumeToken = messageListener1.getFirstMessage().getRaw().getResumeToken();
CollectingMessageListener<ChangeStreamDocument<Document>, User> messageListener2 = new CollectingMessageListener<>();
ChangeStreamRequest<User> subSequentRequest = ChangeStreamRequest.builder().collection("user").publishTo(messageListener2).resumeToken(resumeToken).maxAwaitTime(Duration.ofMillis(10)).build();
Subscription subscription2 = container.register(subSequentRequest, User.class);
awaitSubscription(subscription2);
awaitMessages(messageListener2, 2);
List<User> messageBodies = messageListener2.getMessages().stream().map(Message::getBody).collect(Collectors.toList());
assertThat(messageBodies).hasSize(2).doesNotContain(jellyBelly);
}
use of org.springframework.data.mongodb.core.messaging.ChangeStreamRequest.ChangeStreamRequestOptions in project spring-data-mongodb by spring-projects.
the class ChangeStreamTests method readsPlainDocumentMessageCorrectly.
// DATAMONGO-1803
@Test
void readsPlainDocumentMessageCorrectly() throws InterruptedException {
CollectingMessageListener<ChangeStreamDocument<Document>, Document> messageListener = new CollectingMessageListener<>();
ChangeStreamRequest<Document> request = new ChangeStreamRequest<>(messageListener, new ChangeStreamRequestOptions(null, "user", Duration.ofMillis(10), ChangeStreamOptions.builder().build()));
Subscription subscription = container.register(request, Document.class);
awaitSubscription(subscription);
template.save(jellyBelly);
awaitMessages(messageListener, 1);
Message<ChangeStreamDocument<Document>, Document> message1 = messageListener.getFirstMessage();
assertThat(message1.getRaw()).isNotNull();
assertThat(message1.getProperties()).isEqualTo(MessageProperties.builder().collectionName("user").databaseName("change-stream-tests").build());
assertThat(message1.getBody()).isEqualTo(new Document("_id", "id-1").append("user_name", "jellyBelly").append("age", 7).append("_class", User.class.getName()));
}
use of org.springframework.data.mongodb.core.messaging.ChangeStreamRequest.ChangeStreamRequestOptions in project spring-data-mongodb by spring-projects.
the class ChangeStreamTests method resumeAtTimestampCorrectly.
// DATAMONGO-2012, DATAMONGO-2113
@Test
@MongoVersion(asOf = "4.0")
void resumeAtTimestampCorrectly() throws InterruptedException {
CollectingMessageListener<ChangeStreamDocument<Document>, User> messageListener1 = new CollectingMessageListener<>();
Subscription subscription1 = container.register(new ChangeStreamRequest<>(messageListener1, new ChangeStreamRequestOptions(null, "user", Duration.ofMillis(10), ChangeStreamOptions.builder().build())), User.class);
awaitSubscription(subscription1);
template.save(jellyBelly);
// cluster timestamp is in seconds, so we need to wait at least one.
Thread.sleep(1000);
template.save(sugarSplashy);
awaitMessages(messageListener1, 12);
Instant resumeAt = ((ChangeStreamEventMessage) messageListener1.getLastMessage()).getTimestamp();
template.save(huffyFluffy);
awaitMessages(messageListener1, 3);
CollectingMessageListener<ChangeStreamDocument<Document>, User> messageListener2 = new CollectingMessageListener<>();
ChangeStreamRequest<User> subSequentRequest = //
ChangeStreamRequest.builder().collection(//
"user").resumeAt(//
resumeAt).publishTo(//
messageListener2).maxAwaitTime(//
Duration.ofMillis(10)).build();
Subscription subscription2 = container.register(subSequentRequest, User.class);
awaitSubscription(subscription2);
awaitMessages(messageListener2, 2);
List<User> messageBodies = messageListener2.getMessages().stream().map(Message::getBody).collect(Collectors.toList());
assertThat(messageBodies).hasSize(2).doesNotContain(jellyBelly);
}
use of org.springframework.data.mongodb.core.messaging.ChangeStreamRequest.ChangeStreamRequestOptions in project spring-data-mongodb by spring-projects.
the class ChangeStreamTask method initCursor.
/*
* (non-Javadoc)
* @see org.springframework.data.mongodb.core.messaging.CursorReadingTask#initCursor(org.springframework.data.mongodb.core.MongoTemplate, org.springframework.data.mongodb.core.messaging.SubscriptionRequest.RequestOptions, java.lang.Class)
*/
@Override
protected MongoCursor<ChangeStreamDocument<Document>> initCursor(MongoTemplate template, RequestOptions options, Class<?> targetType) {
List<Document> filter = Collections.emptyList();
BsonDocument resumeToken = new BsonDocument();
Collation collation = null;
FullDocument fullDocument = ClassUtils.isAssignable(Document.class, targetType) ? FullDocument.DEFAULT : FullDocument.UPDATE_LOOKUP;
BsonTimestamp startAt = null;
boolean resumeAfter = true;
if (options instanceof ChangeStreamRequest.ChangeStreamRequestOptions) {
ChangeStreamOptions changeStreamOptions = ((ChangeStreamRequestOptions) options).getChangeStreamOptions();
filter = prepareFilter(template, changeStreamOptions);
if (changeStreamOptions.getFilter().isPresent()) {
Object val = changeStreamOptions.getFilter().get();
if (val instanceof Aggregation) {
collation = ((Aggregation) val).getOptions().getCollation().map(org.springframework.data.mongodb.core.query.Collation::toMongoCollation).orElse(null);
}
}
if (changeStreamOptions.getResumeToken().isPresent()) {
resumeToken = changeStreamOptions.getResumeToken().get().asDocument();
resumeAfter = changeStreamOptions.isResumeAfter();
}
fullDocument = changeStreamOptions.getFullDocumentLookup().orElseGet(() -> ClassUtils.isAssignable(Document.class, targetType) ? FullDocument.DEFAULT : FullDocument.UPDATE_LOOKUP);
startAt = changeStreamOptions.getResumeBsonTimestamp().orElse(null);
}
MongoDatabase db = StringUtils.hasText(options.getDatabaseName()) ? template.getMongoDbFactory().getMongoDatabase(options.getDatabaseName()) : template.getDb();
ChangeStreamIterable<Document> iterable;
if (StringUtils.hasText(options.getCollectionName())) {
iterable = filter.isEmpty() ? db.getCollection(options.getCollectionName()).watch(Document.class) : db.getCollection(options.getCollectionName()).watch(filter, Document.class);
} else {
iterable = filter.isEmpty() ? db.watch(Document.class) : db.watch(filter, Document.class);
}
if (!options.maxAwaitTime().isZero()) {
iterable = iterable.maxAwaitTime(options.maxAwaitTime().toMillis(), TimeUnit.MILLISECONDS);
}
if (!resumeToken.isEmpty()) {
if (resumeAfter) {
iterable = iterable.resumeAfter(resumeToken);
} else {
iterable = iterable.startAfter(resumeToken);
}
}
if (startAt != null) {
iterable.startAtOperationTime(startAt);
}
if (collation != null) {
iterable = iterable.collation(collation);
}
iterable = iterable.fullDocument(fullDocument);
return iterable.iterator();
}
Aggregations