|
8 | 8 | import io.axoniq.axonserver.connector.ResultStream; |
9 | 9 | import io.axoniq.axonserver.connector.ResultStreamPublisher; |
10 | 10 | import io.axoniq.axonserver.connector.event.DcbEventChannel; |
| 11 | +import io.axoniq.axonserver.connector.impl.HeaderAttachingInterceptor; |
| 12 | +import io.axoniq.axonserver.connector.impl.Headers; |
11 | 13 | import io.axoniq.axonserver.connector.impl.ServerAddress; |
| 14 | +import io.axoniq.axonserver.grpc.event.dcb.AddSnapshotRequest; |
12 | 15 | import io.axoniq.axonserver.grpc.event.dcb.AppendEventsResponse; |
13 | 16 | import io.axoniq.axonserver.grpc.event.dcb.ConsistencyCondition; |
14 | 17 | import io.axoniq.axonserver.grpc.event.dcb.Criterion; |
| 18 | +import io.axoniq.axonserver.grpc.event.dcb.DcbSnapshotStoreGrpc; |
15 | 19 | import io.axoniq.axonserver.grpc.event.dcb.Event; |
16 | 20 | import io.axoniq.axonserver.grpc.event.dcb.GetSequenceAtResponse; |
17 | 21 | import io.axoniq.axonserver.grpc.event.dcb.GetTagsResponse; |
18 | 22 | import io.axoniq.axonserver.grpc.event.dcb.GetTailResponse; |
| 23 | +import io.axoniq.axonserver.grpc.event.dcb.Snapshot; |
| 24 | +import io.axoniq.axonserver.grpc.event.dcb.SnapshottedSourceRequest; |
19 | 25 | import io.axoniq.axonserver.grpc.event.dcb.SourceEventsRequest; |
20 | 26 | import io.axoniq.axonserver.grpc.event.dcb.SourceEventsResponse; |
21 | 27 | import io.axoniq.axonserver.grpc.event.dcb.StreamEventsRequest; |
22 | 28 | import io.axoniq.axonserver.grpc.event.dcb.StreamEventsResponse; |
23 | 29 | import io.axoniq.axonserver.grpc.event.dcb.Tag; |
24 | 30 | import io.axoniq.axonserver.grpc.event.dcb.TaggedEvent; |
25 | 31 | import io.axoniq.axonserver.grpc.event.dcb.TagsAndNamesCriterion; |
| 32 | +import io.grpc.ManagedChannel; |
| 33 | +import io.grpc.ManagedChannelBuilder; |
26 | 34 | import org.junit.jupiter.api.*; |
27 | 35 | import org.slf4j.Logger; |
28 | 36 | import org.slf4j.LoggerFactory; |
@@ -401,6 +409,72 @@ void sourceSingleTagAndEventName() { |
401 | 409 | .verifyComplete(); |
402 | 410 | } |
403 | 411 |
|
| 412 | + @Test |
| 413 | + void sourceWithSnapshotWhenNoneStored() { |
| 414 | + DcbEventChannel dcbEventChannel = connection.dcbEventChannel(); |
| 415 | + Tag tag = aTag(); |
| 416 | + String eventName = aString(); |
| 417 | + |
| 418 | + long head = retrieveHead(); |
| 419 | + TaggedEvent taggedEvent = taggedEvent(anEvent(aString(), eventName), tag); |
| 420 | + appendEvent(taggedEvent); |
| 421 | + |
| 422 | + TagsAndNamesCriterion tagsAndName = TagsAndNamesCriterion.newBuilder().addTag(tag).addName(eventName).build(); |
| 423 | + Criterion criterion = Criterion.newBuilder().setTagsAndNames(tagsAndName).build(); |
| 424 | + SnapshottedSourceRequest request = SnapshottedSourceRequest.newBuilder() |
| 425 | + .setSnapshotKey(ByteString.copyFromUtf8(aString())) |
| 426 | + .addCriterion(criterion) |
| 427 | + .build(); |
| 428 | + |
| 429 | + StepVerifier.create(new ResultStreamPublisher<>(() -> dcbEventChannel.source(request))) |
| 430 | + .expectNextMatches( |
| 431 | + r -> !r.hasSnapshot() |
| 432 | + && r.getEvent().getEvent().equals(taggedEvent.getEvent()) |
| 433 | + && r.getEvent().getSequence() == head |
| 434 | + ) |
| 435 | + .expectNextMatches(r -> r.getConsistencyMarker() == head + 1L) |
| 436 | + .verifyComplete(); |
| 437 | + } |
| 438 | + |
| 439 | + @Test |
| 440 | + void sourceWithSnapshotWhenPresent() { |
| 441 | + DcbEventChannel dcbEventChannel = connection.dcbEventChannel(); |
| 442 | + Tag tag = aTag(); |
| 443 | + String eventName = aString(); |
| 444 | + ByteString snapshotKey = ByteString.copyFromUtf8(aString()); |
| 445 | + |
| 446 | + long head = retrieveHead(); |
| 447 | + TaggedEvent beforeSnapshot = taggedEvent(anEvent(aString(), eventName), tag); |
| 448 | + long snapshotSequence = appendEvent(beforeSnapshot).getSequenceOfTheFirstEvent(); |
| 449 | + |
| 450 | + Snapshot snapshot = Snapshot.newBuilder() |
| 451 | + .setName("snapshot-name") |
| 452 | + .setVersion("0.0.1") |
| 453 | + .setPayload(ByteString.copyFromUtf8("snapshot-payload")) |
| 454 | + .setTimestamp(Instant.now().toEpochMilli()) |
| 455 | + .build(); |
| 456 | + addSnapshot(snapshotKey, snapshotSequence, snapshot); |
| 457 | + |
| 458 | + TaggedEvent afterSnapshot = taggedEvent(anEvent(aString(), eventName), tag); |
| 459 | + appendEvent(afterSnapshot); |
| 460 | + |
| 461 | + TagsAndNamesCriterion tagsAndNames = TagsAndNamesCriterion.newBuilder().addTag(tag).addName(eventName).build(); |
| 462 | + Criterion criterion = Criterion.newBuilder().setTagsAndNames(tagsAndNames).build(); |
| 463 | + SnapshottedSourceRequest request = SnapshottedSourceRequest.newBuilder() |
| 464 | + .setSnapshotKey(snapshotKey) |
| 465 | + .addCriterion(criterion) |
| 466 | + .build(); |
| 467 | + |
| 468 | + StepVerifier.create(new ResultStreamPublisher<>(() -> dcbEventChannel.source(request))) |
| 469 | + .expectNextMatches(r -> r.hasSnapshot() && r.getSnapshot().equals(snapshot)) |
| 470 | + .expectNextMatches( |
| 471 | + r -> r.getEvent().getEvent().equals(afterSnapshot.getEvent()) |
| 472 | + && r.getEvent().getSequence() > snapshotSequence |
| 473 | + ) |
| 474 | + .expectNextMatches(r -> r.getConsistencyMarker() == head + 2L) |
| 475 | + .verifyComplete(); |
| 476 | + } |
| 477 | + |
404 | 478 | @Test |
405 | 479 | void noConditionAppend() { |
406 | 480 | long head = retrieveHead(); |
@@ -1034,6 +1108,24 @@ private long retrieveHead() { |
1034 | 1108 | .getSequence(); |
1035 | 1109 | } |
1036 | 1110 |
|
| 1111 | + private void addSnapshot(ByteString key, long sequence, Snapshot snapshot) { |
| 1112 | + ManagedChannel channel = |
| 1113 | + ManagedChannelBuilder.forAddress(axonServerAddress.getHostName(), axonServerAddress.getGrpcPort()) |
| 1114 | + .usePlaintext() |
| 1115 | + .intercept(new HeaderAttachingInterceptor<>(Headers.CONTEXT, "default")) |
| 1116 | + .build(); |
| 1117 | + try { |
| 1118 | + AddSnapshotRequest snapshotRequest = AddSnapshotRequest.newBuilder() |
| 1119 | + .setKey(key) |
| 1120 | + .setSequence(sequence) |
| 1121 | + .setSnapshot(snapshot) |
| 1122 | + .build(); |
| 1123 | + DcbSnapshotStoreGrpc.newBlockingStub(channel).add(snapshotRequest); |
| 1124 | + } finally { |
| 1125 | + channel.shutdownNow(); |
| 1126 | + } |
| 1127 | + } |
| 1128 | + |
1037 | 1129 | private AppendEventsResponse appendEvent(TaggedEvent taggedEvent) { |
1038 | 1130 | return appendEventAsync(taggedEvent).join(); |
1039 | 1131 | } |
|
0 commit comments