Repository navigation
add DCB event scheduler #441
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,20 +17,26 @@ | |
| package io.axoniq.axonserver.connector.event.impl; | ||
|
|
||
| import com.google.protobuf.Empty; | ||
| import io.axoniq.axonserver.connector.AxonServerException; | ||
| import io.axoniq.axonserver.connector.ErrorCategory; | ||
| import io.axoniq.axonserver.connector.ResultStream; | ||
| import io.axoniq.axonserver.connector.event.DcbEventChannel; | ||
| import io.axoniq.axonserver.connector.impl.AbstractAxonServerChannel; | ||
| import io.axoniq.axonserver.connector.impl.AbstractBufferedStream; | ||
| import io.axoniq.axonserver.connector.impl.AxonServerManagedChannel; | ||
| import io.axoniq.axonserver.connector.impl.FutureStreamObserver; | ||
| import io.axoniq.axonserver.grpc.FlowControl; | ||
| import io.axoniq.axonserver.grpc.InstructionAck; | ||
| import io.axoniq.axonserver.grpc.control.ClientIdentification; | ||
| import io.axoniq.axonserver.grpc.event.dcb.AddTagsRequest; | ||
| import io.axoniq.axonserver.grpc.event.dcb.AddTagsResponse; | ||
| import io.axoniq.axonserver.grpc.event.dcb.AppendEventsRequest; | ||
| import io.axoniq.axonserver.grpc.event.dcb.AppendEventsResponse; | ||
| import io.axoniq.axonserver.grpc.event.dcb.CancelScheduledEventRequest; | ||
| import io.axoniq.axonserver.grpc.event.dcb.ConsistencyCondition; | ||
| import io.axoniq.axonserver.grpc.event.dcb.DcbEventSchedulerGrpc; | ||
| import io.axoniq.axonserver.grpc.event.dcb.DcbEventStoreGrpc; | ||
| import io.axoniq.axonserver.grpc.event.dcb.Event; | ||
| import io.axoniq.axonserver.grpc.event.dcb.GetHeadRequest; | ||
| import io.axoniq.axonserver.grpc.event.dcb.GetHeadResponse; | ||
| import io.axoniq.axonserver.grpc.event.dcb.GetSequenceAtRequest; | ||
|
|
@@ -41,6 +47,9 @@ | |
| import io.axoniq.axonserver.grpc.event.dcb.GetTailResponse; | ||
| import io.axoniq.axonserver.grpc.event.dcb.RemoveTagsRequest; | ||
| import io.axoniq.axonserver.grpc.event.dcb.RemoveTagsResponse; | ||
| import io.axoniq.axonserver.grpc.event.dcb.RescheduleEventRequest; | ||
| import io.axoniq.axonserver.grpc.event.dcb.ScheduleEventRequest; | ||
| import io.axoniq.axonserver.grpc.event.dcb.ScheduleToken; | ||
| import io.axoniq.axonserver.grpc.event.dcb.SourceEventsRequest; | ||
| import io.axoniq.axonserver.grpc.event.dcb.SourceEventsResponse; | ||
| import io.axoniq.axonserver.grpc.event.dcb.StreamEventsRequest; | ||
|
|
@@ -50,8 +59,6 @@ | |
| import io.grpc.Status; | ||
| import io.grpc.StatusRuntimeException; | ||
| import io.grpc.stub.StreamObserver; | ||
| import org.slf4j.Logger; | ||
| import org.slf4j.LoggerFactory; | ||
|
|
||
| import java.time.Instant; | ||
| import java.util.Collection; | ||
|
|
@@ -60,6 +67,7 @@ | |
| import java.util.concurrent.ConcurrentHashMap; | ||
| import java.util.concurrent.ScheduledExecutorService; | ||
| import java.util.concurrent.atomic.AtomicBoolean; | ||
| import javax.annotation.Nullable; | ||
|
|
||
| /** | ||
| * {@link DcbEventChannel} implementation, serving as the event connection between Axon Server and a client | ||
|
|
@@ -70,11 +78,10 @@ | |
| */ | ||
| public class DcbEventChannelImpl extends AbstractAxonServerChannel<Void> implements DcbEventChannel { | ||
|
|
||
| private static final Logger LOGGER = LoggerFactory.getLogger(DcbEventChannelImpl.class); | ||
|
|
||
| private static final int BUFFER_SIZE = 512; | ||
| private static final int REFILL_BATCH = 16; | ||
| private final DcbEventStoreGrpc.DcbEventStoreStub eventStore; | ||
| private final DcbEventSchedulerGrpc.DcbEventSchedulerStub eventScheduler; | ||
| private final ClientIdentification clientIdentification; | ||
| private final Set<ResultStream<StreamEventsResponse>> buffers = ConcurrentHashMap.newKeySet(); | ||
|
|
||
|
|
@@ -90,6 +97,7 @@ public DcbEventChannelImpl(ClientIdentification clientIdentification, | |
| AxonServerManagedChannel axonServerManagedChannel) { | ||
| super(clientIdentification, executor, axonServerManagedChannel); | ||
| this.eventStore = DcbEventStoreGrpc.newStub(axonServerManagedChannel); | ||
| this.eventScheduler = DcbEventSchedulerGrpc.newStub(axonServerManagedChannel); | ||
| this.clientIdentification = clientIdentification; | ||
| } | ||
|
|
||
|
|
@@ -236,6 +244,53 @@ public CompletableFuture<RemoveTagsResponse> removeTags(long sequence, Collectio | |
| return future; | ||
| } | ||
|
|
||
| @Override | ||
| public CompletableFuture<String> scheduleEvent(Instant scheduleTime, Event event) { | ||
| FutureStreamObserver<ScheduleToken>responseObserver = new FutureStreamObserver<>(new AxonServerException( | ||
| ErrorCategory.INSTRUCTION_ACK_ERROR, | ||
| "An unknown error occurred while scheduling an Event. No response received from Server.", | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we receive no reponse from the server, would
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wouldn't some event scheduling error category make sense? |
||
| "" | ||
| )); | ||
|
|
||
| eventScheduler.scheduleEvent(ScheduleEventRequest.newBuilder() | ||
| .setEvent(event) | ||
| .setInstant(scheduleTime.toEpochMilli()) | ||
| .build(), responseObserver); | ||
| return responseObserver.thenApply(ScheduleToken::getToken); | ||
| } | ||
|
|
||
| @Override | ||
| public CompletableFuture<InstructionAck> cancelSchedule(String token) { | ||
| FutureStreamObserver<InstructionAck> responseObserver = new FutureStreamObserver<>(new AxonServerException( | ||
| ErrorCategory.INSTRUCTION_ACK_ERROR, | ||
| "An unknown error occurred while cancelling a scheduled Event. No response received from Server.", | ||
| "" | ||
| )); | ||
|
|
||
| eventScheduler.cancelScheduledEvent(CancelScheduledEventRequest.newBuilder().setToken(token).build(), | ||
| responseObserver); | ||
| return responseObserver; | ||
| } | ||
|
|
||
| @Override | ||
| public CompletableFuture<String> reschedule(String scheduleToken, Instant scheduleTime, @Nullable Event event) { | ||
| FutureStreamObserver<ScheduleToken>responseObserver = new FutureStreamObserver<>(new AxonServerException( | ||
| ErrorCategory.INSTRUCTION_ACK_ERROR, | ||
| "An unknown error occurred while rescheduling Event. No response received from Server.", | ||
| "" | ||
| )); | ||
|
|
||
| RescheduleEventRequest.Builder builder = RescheduleEventRequest.newBuilder() | ||
| .setToken(scheduleToken) | ||
| .setInstant(scheduleTime.toEpochMilli()); | ||
| if (event != null) { | ||
| builder.setEvent(event); | ||
| } | ||
| eventScheduler.rescheduleEvent(builder.build(), responseObserver); | ||
| return responseObserver.thenApply(ScheduleToken::getToken); | ||
| } | ||
|
|
||
|
|
||
| private static class AppendEventsTransactionImpl implements AppendEventsTransaction { | ||
|
|
||
| private final StreamObserver<AppendEventsRequest> stream; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: We can clarify the fact we are not requiring an
Eventby using@NonNulland@Nullableannotations on the parameters.