From 20b53d3bc28950be91b66a38b2cf867462cc370b Mon Sep 17 00:00:00 2001 From: wireknight Date: Sun, 11 Dec 2022 23:26:49 +0100 Subject: [PATCH 01/16] Reactor Context default name change --- .../io/reacted/core/reactors/ReActions.java | 2 +- .../core/reactors/systemreactors/Ask.java | 18 +-- .../reactors/systemreactors/DeadLetter.java | 6 +- .../reactors/systemreactors/RemotingRoot.java | 82 +++++------ .../reactors/systemreactors/SystemLogger.java | 6 +- .../systemreactors/SystemMonitor.java | 22 +-- .../core/reactorsystem/ReActorContext.java | 2 +- .../io/reacted/core/services/Service.java | 84 +++++------ .../io/reacted/core/utils/ReActedUtils.java | 8 +- .../zookeeper/ZooKeeperDriver.java | 138 +++++++++--------- .../apublish/MessageStormApp.java | 14 +- .../communication/ask/ReactiveClockApp.java | 2 +- .../tell/ping/SimpleTestReActor.java | 6 +- .../tell/pingpong/PingReActor.java | 10 +- .../tell/pingpong/PongReActor.java | 6 +- .../examples/httpserver/ReactiveServer.java | 72 ++++----- .../examples/quickstart/GreeterService.java | 8 +- .../quickstart/QuickstartSubscriber.java | 6 +- .../remoting/services/ClockReActor.java | 2 +- .../remoting/services/TimeReActor.java | 22 +-- .../services/ServicePublicationApp.java | 6 +- .../spawning/ReActorRelationsApp.java | 34 ++--- .../RemoteBroadcastingApp.java | 2 +- .../examples/webappbackend/ServerGate.java | 24 +-- .../webappbackend/db/DatabaseService.java | 22 +-- .../examples/webappbackend/handlers/Get.java | 30 ++-- .../examples/webappbackend/handlers/Post.java | 64 ++++---- .../java/io/reacted/flow/GraphController.java | 24 +-- .../reacted/flow/operators/FlowOperator.java | 68 ++++----- .../flow/operators/map/MapOperator.java | 2 +- .../operators/reduce/ReducingOperator.java | 2 +- .../operators/service/ServiceOperator.java | 42 +++--- .../reacted/streams/BackpressureManager.java | 44 +++--- .../streams/ReactedSubmissionPublisher.java | 34 ++--- .../streams/DistributedPublisherTest.java | 8 +- 35 files changed, 461 insertions(+), 461 deletions(-) diff --git a/core/src/main/java/io/reacted/core/reactors/ReActions.java b/core/src/main/java/io/reacted/core/reactors/ReActions.java index 6dba7056..586b7ba7 100644 --- a/core/src/main/java/io/reacted/core/reactors/ReActions.java +++ b/core/src/main/java/io/reacted/core/reactors/ReActions.java @@ -77,5 +77,5 @@ public ReActions build() { @SuppressWarnings("EmptyMethod") public static - void noReAction(ReActorContext raCtx, PayloadT payload) { /* No Reactions */ } + void noReAction(ReActorContext ctx, PayloadT payload) { /* No Reactions */ } } diff --git a/core/src/main/java/io/reacted/core/reactors/systemreactors/Ask.java b/core/src/main/java/io/reacted/core/reactors/systemreactors/Ask.java index 7caf9e8e..9747daeb 100644 --- a/core/src/main/java/io/reacted/core/reactors/systemreactors/Ask.java +++ b/core/src/main/java/io/reacted/core/reactors/systemreactors/Ask.java @@ -68,28 +68,28 @@ public ReActorConfig getConfig() { .build(); } - private void onInit(ReActorContext raCtx, ReActorInit init) { - if (!target.publish(raCtx.getSelf(), request).isSent()) { - raCtx.stop() + private void onInit(ReActorContext ctx, ReActorInit init) { + if (!target.publish(ctx.getSelf(), request).isSent()) { + ctx.stop() .thenAccept(noVal -> completionTrigger.completeExceptionally(new DeliveryException())); } else { - raCtx.getReActorSystem() + ctx.getReActorSystem() .getSystemSchedulingService() - .schedule(() -> raCtx.stop() + .schedule(() -> ctx.stop() .thenAccept(noVal -> completionTrigger.completeExceptionally(new TimeoutException())), askTimeout.toMillis(), TimeUnit.MILLISECONDS); } } - private void onExpectedReply(ReActorContext raCtx, ReplyT reply) { - raCtx.stop() + private void onExpectedReply(ReActorContext ctx, ReplyT reply) { + ctx.stop() .thenAccept(noVal -> completionTrigger.complete(reply)); } - private void onUnexpected(ReActorContext raCtx, Serializable anyType) { + private void onUnexpected(ReActorContext ctx, Serializable anyType) { var failure = new IllegalArgumentException(String.format("Received %s instead of %s", anyType.getClass().getName(), expectedReplyType.getName())); - raCtx.stop() + ctx.stop() .thenAccept(noVal -> completionTrigger.completeExceptionally(failure)); } } diff --git a/core/src/main/java/io/reacted/core/reactors/systemreactors/DeadLetter.java b/core/src/main/java/io/reacted/core/reactors/systemreactors/DeadLetter.java index 339f1817..424eb0a5 100644 --- a/core/src/main/java/io/reacted/core/reactors/systemreactors/DeadLetter.java +++ b/core/src/main/java/io/reacted/core/reactors/systemreactors/DeadLetter.java @@ -38,10 +38,10 @@ public class DeadLetter { private DeadLetter() { } private static - void onMessage(ReActorContext raCtx, PayloadT message) { + void onMessage(ReActorContext ctx, PayloadT message) { LOGGER.info("{} of {}: {} of type {} from {}", DeadLetter.class.getSimpleName(), - raCtx.getReActorSystem().getLocalReActorSystemId().getReActorSystemName(), message, message.getClass(), - raCtx.getSender()); + ctx.getReActorSystem().getLocalReActorSystemId().getReActorSystemName(), message, message.getClass(), + ctx.getSender()); RECEIVED.incrementAndGet(); } } diff --git a/core/src/main/java/io/reacted/core/reactors/systemreactors/RemotingRoot.java b/core/src/main/java/io/reacted/core/reactors/systemreactors/RemotingRoot.java index f031e78b..15a7e9ba 100644 --- a/core/src/main/java/io/reacted/core/reactors/systemreactors/RemotingRoot.java +++ b/core/src/main/java/io/reacted/core/reactors/systemreactors/RemotingRoot.java @@ -68,104 +68,104 @@ public ReActions getReActions() { .build(); } - private static void onDuplicatedPublicationError(ReActorContext raCtx, + private static void onDuplicatedPublicationError(ReActorContext ctx, DuplicatedPublicationError duplicatedPublicationError) { - raCtx.logError("CRITIC! Duplicated ReActor System detected. ReActorSystem names must be unique within" + + ctx.logError("CRITIC! Duplicated ReActor System detected. ReActorSystem names must be unique within" + " a cluster. Shutting down reporting driver: {}", - raCtx.getSender().getReActorId().getReActorName()); - raCtx.getReActorSystem().stop(raCtx.getSender().getReActorId()); + ctx.getSender().getReActorId().getReActorName()); + ctx.getReActorSystem().stop(ctx.getSender().getReActorId()); } @SuppressWarnings("EmptyMethod") - private static void onStop(ReActorContext raCtx, ReActorStop stop) { /* Nothing to do */ } + private static void onStop(ReActorContext ctx, ReActorStop stop) { /* Nothing to do */ } - private static void onCancelService(ReActorContext raCtx, + private static void onCancelService(ReActorContext ctx, ServiceCancellationRequest serviceCancellationRequest) { - raCtx.getChildren().forEach(serviceRegistryDriver -> serviceRegistryDriver.publish(raCtx.getSelf(), + ctx.getChildren().forEach(serviceRegistryDriver -> serviceRegistryDriver.publish(ctx.getSelf(), serviceCancellationRequest)); } - private static void onPublishService(ReActorContext raCtx, ServicePublicationRequest publishService) { - if (raCtx.getChildren().isEmpty()) { - if (!raCtx.reply(new ServiceRegistryNotAvailable()).isSent()) { - raCtx.logError("Unable to make a service discoverable {}", + private static void onPublishService(ReActorContext ctx, ServicePublicationRequest publishService) { + if (ctx.getChildren().isEmpty()) { + if (!ctx.reply(new ServiceRegistryNotAvailable()).isSent()) { + ctx.logError("Unable to make a service discoverable {}", publishService.getServiceProperties()); } return; } - raCtx.getChildren().stream() - .map(registryDriver -> registryDriver.publish(raCtx.getSelf(), publishService)) + ctx.getChildren().stream() + .map(registryDriver -> registryDriver.publish(ctx.getSelf(), publishService)) .filter(Predicate.not(DeliveryStatus::isSent)) - .forEach(registryDriver -> raCtx.logError("Unable to deliver service publication request {}", + .forEach(registryDriver -> ctx.logError("Unable to deliver service publication request {}", publishService.getServiceProperties())); } - private static void onInitComplete(ReActorContext raCtx, + private static void onInitComplete(ReActorContext ctx, RegistryDriverInitComplete initComplete) { - raCtx.reply(new SynchronizationWithServiceRegistryRequest()); + ctx.reply(new SynchronizationWithServiceRegistryRequest()); } - private static void onSpuriousMessage(ReActorContext raCtx, Serializable payload) { - raCtx.logError("Spurious message received", new IllegalStateException(payload.toString())); + private static void onSpuriousMessage(ReActorContext ctx, Serializable payload) { + ctx.logError("Spurious message received", new IllegalStateException(payload.toString())); } - private void onSubscriptionComplete(ReActorContext raCtx, + private void onSubscriptionComplete(ReActorContext ctx, SynchronizationWithServiceRegistryComplete subCompleted) { remotingDrivers.stream() .map(remotingDriver -> new ReActorSystemChannelIdPublicationRequest(localReActorSystem, remotingDriver.getChannelId(), remotingDriver.getChannelProperties())) - .map(raCtx::reply) + .map(ctx::reply) .filter(Predicate.not(DeliveryStatus::isSent)) - .forEach(pubRequest -> raCtx.logError("Unable to publish channel")); + .forEach(pubRequest -> ctx.logError("Unable to publish channel")); } - private static void onRegistryServicePublicationFailure(ReActorContext raCtx, + private static void onRegistryServicePublicationFailure(ReActorContext ctx, RegistryServicePublicationFailed failure) { - raCtx.logError("Error publishing service {}", failure.getServiceName(), failure.getPublicationError()); + ctx.logError("Error publishing service {}", failure.getServiceName(), failure.getPublicationError()); } - private void onRegistryGateUpsert(ReActorContext raCtx, RegistryGateUpserted upsert) { + private void onRegistryGateUpsert(ReActorContext ctx, RegistryGateUpserted upsert) { //skip self notifications - if (!raCtx.getReActorSystem().getLocalReActorSystemId().equals(upsert.getReActorSystemId())) { - raCtx.logInfo("Gate added in {} : {} -> {}", raCtx.getReActorSystem().getLocalReActorSystemId() + if (!ctx.getReActorSystem().getLocalReActorSystemId().equals(upsert.getReActorSystemId())) { + ctx.logInfo("Gate added in {} : {} -> {}", ctx.getReActorSystem().getLocalReActorSystemId() .getReActorSystemName(), upsert.getChannelId().toString(), upsert.getReActorSystemId().getReActorSystemName()); - raCtx.getReActorSystem().unregisterRoute(upsert.getReActorSystemId(), upsert.getChannelId()); - raCtx.getReActorSystem().registerNewRoute(upsert.getReActorSystemId(), upsert.getChannelId(), - upsert.getChannelData(), raCtx.getSender()); + ctx.getReActorSystem().unregisterRoute(upsert.getReActorSystemId(), upsert.getChannelId()); + ctx.getReActorSystem().registerNewRoute(upsert.getReActorSystemId(), upsert.getChannelId(), + upsert.getChannelData(), ctx.getSender()); } } - private void onRegistryConnectionLost(ReActorContext raCtx, RegistryConnectionLost connectionLost) { - raCtx.getReActorSystem().flushRemoteGatesForDriver(raCtx.getSender()); + private void onRegistryConnectionLost(ReActorContext ctx, RegistryConnectionLost connectionLost) { + ctx.getReActorSystem().flushRemoteGatesForDriver(ctx.getSender()); } - private void onRegistryGateRemoval(ReActorContext raCtx, RegistryGateRemoved removed) { - if (raCtx.getReActorSystem().getLocalReActorSystemId().equals(removed.getReActorSystem())) { + private void onRegistryGateRemoval(ReActorContext ctx, RegistryGateRemoved removed) { + if (ctx.getReActorSystem().getLocalReActorSystemId().equals(removed.getReActorSystem())) { //if for any reason we got removed from remove service registry, refresh subscription - raCtx.getSelf().publish(raCtx.getSender(), new SynchronizationWithServiceRegistryComplete()); + ctx.getSelf().publish(ctx.getSender(), new SynchronizationWithServiceRegistryComplete()); return; } - raCtx.logInfo("Gate removed in {} : {} -> {}", - raCtx.getReActorSystem().getLocalReActorSystemId().getReActorSystemName(), + ctx.logInfo("Gate removed in {} : {} -> {}", + ctx.getReActorSystem().getLocalReActorSystemId().getReActorSystemName(), removed.getChannelId().toString(), removed.getReActorSystem().getReActorSystemName()); - raCtx.getReActorSystem().unregisterRoute(removed.getReActorSystem(), removed.getChannelId()); + ctx.getReActorSystem().unregisterRoute(removed.getReActorSystem(), removed.getChannelId()); } - private static void onFilterServiceDiscoveryRequest(ReActorContext raCtx, + private static void onFilterServiceDiscoveryRequest(ReActorContext ctx, FilterServiceDiscoveryRequest filterThis) { var foundServices = filterThis.getServiceDiscoveryResult().stream() .flatMap(filterItem -> ReActorSystem.getRoutedReference(filterItem.serviceGate(), - raCtx.getReActorSystem()).stream() + ctx.getReActorSystem()).stream() .map(routedGate -> new FilterItem(routedGate, filterItem.serviceProperties()))) .filter(filterItem -> filterThis.getFilteringRuleToApply().matches(filterItem.serviceProperties(), filterItem.serviceGate())) .map(FilterItem::serviceGate) .collect(Collectors.toUnmodifiableSet()); - if (!raCtx.reply(new ServiceDiscoveryReply(foundServices)).isSent()) { - raCtx.logError("Unable to answer with a {}", + if (!ctx.reply(new ServiceDiscoveryReply(foundServices)).isSent()) { + ctx.logError("Unable to answer with a {}", ServiceDiscoveryReply.class.getSimpleName()); } } diff --git a/core/src/main/java/io/reacted/core/reactors/systemreactors/SystemLogger.java b/core/src/main/java/io/reacted/core/reactors/systemreactors/SystemLogger.java index 137b3f39..c36076f2 100644 --- a/core/src/main/java/io/reacted/core/reactors/systemreactors/SystemLogger.java +++ b/core/src/main/java/io/reacted/core/reactors/systemreactors/SystemLogger.java @@ -22,11 +22,11 @@ public class SystemLogger { private static final Logger LOGGER = LoggerFactory.getLogger(SystemLogger.class); public static final ReActions SYSTEM_LOGGER = ReActions.newBuilder() .reAct(ReActedError.class, - (raCtx, message) -> logMessage(LOGGER::error, message)) + (ctx, message) -> logMessage(LOGGER::error, message)) .reAct(ReActedDebug.class, - (raCtx, message) -> logMessage(LOGGER::debug, message)) + (ctx, message) -> logMessage(LOGGER::debug, message)) .reAct(ReActedInfo.class, - (raCtx, message) -> logMessage(LOGGER::info, message)) + (ctx, message) -> logMessage(LOGGER::info, message)) .reAct(ReActions::noReAction) .build(); diff --git a/core/src/main/java/io/reacted/core/reactors/systemreactors/SystemMonitor.java b/core/src/main/java/io/reacted/core/reactors/systemreactors/SystemMonitor.java index 6309c32e..2bb1be9c 100644 --- a/core/src/main/java/io/reacted/core/reactors/systemreactors/SystemMonitor.java +++ b/core/src/main/java/io/reacted/core/reactors/systemreactors/SystemMonitor.java @@ -47,17 +47,17 @@ public SystemMonitor(Duration taskPeriod, ScheduledExecutorService timerService) @Override public ReActions getReActions() { return ReActions.newBuilder() - .reAct(ReActorInit.class, (raCtx, init) -> onInit(raCtx)) - .reAct(ReActorStop.class, (raCtx, stop) -> onStop()) + .reAct(ReActorInit.class, (ctx, init) -> onInit(ctx)) + .reAct(ReActorStop.class, (ctx, stop) -> onStop()) .reAct(ReActions::noReAction) .build(); } - private void onInit(ReActorContext raCtx) { - this.timer = Try.of(() -> timerService.scheduleAtFixedRate(() -> broadcastStatistics(raCtx), + private void onInit(ReActorContext ctx) { + this.timer = Try.of(() -> timerService.scheduleAtFixedRate(() -> broadcastStatistics(ctx), 0, taskPeriod.toMillis(), TimeUnit.MILLISECONDS)) - .orElse(null, error -> initRetry(error, raCtx)); + .orElse(null, error -> initRetry(error, ctx)); } private void onStop() { @@ -66,12 +66,12 @@ private void onStop() { } } - private void broadcastStatistics(ReActorContext raCtx) { - Try.ofRunnable(() -> raCtx.getReActorSystem() + private void broadcastStatistics(ReActorContext ctx) { + Try.ofRunnable(() -> ctx.getReActorSystem() .broadcastToLocalSubscribers(ReActorRef.NO_REACTOR_REF, getSystemStatistics( systemDataSource))) - .ifError(error -> raCtx.logError("Unable to broadcast statistics update", error)); + .ifError(error -> ctx.logError("Unable to broadcast statistics update", error)); } /* @@ -84,9 +84,9 @@ private static SystemMonitorReport getSystemStatistics(OperatingSystemMXBean sys .build(); } - private static void initRetry(Throwable error, ReActorContext raCtx) { - raCtx.logError("Unable to init {} reattempting", + private static void initRetry(Throwable error, ReActorContext ctx) { + ctx.logError("Unable to init {} reattempting", SystemMonitor.class.getSimpleName(), error); - raCtx.selfPublish(new ReActorInit()); + ctx.selfPublish(new ReActorInit()); } } diff --git a/core/src/main/java/io/reacted/core/reactorsystem/ReActorContext.java b/core/src/main/java/io/reacted/core/reactorsystem/ReActorContext.java index 59a01744..60f32e54 100644 --- a/core/src/main/java/io/reacted/core/reactorsystem/ReActorContext.java +++ b/core/src/main/java/io/reacted/core/reactorsystem/ReActorContext.java @@ -43,7 +43,7 @@ @NonNullByDefault public class ReActorContext { public static final ReActorContext NO_REACTOR_CTX = ReActorContext.newBuilder() - .setMbox(raCtx -> new NullMailbox()) + .setMbox(ctx -> new NullMailbox()) .setParentActor(ReActorRef.NO_REACTOR_REF) .setReactorRef(ReActorRef.NO_REACTOR_REF) .setReActions(ReActions.NO_REACTIONS) diff --git a/core/src/main/java/io/reacted/core/services/Service.java b/core/src/main/java/io/reacted/core/services/Service.java index 6a395a61..2b7642a0 100644 --- a/core/src/main/java/io/reacted/core/services/Service.java +++ b/core/src/main/java/io/reacted/core/services/Service.java @@ -69,7 +69,7 @@ public Service(ServiceCfgT serviceConfig) { @Nonnull public ReActions getReActions() { return ReActions.newBuilder() - .reAct((raCtx, message) -> requestNextMessage(raCtx, message, this::routeMessage)) + .reAct((ctx, message) -> requestNextMessage(ctx, message, this::routeMessage)) .reAct(ServiceRegistryNotAvailable.class, this::onServiceRegistryNotAvailable) .reAct(ServiceDiscoveryRequest.class, this::serviceDiscovery) .reAct(RouteeReSpawnRequest.class, this::respawnRoutee) @@ -80,47 +80,47 @@ public ReActions getReActions() { .build(); } - private void onServiceRegistryNotAvailable(ReActorContext raCtx, + private void onServiceRegistryNotAvailable(ReActorContext ctx, ServiceRegistryNotAvailable notAvailable) { - raCtx.logInfo("{} makes itself locally discoverable", + ctx.logInfo("{} makes itself locally discoverable", serviceInfo.getProperty(ServiceDiscoverySearchFilter.FIELD_NAME_SERVICE_NAME)); - raCtx.addTypedSubscriptions(TypedSubscription.LOCAL.forType(ServiceDiscoveryRequest.class)); + ctx.addTypedSubscriptions(TypedSubscription.LOCAL.forType(ServiceDiscoveryRequest.class)); } - public void onServicePublicationError(ReActorContext raCtx, ServicePublicationRequestError error) { + public void onServicePublicationError(ReActorContext ctx, ServicePublicationRequestError error) { if (!serviceConfig.isRemoteService()) { return; } - Try.of(() -> raCtx.getReActorSystem() + Try.of(() -> ctx.getReActorSystem() .getSystemSchedulingService() - .schedule(() -> sendPublicationRequest(raCtx, serviceInfo), + .schedule(() -> sendPublicationRequest(ctx, serviceInfo), serviceConfig.getServiceRepublishReattemptDelayOnError().toMillis(), TimeUnit.MILLISECONDS)) - .peekFailure(failure -> raCtx.logError("Unable to reschedule service publication", failure)) - .ifError(failure -> raCtx.getSelf().publish(raCtx.getSender(), error)); + .peekFailure(failure -> ctx.logError("Unable to reschedule service publication", failure)) + .ifError(failure -> ctx.getSelf().publish(ctx.getSender(), error)); } List getRouteesMap() { return routeesMap; } - private void onSystemInfoReport(ReActorContext raCtx, SystemMonitorReport report) { + private void onSystemInfoReport(ReActorContext ctx, SystemMonitorReport report) { serviceInfo.put(ServiceDiscoverySearchFilter.FIELD_NAME_CPU_LOAD, report.getCpuLoad()); serviceInfo.put(ServiceDiscoverySearchFilter.FIELD_NAME_FREE_MEMORY_SIZE, report.getFreeMemorySize()); - updateServiceRegistry(raCtx, serviceInfo); + updateServiceRegistry(ctx, serviceInfo); } - private void stopService(ReActorContext raCtx, ReActorStop stop) { - raCtx.getReActorSystem() + private void stopService(ReActorContext ctx, ReActorStop stop) { + ctx.getReActorSystem() .getSystemRemotingRoot() - .publish(raCtx.getSelf(), new ServiceCancellationRequest(raCtx.getReActorSystem().getLocalReActorSystemId(), + .publish(ctx.getSelf(), new ServiceCancellationRequest(ctx.getReActorSystem().getLocalReActorSystemId(), serviceConfig.getReActorName())); } - private void initService(ReActorContext raCtx, ReActorInit reActorInit) { + private void initService(ReActorContext ctx, ReActorInit reActorInit) { //All the services can receive service stats - raCtx.addTypedSubscriptions(TypedSubscription.LOCAL.forType(SystemMonitorReport.class)); + ctx.addTypedSubscriptions(TypedSubscription.LOCAL.forType(SystemMonitorReport.class)); - var backpressuringMbox = BackpressuringMbox.toBackpressuringMailbox(raCtx.getMbox()); + var backpressuringMbox = BackpressuringMbox.toBackpressuringMailbox(ctx.getMbox()); backpressuringMbox.filter(mbox -> !mbox.isDelayable(ReActorInit.class)) .ifPresent(mbox -> mbox.request(1)); backpressuringMbox.ifPresent(mbox -> mbox.addNonDelayableTypes(getNonDelayedMessageTypes())); @@ -139,35 +139,35 @@ private void initService(ReActorContext raCtx, ReActorInit reActorInit) { ReActorConfig newRouteeCfg = ReActorConfig.fromConfig(routeeConfig) .setReActorName(routeeNewName) .build(); - this.routeesMap.add(spawnRoutee(raCtx, routeeReActions, newRouteeCfg)); + this.routeesMap.add(spawnRoutee(ctx, routeeReActions, newRouteeCfg)); } catch (Throwable routeeSpawnError) { - raCtx.logError(ROUTEE_SPAWN_ERROR, routeeSpawnError); + ctx.logError(ROUTEE_SPAWN_ERROR, routeeSpawnError); } } if (serviceConfig.isRemoteService()) { - sendPublicationRequest(raCtx, serviceInfo); + sendPublicationRequest(ctx, serviceInfo); } } - private void serviceDiscovery(ReActorContext raCtx, ServiceDiscoveryRequest request) { - if (!request.getSearchFilter().matches(serviceInfo, raCtx.getSelf())) { + private void serviceDiscovery(ReActorContext ctx, ServiceDiscoveryRequest request) { + if (!request.getSearchFilter().matches(serviceInfo, ctx.getSelf())) { return; } ReActorRef serviceSelection = request.getSearchFilter() .getSelectionType() == SelectionType.ROUTED - ? raCtx.getSelf() - : selectRoutee(raCtx, msgReceived, request); + ? ctx.getSelf() + : selectRoutee(ctx, msgReceived, request); if (serviceSelection != null) { - raCtx.reply(raCtx.getSelf(), new ServiceDiscoveryReply(serviceSelection)); + ctx.reply(ctx.getSelf(), new ServiceDiscoveryReply(serviceSelection)); } } - private DeliveryStatus routeMessage(ReActorContext raCtx, + private DeliveryStatus routeMessage(ReActorContext ctx, Serializable newMessage) { - ReActorRef routee = selectRoutee(raCtx, ++msgReceived, newMessage); + ReActorRef routee = selectRoutee(ctx, ++msgReceived, newMessage); return routee != null - ? routee.tell(raCtx.getSender(), newMessage) + ? routee.tell(ctx.getSender(), newMessage) : DeliveryStatus.NOT_SENT; } @@ -177,15 +177,15 @@ private ReActorRef selectRoutee(ReActorContext routerCtx, long msgReceived, return serviceConfig.getLoadBalancingPolicy() .selectRoutee(routerCtx, this, msgReceived, message); } - private void respawnRoutee(ReActorContext raCtx, RouteeReSpawnRequest reSpawnRequest) { + private void respawnRoutee(ReActorContext ctx, RouteeReSpawnRequest reSpawnRequest) { this.routeesMap.remove(reSpawnRequest.deadRoutee); Try.of(() -> Objects.requireNonNull(serviceConfig.getRouteeProvider() .apply(serviceConfig))) - .map(routee -> spawnRoutee(raCtx, routee.getReActions(), + .map(routee -> spawnRoutee(ctx, routee.getReActions(), ReActorConfig.fromConfig(routee.getConfig()) .setReActorName(reSpawnRequest.routeeName) .build())) - .ifSuccessOrElse(this.routeesMap::add, spawnError -> raCtx.logError(ROUTEE_SPAWN_ERROR, + .ifSuccessOrElse(this.routeesMap::add, spawnError -> ctx.logError(ROUTEE_SPAWN_ERROR, spawnError)); } @@ -209,32 +209,32 @@ private ReActorRef spawnRoutee(ReActorContext routerCtx, ReActions routeeReActio return routee; } - private void updateServiceRegistry(ReActorContext raCtx, Properties serviceInfo) { + private void updateServiceRegistry(ReActorContext ctx, Properties serviceInfo) { if (!serviceConfig.isRemoteService()) { return; } - if (!sendPublicationRequest(raCtx, serviceInfo).isSent()) { - raCtx.logError("Unable to refresh service info {}", + if (!sendPublicationRequest(ctx, serviceInfo).isSent()) { + ctx.logError("Unable to refresh service info {}", serviceInfo.getProperty(ServiceDiscoverySearchFilter.FIELD_NAME_SERVICE_NAME)); } } - private static DeliveryStatus sendPublicationRequest(ReActorContext raCtx, + private static DeliveryStatus sendPublicationRequest(ReActorContext ctx, Properties serviceInfo) { - return raCtx.getReActorSystem() + return ctx.getReActorSystem() .getSystemRemotingRoot() - .publish(raCtx.getSelf(), new ServicePublicationRequest(raCtx.getSelf(), serviceInfo)); + .publish(ctx.getSelf(), new ServicePublicationRequest(ctx.getSelf(), serviceInfo)); } private static - void requestNextMessage(ReActorContext raCtx, PayloadT payload, + void requestNextMessage(ReActorContext ctx, PayloadT payload, BiFunction realCall) { - if (realCall.apply(raCtx, payload).isNotSent()) { - raCtx.getReActorSystem().toDeadLetters(raCtx.getSender(), payload); - raCtx.logError(NO_ROUTEE_FOR_SPECIFIED_ROUTER, raCtx.getSelf().getReActorId().getReActorName()); + if (realCall.apply(ctx, payload).isNotSent()) { + ctx.getReActorSystem().toDeadLetters(ctx.getSender(), payload); + ctx.logError(NO_ROUTEE_FOR_SPECIFIED_ROUTER, ctx.getSelf().getReActorId().getReActorName()); } - raCtx.getMbox().request(1); + ctx.getMbox().request(1); } //Messages required for the Service management logic cannot be backpressured diff --git a/core/src/main/java/io/reacted/core/utils/ReActedUtils.java b/core/src/main/java/io/reacted/core/utils/ReActedUtils.java index d1dc9276..ea32a163 100644 --- a/core/src/main/java/io/reacted/core/utils/ReActedUtils.java +++ b/core/src/main/java/io/reacted/core/utils/ReActedUtils.java @@ -73,18 +73,18 @@ private ReActedUtils() { /* No Implementation required */ } public static void rescheduleIf(BiConsumer realCall, BooleanSupplier shouldReschedule, Duration rescheduleInterval, - ReActorContext raCtx, PayloadT message) { + ReActorContext ctx, PayloadT message) { if (shouldReschedule.getAsBoolean()) { - raCtx.rescheduleMessage(message, rescheduleInterval) - .ifError(error -> raCtx.logError("WARNING {} misbehaves. Error attempting a {} " + + ctx.rescheduleMessage(message, rescheduleInterval) + .ifError(error -> ctx.logError("WARNING {} misbehaves. Error attempting a {} " + "reschedulation. " + "System remoting may become unreliable ", realCall.toString(), message.getClass().getSimpleName(), error)); } else { - realCall.accept(raCtx, message); + realCall.accept(ctx, message); } } } diff --git a/drivers/src/main/java/io/reacted/drivers/serviceregistries/zookeeper/ZooKeeperDriver.java b/drivers/src/main/java/io/reacted/drivers/serviceregistries/zookeeper/ZooKeeperDriver.java index 83b7c3a4..bf68f3d6 100644 --- a/drivers/src/main/java/io/reacted/drivers/serviceregistries/zookeeper/ZooKeeperDriver.java +++ b/drivers/src/main/java/io/reacted/drivers/serviceregistries/zookeeper/ZooKeeperDriver.java @@ -126,83 +126,83 @@ public boolean equals(Object o) { public ReActions getReActions() { return ReActions.newBuilder() .reAct(ReActorInit.class, this::onInit) - .reAct(ReActorStop.class, (raCtx, stop) -> onStop(raCtx)) + .reAct(ReActorStop.class, (ctx, stop) -> onStop(ctx)) .reAct(ZooKeeperRootPathsCreated.class, this::onRootPathsCreated) .reAct(ReActorSystemChannelIdPublicationRequest.class, - (raCtx, systemPubRequest) -> ReActedUtils.rescheduleIf(this::onChannelIdPublicationRequest, + (ctx, systemPubRequest) -> ReActedUtils.rescheduleIf(this::onChannelIdPublicationRequest, this::isCuratorClientMissing, getConfig().getReconnectionDelay(), - raCtx, systemPubRequest)) + ctx, systemPubRequest)) .reAct(ReActorSystemChannelIdCancellationRequest.class, - (raCtx, cancRequest) -> ReActedUtils.rescheduleIf(this::onChannelIdCancellationRequest, + (ctx, cancRequest) -> ReActedUtils.rescheduleIf(this::onChannelIdCancellationRequest, this::isServiceDiscoveryClientMissing, getConfig().getReconnectionDelay(), - raCtx, cancRequest)) + ctx, cancRequest)) .reAct(SynchronizationWithServiceRegistryRequest.class, - (raCtx, syncRequest) -> ReActedUtils.rescheduleIf(this::onSynchronizationWithRegistryRequest, + (ctx, syncRequest) -> ReActedUtils.rescheduleIf(this::onSynchronizationWithRegistryRequest, this::isCuratorClientMissing, getConfig().getReconnectionDelay(), - raCtx, syncRequest)) + ctx, syncRequest)) .reAct(ServicePublicationRequest.class, - (raCtx, servicePubRequest) -> ReActedUtils.rescheduleIf(this::onServicePublicationRequest, + (ctx, servicePubRequest) -> ReActedUtils.rescheduleIf(this::onServicePublicationRequest, this::isServiceDiscoveryClientMissing, getConfig().getReconnectionDelay(), - raCtx, servicePubRequest)) + ctx, servicePubRequest)) .reAct(ServiceCancellationRequest.class, - (raCtx, serviceCancRequest) -> ReActedUtils.rescheduleIf(this::onServiceCancellationRequest, + (ctx, serviceCancRequest) -> ReActedUtils.rescheduleIf(this::onServiceCancellationRequest, this::isServiceDiscoveryClientMissing, getConfig().getReconnectionDelay(), - raCtx, serviceCancRequest)) + ctx, serviceCancRequest)) .reAct(ServiceDiscoveryRequest.class, - (raCtx, serviceDiscoveryRequest) -> ReActedUtils.rescheduleIf(this::onServiceDiscovery, + (ctx, serviceDiscoveryRequest) -> ReActedUtils.rescheduleIf(this::onServiceDiscovery, this::isServiceDiscoveryClientMissing, getConfig().getReconnectionDelay(), - raCtx, serviceDiscoveryRequest)) + ctx, serviceDiscoveryRequest)) .reAct(ZooKeeperDriver::onSpuriousMessage) .build(); } - private void onServiceCancellationRequest(ReActorContext raCtx, ServiceCancellationRequest cancellationRequest) { + private void onServiceCancellationRequest(ReActorContext ctx, ServiceCancellationRequest cancellationRequest) { runAsync(() -> getServiceInstance(cancellationRequest.getServiceName(), - raCtx.getReActorSystem().getLocalReActorSystemId(), + ctx.getReActorSystem().getLocalReActorSystemId(), (ServicePublicationRequest)null) .ifSuccessOrElse(Objects.requireNonNull(this.serviceDiscovery)::unregisterService, - error -> raCtx.logError("Unable to unregister service {}", + error -> ctx.logError("Unable to unregister service {}", cancellationRequest.toString(), error))); } - private void onServicePublicationRequest(ReActorContext raCtx, ServicePublicationRequest serviceInfo) { + private void onServicePublicationRequest(ReActorContext ctx, ServicePublicationRequest serviceInfo) { String serviceName = serviceInfo.getServiceProperties() .getProperty(ServiceDiscoverySearchFilter.FIELD_NAME_SERVICE_NAME); if (StringUtils.isBlank(serviceName)) { - raCtx.logError("Skipping publication attempt of an invalid service name {}", serviceName); - raCtx.reply(new RegistryServicePublicationFailed(serviceName, + ctx.logError("Skipping publication attempt of an invalid service name {}", serviceName); + ctx.reply(new RegistryServicePublicationFailed(serviceName, new IllegalArgumentException("Invalid name: blank"))); return; } - runAsync(() -> getServiceInstance(serviceName, raCtx.getReActorSystem() + runAsync(() -> getServiceInstance(serviceName, ctx.getReActorSystem() .getLocalReActorSystemId(), serviceInfo) .ifSuccess(Objects.requireNonNull(this.serviceDiscovery)::registerService) - .ifSuccessOrElse(noVal -> raCtx.logInfo("Service {} published", + .ifSuccessOrElse(noVal -> ctx.logInfo("Service {} published", serviceInfo.getServiceProperties() .getProperty(ServiceDiscoverySearchFilter.FIELD_NAME_SERVICE_NAME)), - registeringError -> raCtx.reply(new RegistryServicePublicationFailed(serviceName, + registeringError -> ctx.reply(new RegistryServicePublicationFailed(serviceName, registeringError)))); } - private void onServiceDiscovery(ReActorContext raCtx, ServiceDiscoveryRequest request) { - ReActorRef discoveryRequester = raCtx.getSender(); - runAsync(() -> queryZooKeeper(raCtx, Objects.requireNonNull(this.serviceDiscovery), request.getSearchFilter())) - .thenAccept(filterItemSet -> raCtx.getReActorSystem().getSystemRemotingRoot() + private void onServiceDiscovery(ReActorContext ctx, ServiceDiscoveryRequest request) { + ReActorRef discoveryRequester = ctx.getSender(); + runAsync(() -> queryZooKeeper(ctx, Objects.requireNonNull(this.serviceDiscovery), request.getSearchFilter())) + .thenAccept(filterItemSet -> ctx.getReActorSystem().getSystemRemotingRoot() .publish(discoveryRequester, new FilterServiceDiscoveryRequest(request.getSearchFilter(), filterItemSet))); } - private static Set queryZooKeeper(ReActorContext raCtx, + private static Set queryZooKeeper(ReActorContext ctx, ServiceDiscovery synchronousServiceDiscovery, ServiceDiscoverySearchFilter serviceFilter) { var nameMatchingServices = Try.of(() -> synchronousServiceDiscovery.queryForInstances(serviceFilter.getServiceName())) - .orElse(List.of(), error -> raCtx.logError("Error discovering service {}", + .orElse(List.of(), error -> ctx.logError("Error discovering service {}", serviceFilter.getServiceName(), error)); return nameMatchingServices.stream() .map(serviceInstance -> new FilterItem(serviceInstance.getPayload().getServiceGate(), @@ -212,7 +212,7 @@ private static Set queryZooKeeper(ReActorContext raCtx, .collect(Collectors.toUnmodifiableSet()); } - private void onChannelIdCancellationRequest(ReActorContext raCtx, + private void onChannelIdCancellationRequest(ReActorContext ctx, ReActorSystemChannelIdCancellationRequest cancelRequest) { Objects.requireNonNull(asyncClient) .delete() @@ -220,7 +220,7 @@ private void onChannelIdCancellationRequest(ReActorContext raCtx, cancelRequest.getChannelId())); } - private void onChannelIdPublicationRequest(ReActorContext raCtx, + private void onChannelIdPublicationRequest(ReActorContext ctx, ReActorSystemChannelIdPublicationRequest pubRequest) { try { createPathIfRequired(Objects.requireNonNull(asyncClient), @@ -231,68 +231,68 @@ private void onChannelIdPublicationRequest(ReActorContext raCtx, ObjectUtils.toBytes(pubRequest.getChannelIdData())) .toCompletableFuture() .exceptionally(encodeError -> { - raCtx.logError("Permanent error, unable to encode channel properties {}", + ctx.logError("Permanent error, unable to encode channel properties {}", pubRequest.getChannelIdData(), encodeError); return false; }); } catch (IOException serializationError) { - raCtx.logError("Unable to serialize gate properties {}", pubRequest.getChannelId(), serializationError); + ctx.logError("Unable to serialize gate properties {}", pubRequest.getChannelId(), serializationError); } } - private void onSynchronizationWithRegistryRequest(ReActorContext raCtx, + private void onSynchronizationWithRegistryRequest(ReActorContext ctx, SynchronizationWithServiceRegistryRequest subRequest) { CompletableFuture cacheStarted = CompletableFuture.completedFuture(null); if (curatorCache == null) { this.curatorCache = CuratorCache.builder(Objects.requireNonNull(asyncClient).unwrap(), REACTED_CLUSTER_ROOT) - .withExceptionHandler(error -> raCtx.logError("ZooKeeper Cache error", + .withExceptionHandler(error -> ctx.logError("ZooKeeper Cache error", error)) .build(); Objects.requireNonNull(curatorCache).listenable() .addListener(CuratorCacheListener.builder() .forTreeCache(Objects.requireNonNull(asyncClient).unwrap(), - getTreeListener(raCtx.getReActorSystem(), - raCtx.getSelf())) + getTreeListener(ctx.getReActorSystem(), + ctx.getSelf())) .build(), getConfig().getAsyncExecutionService()); cacheStarted = runAsync(() -> Objects.requireNonNull(curatorCache).start()); } - cacheStarted.thenAccept(noVal -> raCtx.getReActorSystem() + cacheStarted.thenAccept(noVal -> ctx.getReActorSystem() .getSystemRemotingRoot() - .publish(raCtx.getSelf(), new SynchronizationWithServiceRegistryComplete())); + .publish(ctx.getSelf(), new SynchronizationWithServiceRegistryComplete())); } - private void onStop(ReActorContext raCtx) { + private void onStop(ReActorContext ctx) { Try.ofRunnable(this::shutdownZookeeperConnection) - .ifError(error -> raCtx.logError("Error stopping service registry", error)); - raCtx.getReActorSystem().getSystemRemotingRoot() - .publish(raCtx.getSelf(), new RegistryConnectionLost()); + .ifError(error -> ctx.logError("Error stopping service registry", error)); + ctx.getReActorSystem().getSystemRemotingRoot() + .publish(ctx.getSelf(), new RegistryConnectionLost()); } - private void onInit(ReActorContext raCtx, ReActorInit init) { + private void onInit(ReActorContext ctx, ReActorInit init) { if (asyncClient == null) { - this.asyncClient = createCuratorAsyncClient(raCtx); + this.asyncClient = createCuratorAsyncClient(ctx); } asyncClient.unwrap().start(); try { asyncClient.unwrap().blockUntilConnected(); } catch (InterruptedException interruptedException) { Thread.currentThread().interrupt(); - raCtx.stop(); + ctx.stop(); return; } CompletableFuture.allOf(createPathIfRequired(asyncClient, CreateMode.PERSISTENT, REACTOR_SYSTEMS_PATH, NO_PAYLOAD), createPathIfRequired(asyncClient, CreateMode.PERSISTENT, SERVICES_PATH, NO_PAYLOAD), createPathIfRequired(asyncClient, CreateMode.PERSISTENT, REACTOR_SYSTEMS_GATES_PATH, NO_PAYLOAD)) - .thenAccept(pathCreated -> raCtx.selfPublish(new ZooKeeperRootPathsCreated())) + .thenAccept(pathCreated -> ctx.selfPublish(new ZooKeeperRootPathsCreated())) .exceptionally(initError -> { - raCtx.logError("Unable to init {} ", ZooKeeperDriver.class.getSimpleName(), initError); - raCtx.rescheduleMessage(init, getConfig().getReconnectionDelay()); + ctx.logError("Unable to init {} ", ZooKeeperDriver.class.getSimpleName(), initError); + ctx.rescheduleMessage(init, getConfig().getReconnectionDelay()); return null; }); } - private AsyncCuratorFramework createCuratorAsyncClient(ReActorContext raCtx) { + private AsyncCuratorFramework createCuratorAsyncClient(ReActorContext ctx) { var retryPolicy = new ExponentialBackoffRetry((int) getConfig().getReconnectionDelay().toMillis(), getConfig().getMaxReconnectionAttempts()); int sessionTimeout = (int)getConfig().getSessionTimeout().toMillis(); @@ -300,22 +300,22 @@ private AsyncCuratorFramework createCuratorAsyncClient(ReActorContext raCtx) { var curatorClient = CuratorFrameworkFactory.newClient(getConfig().getConnectionString(), sessionTimeout, connectionTimeout, retryPolicy); curatorClient.getConnectionStateListenable() - .addListener((curator, newState) -> onConnectionStateChange(raCtx, curator, curatorCache, + .addListener((curator, newState) -> onConnectionStateChange(ctx, curator, curatorCache, newState, reActorSystemInstanceMarker), getConfig().getAsyncExecutionService()); return AsyncCuratorFramework.wrap(curatorClient); } - private void onRootPathsCreated(ReActorContext raCtx, ZooKeeperRootPathsCreated created) { - isReActorSystemUnique(raCtx.getReActorSystem().getLocalReActorSystemId(), + private void onRootPathsCreated(ReActorContext ctx, ZooKeeperRootPathsCreated created) { + isReActorSystemUnique(ctx.getReActorSystem().getLocalReActorSystemId(), Objects.requireNonNull(asyncClient), reActorSystemInstanceMarker) .thenApply(isUnique -> isUnique ? serviceDiscovery == null - ? setupServiceDiscovery(raCtx) - : raCtx.getReActorSystem().getSystemRemotingRoot().publish(raCtx.getSelf(), + ? setupServiceDiscovery(ctx) + : ctx.getReActorSystem().getSystemRemotingRoot().publish(ctx.getSelf(), new RegistryDriverInitComplete()) - : onDuplicateReactorSystem(raCtx)); + : onDuplicateReactorSystem(ctx)); } @@ -356,21 +356,21 @@ private static boolean isThisInstanceMarker(@Nullable byte[] remoteMarkerData, .map(reActorSystemInstanceMarker::equals) .orElse(false); } - private CompletionStage setupServiceDiscovery(ReActorContext raCtx) { + private CompletionStage setupServiceDiscovery(ReActorContext ctx) { return runAsync(() -> ServiceDiscoveryBuilder.builder(ServicePublicationRequest.class) .basePath(SERVICES_PATH) .client(Objects.requireNonNull(asyncClient).unwrap()) .build()) .thenAccept(serviceDiscovery -> this.serviceDiscovery = serviceDiscovery) .thenAccept(noVal -> UnChecked.runnable(serviceDiscovery::start).run()) - .thenApply(noVal -> raCtx.getReActorSystem() + .thenApply(noVal -> ctx.getReActorSystem() .getSystemRemotingRoot() - .publish(raCtx.getSelf(), new RegistryDriverInitComplete())); + .publish(ctx.getSelf(), new RegistryDriverInitComplete())); } - private static DeliveryStatus onDuplicateReactorSystem(ReActorContext raCtx) { - return raCtx.getReActorSystem() + private static DeliveryStatus onDuplicateReactorSystem(ReActorContext ctx) { + return ctx.getReActorSystem() .getSystemRemotingRoot() - .publish(raCtx.getSelf(), new DuplicatedPublicationError()); + .publish(ctx.getSelf(), new DuplicatedPublicationError()); } private boolean isCuratorClientMissing() { return asyncClient == null; } @@ -398,8 +398,8 @@ private CompletableFuture createPathIfRequired(AsyncCuratorFramework as .exceptionally(NodeExistsException.class::isInstance); } - private static void onSpuriousMessage(ReActorContext raCtx, Object message) { - raCtx.logError("Unrecognized message received in {}", ZooKeeperDriver.class.getSimpleName(), + private static void onSpuriousMessage(ReActorContext ctx, Object message) { + ctx.logError("Unrecognized message received in {}", ZooKeeperDriver.class.getSimpleName(), new IllegalStateException(message.toString())); } @@ -473,21 +473,21 @@ private static DeliveryStatus upsertGate(ReActorSystem reActorSystem, ReActorRef .orElse(DeliveryStatus.NOT_DELIVERED); } - private void onConnectionStateChange(ReActorContext raCtx, CuratorFramework curator, + private void onConnectionStateChange(ReActorContext ctx, CuratorFramework curator, @Nullable CuratorCache curatorCache, ConnectionState newState, UUID reActorSystemInstanceMarker) { switch (newState) { - case LOST, SUSPENDED -> raCtx.getReActorSystem() + case LOST, SUSPENDED -> ctx.getReActorSystem() .getSystemRemotingRoot() - .publish(raCtx.getSelf(), new RegistryConnectionLost()); - case RECONNECTED -> isReActorSystemUnique(raCtx.getReActorSystem().getLocalReActorSystemId(), + .publish(ctx.getSelf(), new RegistryConnectionLost()); + case RECONNECTED -> isReActorSystemUnique(ctx.getReActorSystem().getLocalReActorSystemId(), AsyncCuratorFramework.wrap(curator), reActorSystemInstanceMarker) .thenAccept(isUnique -> { if (isUnique) { - refreshDriverStatus(curatorCache, raCtx); + refreshDriverStatus(curatorCache, ctx); } else { - onDuplicateReactorSystem(raCtx); + onDuplicateReactorSystem(ctx); } }); } diff --git a/examples/src/main/java/io/reacted/examples/communication/apublish/MessageStormApp.java b/examples/src/main/java/io/reacted/examples/communication/apublish/MessageStormApp.java index 464d87d9..7b2630f3 100644 --- a/examples/src/main/java/io/reacted/examples/communication/apublish/MessageStormApp.java +++ b/examples/src/main/java/io/reacted/examples/communication/apublish/MessageStormApp.java @@ -143,30 +143,30 @@ public ReActions getReActions() { .build(); } - private void onInit(ReActorContext raCtx) { + private void onInit(ReActorContext ctx) { this.testStart = System.nanoTime(); - raCtx.selfPublish(NextRecord.INSTANCE); + ctx.selfPublish(NextRecord.INSTANCE); } - private void onNextRecord(ReActorContext raCtx) { + private void onNextRecord(ReActorContext ctx) { if (missingCycles == 0) { System.err.printf("Finished Storm. Time %s%n", Duration.ofNanos(System.nanoTime() - testStart)); - raCtx.stop(); + ctx.stop(); } else { serverReference.apublish(String.format("Async Message %d", missingCycles--)) .toCompletableFuture() .handle((deliveryStatus, error) -> { if (error != null) { - raCtx.stop(); + ctx.stop(); error.printStackTrace(); } else { if (deliveryStatus.isDelivered()) { - raCtx.selfPublish(NextRecord.INSTANCE); + ctx.selfPublish(NextRecord.INSTANCE); } else { System.err.printf("Unable to deliver loop message: %s%n", deliveryStatus); - raCtx.stop(); + ctx.stop(); } } return null; diff --git a/examples/src/main/java/io/reacted/examples/communication/ask/ReactiveClockApp.java b/examples/src/main/java/io/reacted/examples/communication/ask/ReactiveClockApp.java index 7cd797c3..061e9ef1 100644 --- a/examples/src/main/java/io/reacted/examples/communication/ask/ReactiveClockApp.java +++ b/examples/src/main/java/io/reacted/examples/communication/ask/ReactiveClockApp.java @@ -26,7 +26,7 @@ public static void main(String[] args) throws FileNotFoundException { var reactiveClockReactions = ReActions.newBuilder() .reAct(TimeRequest.class, - (raCtx, request) -> raCtx.getSender() + (ctx, request) -> ctx.getSender() .publish(Instant.now())) //For any other message type simply ignore the message .reAct((ctx, any) -> { diff --git a/examples/src/main/java/io/reacted/examples/communication/tell/ping/SimpleTestReActor.java b/examples/src/main/java/io/reacted/examples/communication/tell/ping/SimpleTestReActor.java index f84af104..7f416740 100644 --- a/examples/src/main/java/io/reacted/examples/communication/tell/ping/SimpleTestReActor.java +++ b/examples/src/main/java/io/reacted/examples/communication/tell/ping/SimpleTestReActor.java @@ -49,10 +49,10 @@ public ReActions getReActions() { .build(); } - private void onPing(ReActorContext raCtx, String ping) { - Try.ofRunnable(() -> raCtx.logInfo("Received ping {} on dispatcher {}", ping.split(splitter)[1].trim(), + private void onPing(ReActorContext ctx, String ping) { + Try.ofRunnable(() -> ctx.logInfo("Received ping {} on dispatcher {}", ping.split(splitter)[1].trim(), Thread.currentThread().getName())) - .ifError(error -> raCtx.logError("Illegal ping format received", error)); + .ifError(error -> ctx.logError("Illegal ping format received", error)); receivedPings++; } diff --git a/examples/src/main/java/io/reacted/examples/communication/tell/pingpong/PingReActor.java b/examples/src/main/java/io/reacted/examples/communication/tell/pingpong/PingReActor.java index 559a81dc..bcd448fd 100644 --- a/examples/src/main/java/io/reacted/examples/communication/tell/pingpong/PingReActor.java +++ b/examples/src/main/java/io/reacted/examples/communication/tell/pingpong/PingReActor.java @@ -37,7 +37,7 @@ public ReActions getReActions() { return ReActions.newBuilder() .reAct(ReActorInit.class, this::onInit) .reAct(Pong.class, this::onPong) - .reAct((raCtx, payload) -> { + .reAct((ctx, payload) -> { }) .build(); } @@ -53,13 +53,13 @@ public ReActorConfig getConfig() { .build(); } - private void onInit(ReActorContext raCtx, ReActorInit init) { - sendPing(raCtx.getSelf(), pingSent++); + private void onInit(ReActorContext ctx, ReActorInit init) { + sendPing(ctx.getSelf(), pingSent++); } - private void onPong(ReActorContext raCtx, Pong pong) { + private void onPong(ReActorContext ctx, Pong pong) { System.out.printf("Ping sent %d Pong received %d%n", pingSent, pongReceived++); - sendPing(raCtx.getSelf(), pingSent++); + sendPing(ctx.getSelf(), pingSent++); } private void sendPing(ReActorRef sender, int pingSeq) { diff --git a/examples/src/main/java/io/reacted/examples/communication/tell/pingpong/PongReActor.java b/examples/src/main/java/io/reacted/examples/communication/tell/pingpong/PongReActor.java index 155a7064..4107de97 100644 --- a/examples/src/main/java/io/reacted/examples/communication/tell/pingpong/PongReActor.java +++ b/examples/src/main/java/io/reacted/examples/communication/tell/pingpong/PongReActor.java @@ -45,16 +45,16 @@ public ReActorConfig getConfig() { .build(); } - public void onPing(ReActorContext raCtx, Ping ping) { + public void onPing(ReActorContext ctx, Ping ping) { System.out.printf("Pong received a ping for seq %d%n", ping.pingValue()); //Schedule a reply after 1 second pongTimer.schedule(new TimerTask() { @Override - public void run() { raCtx.reply(new Pong(ping.pingValue())); } + public void run() { ctx.reply(new Pong(ping.pingValue())); } }, 1000); } - public void onStop(ReActorContext raCtx, ReActorStop stop) { + public void onStop(ReActorContext ctx, ReActorStop stop) { pongTimer.cancel(); pongTimer.purge(); } diff --git a/examples/src/main/java/io/reacted/examples/httpserver/ReactiveServer.java b/examples/src/main/java/io/reacted/examples/httpserver/ReactiveServer.java index bf89bfea..469f0bce 100644 --- a/examples/src/main/java/io/reacted/examples/httpserver/ReactiveServer.java +++ b/examples/src/main/java/io/reacted/examples/httpserver/ReactiveServer.java @@ -133,29 +133,29 @@ public ReActions getReActions() { return ReActions.newBuilder() .reAct(ReActorInit.class, this::onInit) .reAct(ReactedSubmissionPublisher.class, this::onDataPublisher) - .reAct(InternalError.class, (raCtx, error) -> handleError(raCtx, error.anyError)) - .reAct(ReActorStop.class, (raCtx, error) -> onStop(raCtx)) + .reAct(InternalError.class, (ctx, error) -> handleError(ctx, error.anyError)) + .reAct(ReActorStop.class, (ctx, error) -> onStop(ctx)) .reAct(ReActions::noReAction) .build(); } - private void onInit(ReActorContext raCtx, ReActorInit init) { - raCtx.logInfo("Initializing {}", raCtx.getSelf().getReActorId().getReActorName()); + private void onInit(ReActorContext ctx, ReActorInit init) { + ctx.logInfo("Initializing {}", ctx.getSelf().getReActorId().getReActorName()); Try.ofRunnable(() -> httpCtx.sendResponseHeaders(200, 0)) .flatMap(noVal -> Try.ofRunnable(() -> sendData(""))) - .flatMap(noVal -> spawnPathReaders(filePaths, raCtx, requestId)) - .ifError(error -> handleError(raCtx, error)); + .flatMap(noVal -> spawnPathReaders(filePaths, ctx, requestId)) + .ifError(error -> handleError(ctx, error)); } - private void onDataPublisher(ReActorContext raCtx, ReactedSubmissionPublisher publisher) { + private void onDataPublisher(ReActorContext ctx, ReactedSubmissionPublisher publisher) { publisher.subscribe(ReActedSubscriptionConfig.newBuilder() - .setSubscriberName("sub_" + raCtx.getSender().getReActorId().getReActorName()) + .setSubscriberName("sub_" + ctx.getSender().getReActorId().getReActorName()) .setBufferSize(ReactiveServer.BATCH_BUFFER_SIZE) - .build(), getNexDataConsumer(raCtx)) - .thenAccept(noVal -> raCtx.reply(new PublishRequest(Duration.ofNanos(1)))); + .build(), getNexDataConsumer(ctx)) + .thenAccept(noVal -> ctx.reply(new PublishRequest(Duration.ofNanos(1)))); } - private Flow.Subscriber getNexDataConsumer(ReActorContext raCtx) { + private Flow.Subscriber getNexDataConsumer(ReActorContext ctx) { return new Flow.Subscriber<>() { @Nullable private Flow.Subscription subscription; @@ -176,27 +176,27 @@ public void onNext(String item) { } @Override - public void onError(Throwable throwable) { handleError(raCtx, throwable); } + public void onError(Throwable throwable) { handleError(ctx, throwable); } @Override public void onComplete() { if (ReactiveResponse.this.processed.decrementAndGet() == 0) { - raCtx.stop(); + ctx.stop(); } } }; } - private void onStop(ReActorContext raCtx) { - logOnStop(raCtx); + private void onStop(ReActorContext ctx) { + logOnStop(ctx); Try.ofRunnable(() -> sendData("")) .ifSuccess(noVal -> { outputStream.flush(); outputStream.close(); }); } - private void handleError(ReActorContext raCtx, Throwable anyError) { - raCtx.stop(); - raCtx.logError("Error detected ", anyError); + private void handleError(ReActorContext ctx, Throwable anyError) { + ctx.stop(); + ctx.logError("Error detected ", anyError); } private void sendData(String htmlResponse) throws IOException { @@ -204,9 +204,9 @@ private void sendData(String htmlResponse) throws IOException { } private Try spawnPathReaders(List filePaths, - ReActorContext raCtx, long requestId) { + ReActorContext ctx, long requestId) { return IntStream.range(0, filePaths.size()) - .mapToObj(pathId -> raCtx.spawnChild(new ReadFileWorker(raCtx.getReActorSystem(), + .mapToObj(pathId -> ctx.spawnChild(new ReadFileWorker(ctx.getReActorSystem(), filePaths.get(pathId), requestId, pathId))) .reduce(ReactiveResponse::detectAnyError) @@ -228,11 +228,11 @@ private static class ReadFileWorker implements ReActor { private ReadFileWorker(ReActorSystem reActorSystem, String filePath, long requestId, long workerId) { this.readFileWorkerBehavior = ReActions.newBuilder() .reAct(ReActorInit.class, - ((raCtx, init) -> onInit(raCtx, filePath))) + ((ctx, init) -> onInit(ctx, filePath))) .reAct(ReActorStop.class, - (raCtx, stop) -> onStop(raCtx)) + (ctx, stop) -> onStop(ctx)) .reAct(PublishRequest.class, - (raCtx, pubStart) -> readFileLine(raCtx, fileLines, + (ctx, pubStart) -> readFileLine(ctx, fileLines, pubStart.backpressureDelay)) .reAct(ReActions::noReAction) .build(); @@ -252,29 +252,29 @@ private ReadFileWorker(ReActorSystem reActorSystem, String filePath, long reques @Override public ReActorConfig getConfig() { return readFileWorkerCfg; } - private void onInit(ReActorContext raCtx, String filePath) { + private void onInit(ReActorContext ctx, String filePath) { this.fileLines = Try.of(() -> new InputStreamReader(new FileInputStream(filePath))) - .orElse(null, error -> raCtx.getParent().publish(new InternalError(error))); + .orElse(null, error -> ctx.getParent().publish(new InternalError(error))); if (fileLines == null) { dataPublisher.close(); return; } - if (raCtx.getParent().publish(raCtx.getSelf(), dataPublisher).isNotSent()) { - raCtx.getParent().publish(raCtx.getSelf(), new InternalError(new DeliveryException())); + if (ctx.getParent().publish(ctx.getSelf(), dataPublisher).isNotSent()) { + ctx.getParent().publish(ctx.getSelf(), new InternalError(new DeliveryException())); } } - private void onStop(ReActorContext raCtx) { - logOnStop(raCtx); + private void onStop(ReActorContext ctx) { + logOnStop(ctx); dataPublisher.interrupt(); if (fileLines != null) { Try.ofRunnable(() -> fileLines.close()); } } - private void readFileLine(ReActorContext raCtx, InputStreamReader file, Duration backpressureDelay) { - if (raCtx.isStop()) { + private void readFileLine(ReActorContext ctx, InputStreamReader file, Duration backpressureDelay) { + if (ctx.isStop()) { return; } try { @@ -285,19 +285,19 @@ private void readFileLine(ReActorContext raCtx, InputStreamReader file, Duration return; } if (dataPublisher.submit(new String(buffer, 0, read)).isBackpressureRequired()) { - raCtx.rescheduleMessage(new PublishRequest(backpressureDelay.multipliedBy(2)), + ctx.rescheduleMessage(new PublishRequest(backpressureDelay.multipliedBy(2)), backpressureDelay.multipliedBy(2)); } else { - raCtx.getSelf().tell(raCtx.getSelf(), new PublishRequest(Duration.ofNanos(1))); + ctx.getSelf().tell(ctx.getSelf(), new PublishRequest(Duration.ofNanos(1))); } } catch (Exception exc) { - raCtx.getParent().publish(new InternalError(exc)); + ctx.getParent().publish(new InternalError(exc)); } } } - private static void logOnStop(ReActorContext raCtx) { - raCtx.logInfo("Stopping {}", raCtx.getSelf().getReActorId().getReActorName()); + private static void logOnStop(ReActorContext ctx) { + ctx.logInfo("Stopping {}", ctx.getSelf().getReActorId().getReActorName()); } private record PublishRequest(Duration backpressureDelay) implements Serializable { } diff --git a/examples/src/main/java/io/reacted/examples/quickstart/GreeterService.java b/examples/src/main/java/io/reacted/examples/quickstart/GreeterService.java index f5583fb1..064a770f 100644 --- a/examples/src/main/java/io/reacted/examples/quickstart/GreeterService.java +++ b/examples/src/main/java/io/reacted/examples/quickstart/GreeterService.java @@ -33,11 +33,11 @@ public ReActorConfig getConfig() { public ReActions getReActions() { return ReActions.newBuilder() .reAct(ReActorInit.class, - (raCtx, init) -> - raCtx.logInfo("{} was born", raCtx.getSelf().getReActorId().getReActorName())) + (ctx, init) -> + ctx.logInfo("{} was born", ctx.getSelf().getReActorId().getReActorName())) .reAct(GreetingsRequest.class, - (raCtx, greetingsRequest) -> - raCtx.reply("Hello from " + GreeterService.class.getSimpleName())) + (ctx, greetingsRequest) -> + ctx.reply("Hello from " + GreeterService.class.getSimpleName())) .build(); } static final class GreetingsRequest implements Serializable { } diff --git a/examples/src/main/java/io/reacted/examples/quickstart/QuickstartSubscriber.java b/examples/src/main/java/io/reacted/examples/quickstart/QuickstartSubscriber.java index 0d75d7bd..c1c6524f 100644 --- a/examples/src/main/java/io/reacted/examples/quickstart/QuickstartSubscriber.java +++ b/examples/src/main/java/io/reacted/examples/quickstart/QuickstartSubscriber.java @@ -65,9 +65,9 @@ public ReActorConfig getConfig() { public ReActions getReActions() { return ReActions.newBuilder() .reAct(GreeterService.GreetingsRequest.class, - (raCtx, greetingsRequest) -> - raCtx.logInfo("{} intercepted {}", - raCtx.getSelf().getReActorId().getReActorName(), + (ctx, greetingsRequest) -> + ctx.logInfo("{} intercepted {}", + ctx.getSelf().getReActorId().getReActorName(), greetingsRequest)) .build(); } diff --git a/examples/src/main/java/io/reacted/examples/remoting/services/ClockReActor.java b/examples/src/main/java/io/reacted/examples/remoting/services/ClockReActor.java index fd4a5f1a..2fac3131 100644 --- a/examples/src/main/java/io/reacted/examples/remoting/services/ClockReActor.java +++ b/examples/src/main/java/io/reacted/examples/remoting/services/ClockReActor.java @@ -33,7 +33,7 @@ public class ClockReActor implements ReActor { public ReActions getReActions() { return ReActions.newBuilder() .reAct(TimeRequest.class, - (raCtx, timeRequest) -> raCtx.reply(raCtx.getParent(), ZonedDateTime.now())) + (ctx, timeRequest) -> ctx.reply(ctx.getParent(), ZonedDateTime.now())) .reAct(ReActions::noReAction) .build(); } diff --git a/examples/src/main/java/io/reacted/examples/remoting/services/TimeReActor.java b/examples/src/main/java/io/reacted/examples/remoting/services/TimeReActor.java index d5240091..fd15f681 100644 --- a/examples/src/main/java/io/reacted/examples/remoting/services/TimeReActor.java +++ b/examples/src/main/java/io/reacted/examples/remoting/services/TimeReActor.java @@ -42,29 +42,29 @@ public ReActions getReActions() { .build(); } - private void onInit(ReActorContext raCtx, ReActorInit init) { - if (!raCtx.getReActorSystem() + private void onInit(ReActorContext ctx, ReActorInit init) { + if (!ctx.getReActorSystem() .serviceDiscovery(BasicServiceDiscoverySearchFilter.newBuilder() .setServiceName(serviceToQuery) .setSelectionType(SelectionType.DIRECT) - .build(), raCtx.getSelf()).isDelivered()) { - raCtx.logError("Error discovering service"); + .build(), ctx.getSelf()).isDelivered()) { + ctx.logError("Error discovering service"); } } - private void onServiceDiscoveryReply(ReActorContext raCtx, ServiceDiscoveryReply serviceDiscoveryReply) { + private void onServiceDiscoveryReply(ReActorContext ctx, ServiceDiscoveryReply serviceDiscoveryReply) { var gate = serviceDiscoveryReply.getServiceGates().stream() .findAny(); - gate.ifPresentOrElse(serviceGate -> serviceGate.publish(raCtx.getSelf(), new TimeRequest()), - () -> raCtx.logError("No service discovery response received")); + gate.ifPresentOrElse(serviceGate -> serviceGate.publish(ctx.getSelf(), new TimeRequest()), + () -> ctx.logError("No service discovery response received")); } - private void onServiceResponse(ReActorContext raCtx, ZonedDateTime time) { - raCtx.logInfo("Received {} response from service: {}", ++received, time.toString()); + private void onServiceResponse(ReActorContext ctx, ZonedDateTime time) { + ctx.logInfo("Received {} response from service: {}", ++received, time.toString()); } - private void onStop(ReActorContext raCtx, ReActorStop stop) { - raCtx.logInfo("{} is exiting", raCtx.getSelf().getReActorId().getReActorName()); + private void onStop(ReActorContext ctx, ReActorStop stop) { + ctx.logInfo("{} is exiting", ctx.getSelf().getReActorId().getReActorName()); } @Nonnull diff --git a/examples/src/main/java/io/reacted/examples/services/ServicePublicationApp.java b/examples/src/main/java/io/reacted/examples/services/ServicePublicationApp.java index 23c58fa0..45ba809c 100644 --- a/examples/src/main/java/io/reacted/examples/services/ServicePublicationApp.java +++ b/examples/src/main/java/io/reacted/examples/services/ServicePublicationApp.java @@ -114,9 +114,9 @@ public static void main(String[] args) { .thenAccept(dummyReturn -> reActorSystem.shutDown()); } - private static void onTimeRequest(ReActorContext raCtx, TimeRequest timeRequest) { - raCtx.logInfo("{} received {}", raCtx.getSelf().getReActorId().getReActorName(), + private static void onTimeRequest(ReActorContext ctx, TimeRequest timeRequest) { + ctx.logInfo("{} received {}", ctx.getSelf().getReActorId().getReActorName(), timeRequest.getClass().getSimpleName()); - raCtx.reply(ReActorRef.NO_REACTOR_REF, ZonedDateTime.ofInstant(Instant.now(), ZoneId.systemDefault())); + ctx.reply(ReActorRef.NO_REACTOR_REF, ZonedDateTime.ofInstant(Instant.now(), ZoneId.systemDefault())); } } diff --git a/examples/src/main/java/io/reacted/examples/spawning/ReActorRelationsApp.java b/examples/src/main/java/io/reacted/examples/spawning/ReActorRelationsApp.java index e7965652..45174c96 100644 --- a/examples/src/main/java/io/reacted/examples/spawning/ReActorRelationsApp.java +++ b/examples/src/main/java/io/reacted/examples/spawning/ReActorRelationsApp.java @@ -43,8 +43,8 @@ public static void main(String[] args) { } } - private static void onStop(ReActorContext raCtx, ReActorStop stop) { - raCtx.logInfo(raCtx.getSelf().getReActorId().getReActorName() + " is terminating"); + private static void onStop(ReActorContext ctx, ReActorStop stop) { + ctx.logInfo(ctx.getSelf().getReActorId().getReActorName() + " is terminating"); } @NonNullByDefault @@ -65,22 +65,22 @@ private Father() { @Override public ReActions getReActions() { return fatherReactions; } - private void onBreedRequest(ReActorContext raCtx, BreedRequest breedRequest) { + private void onBreedRequest(ReActorContext ctx, BreedRequest breedRequest) { this.requestedChildren = breedRequest.requestedChildren(); - raCtx.logInfo("{} received a {} for {} from {}", - raCtx.getSelf().getReActorId().getReActorName(), + ctx.logInfo("{} received a {} for {} from {}", + ctx.getSelf().getReActorId().getReActorName(), breedRequest.getClass().getSimpleName(), breedRequest.requestedChildren(), - raCtx.getSender().getReActorId().getReActorName()); + ctx.getSender().getReActorId().getReActorName()); LongStream.range(0, breedRequest.requestedChildren()) - .forEachOrdered(childNum -> raCtx.spawnChild(new Child(childNum, raCtx.getSender()))); + .forEachOrdered(childNum -> ctx.spawnChild(new Child(childNum, ctx.getSender()))); } - private void onThankYou(ReActorContext raCtx, ThankYouFather thanks) { + private void onThankYou(ReActorContext ctx, ThankYouFather thanks) { if (--requestedChildren == 0) { - raCtx.stop() - .thenAcceptAsync(voidVal -> raCtx.reply(ReActorRef.NO_REACTOR_REF, new ByeByeUncle())); + ctx.stop() + .thenAcceptAsync(voidVal -> ctx.reply(ReActorRef.NO_REACTOR_REF, new ByeByeUncle())); } } } @@ -97,13 +97,13 @@ private static class Uncle implements ReActiveEntity { @Override public ReActions getReActions() { return UNCLE_REACTIONS; } - private static void onGreetingsFromChild(ReActorContext raCtx, Greetings greetingsMessage) { - raCtx.logInfo("{} received {}. Sending thank you to {}", raCtx.getSelf().getReActorId().getReActorName(), - greetingsMessage.greetingsMessage(), raCtx.getSender().getReActorId().getReActorName()); - raCtx.reply(new ThankYouFather()); + private static void onGreetingsFromChild(ReActorContext ctx, Greetings greetingsMessage) { + ctx.logInfo("{} received {}. Sending thank you to {}", ctx.getSelf().getReActorId().getReActorName(), + greetingsMessage.greetingsMessage(), ctx.getSender().getReActorId().getReActorName()); + ctx.reply(new ThankYouFather()); } - private static void onByeByeUncle(ReActorContext raCtx, ByeByeUncle timeToDie) { raCtx.stop(); } + private static void onByeByeUncle(ReActorContext ctx, ByeByeUncle timeToDie) { ctx.stop(); } } @NonNullByDefault @@ -131,8 +131,8 @@ public ReActions getReActions() { .build(); } - private void onInit(ReActorContext raCtx, ReActorInit init) { - breedRequester.publish(raCtx.getParent(), + private void onInit(ReActorContext ctx, ReActorInit init) { + breedRequester.publish(ctx.getParent(), new Greetings("Hello from " + childConfig.getReActorName())); } } diff --git a/examples/src/main/java/io/reacted/examples/typedsubscription/RemoteBroadcastingApp.java b/examples/src/main/java/io/reacted/examples/typedsubscription/RemoteBroadcastingApp.java index 4e70806e..ed2563a5 100644 --- a/examples/src/main/java/io/reacted/examples/typedsubscription/RemoteBroadcastingApp.java +++ b/examples/src/main/java/io/reacted/examples/typedsubscription/RemoteBroadcastingApp.java @@ -53,7 +53,7 @@ public static void main(String[] args) throws InterruptedException { subscriberSystem.spawn(ReActions.newBuilder() .reAct(Update.class, - (raCtx, update) -> raCtx.logInfo("Received {}", + (ctx, update) -> ctx.logInfo("Received {}", update.getClass().getSimpleName())) .build(), ReActorConfig.newBuilder() diff --git a/examples/src/main/java/io/reacted/examples/webappbackend/ServerGate.java b/examples/src/main/java/io/reacted/examples/webappbackend/ServerGate.java index 4756e2d4..faf838fb 100644 --- a/examples/src/main/java/io/reacted/examples/webappbackend/ServerGate.java +++ b/examples/src/main/java/io/reacted/examples/webappbackend/ServerGate.java @@ -48,8 +48,8 @@ public ServerGate(HttpServer server, ExecutorService asyncExecutorService, Execu @Override public ReActions getReActions() { return ReActions.newBuilder() - .reAct(ReActorInit.class, (raCtx, init) -> onGateInit(raCtx)) - .reAct(ReActorStop.class, (raCtx, stop) -> server.stop(0)) + .reAct(ReActorInit.class, (ctx, init) -> onGateInit(ctx)) + .reAct(ReActorStop.class, (ctx, stop) -> server.stop(0)) .reAct(SpawnPostHandler.class, this::spawnPostHandler) .reAct(SpawnGetHandler.class, this::spawnGetHandler) .reAct(SpawnUnknownHandler.class, ServerGate::spawnUnknownHandler) @@ -74,8 +74,8 @@ public void handle(HttpExchange exchange) { ? new SpawnPostHandler(requestId) : new SpawnUnknownHandler(requestId)); } - private void onGateInit(ReActorContext raCtx) { - this.thisCtx = raCtx; + private void onGateInit(ReActorContext ctx) { + this.thisCtx = ctx; server.createContext(WRITE_PREDICATE_PATH, this); server.createContext(READ_PREDICATE_PATH, this); server.setExecutor(serverExecutor); @@ -87,21 +87,21 @@ private void onGateInit(ReActorContext raCtx) { On replay, this ServerGate reactor regardless if a http request arrives or not will receive a spawn request, triggering the handling using the saved logs and initializing the flow */ - private void spawnPostHandler(ReActorContext raCtx, SpawnPostHandler spawnRequest) { - raCtx.spawnChild(new Post(this.requestIdToHttpExchange.remove(spawnRequest.requestId), + private void spawnPostHandler(ReActorContext ctx, SpawnPostHandler spawnRequest) { + ctx.spawnChild(new Post(this.requestIdToHttpExchange.remove(spawnRequest.requestId), spawnRequest.requestId, asyncService)) - .ifError(error -> raCtx.logError("Unable to spawn child reactor for request [{}]", + .ifError(error -> ctx.logError("Unable to spawn child reactor for request [{}]", spawnRequest.requestId, error)); } - private void spawnGetHandler(ReActorContext raCtx, SpawnGetHandler spawnRequest) { - raCtx.spawnChild(new Get(this.requestIdToHttpExchange.remove(spawnRequest.getRequestId()), + private void spawnGetHandler(ReActorContext ctx, SpawnGetHandler spawnRequest) { + ctx.spawnChild(new Get(this.requestIdToHttpExchange.remove(spawnRequest.getRequestId()), spawnRequest.getRequestId(), asyncService)) - .ifError(error -> raCtx.logError("Unable to spawn child reactor for request [{}]", + .ifError(error -> ctx.logError("Unable to spawn child reactor for request [{}]", spawnRequest.getRequestId(), error)); } - private static void spawnUnknownHandler(ReActorContext raCtx, SpawnUnknownHandler spawnUnknownRequest) { - raCtx.logError("Unknown request type received: ", spawnUnknownRequest.getRequestId()); + private static void spawnUnknownHandler(ReActorContext ctx, SpawnUnknownHandler spawnUnknownRequest) { + ctx.logError("Unknown request type received: ", spawnUnknownRequest.getRequestId()); } private static class SpawnPostHandler implements Serializable { diff --git a/examples/src/main/java/io/reacted/examples/webappbackend/db/DatabaseService.java b/examples/src/main/java/io/reacted/examples/webappbackend/db/DatabaseService.java index c30fac32..70e98998 100644 --- a/examples/src/main/java/io/reacted/examples/webappbackend/db/DatabaseService.java +++ b/examples/src/main/java/io/reacted/examples/webappbackend/db/DatabaseService.java @@ -50,33 +50,33 @@ public ReActorConfig getConfig() { @Override public ReActions getReActions() { return ReActions.newBuilder() - .reAct(ReActorInit.class, (raCtx, init) -> ifNotReplaying(this::onMongoInit, raCtx, init)) + .reAct(ReActorInit.class, (ctx, init) -> ifNotReplaying(this::onMongoInit, ctx, init)) .reAct(StorageMessages.StoreRequest.class, - (raCtx, store) -> ifNotReplaying(this::onStoreRequest, raCtx, store)) + (ctx, store) -> ifNotReplaying(this::onStoreRequest, ctx, store)) .reAct(StorageMessages.QueryRequest.class, - (raCtx, query) -> ifNotReplaying(this::onQueryRequest, raCtx, query)) + (ctx, query) -> ifNotReplaying(this::onQueryRequest, ctx, query)) .build(); } - private void onMongoInit(ReActorContext raCtx, ReActorInit init) { + private void onMongoInit(ReActorContext ctx, ReActorInit init) { this.mongoCollection = Objects.requireNonNull(mongoClient).getDatabase(DB_NAME) .getCollection(COLLECTION); } - private void onStoreRequest(ReActorContext raCtx, StorageMessages.StoreRequest request) { + private void onStoreRequest(ReActorContext ctx, StorageMessages.StoreRequest request) { var publisher = mongoCollection.insertOne(new Document(Map.of("_id", request.getKey(), PAYLOAD_FIELD, request.getPayload()))); - publisher.subscribe(new MongoSubscribers.MongoStoreSubscriber(raCtx.getSelf(), raCtx.getSender())); + publisher.subscribe(new MongoSubscribers.MongoStoreSubscriber(ctx.getSelf(), ctx.getSender())); } - private void onQueryRequest(ReActorContext raCtx, StorageMessages.QueryRequest request) { + private void onQueryRequest(ReActorContext ctx, StorageMessages.QueryRequest request) { mongoCollection.find(Filters.eq("_id", request.key())) - .first().subscribe(new MongoSubscribers.MongoQuerySubscriber(raCtx.getSelf(), - raCtx.getSender())); + .first().subscribe(new MongoSubscribers.MongoQuerySubscriber(ctx.getSelf(), + ctx.getSender())); } private - void ifNotReplaying(BiConsumer realCall, ReActorContext raCtx, PayloadT anyPayload) { + void ifNotReplaying(BiConsumer realCall, ReActorContext ctx, PayloadT anyPayload) { if (mongoClient != null) { - realCall.accept(raCtx, anyPayload); + realCall.accept(ctx, anyPayload); } } } diff --git a/examples/src/main/java/io/reacted/examples/webappbackend/handlers/Get.java b/examples/src/main/java/io/reacted/examples/webappbackend/handlers/Get.java index 2af08f23..a2527895 100644 --- a/examples/src/main/java/io/reacted/examples/webappbackend/handlers/Get.java +++ b/examples/src/main/java/io/reacted/examples/webappbackend/handlers/Get.java @@ -60,57 +60,57 @@ public ReActorConfig getConfig() { @Override public ReActions getReActions() { return ReActions.newBuilder() - .reAct(ReActorInit.class, (raCtx, init) -> onInit(raCtx)) + .reAct(ReActorInit.class, (ctx, init) -> onInit(ctx)) .reAct(ProcessGet.class, this::onProcessGet) .reAct(ServiceDiscoveryReply.class, this::onDbServiceDiscoveryReply) .build(); } - private void onInit(ReActorContext raCtx) { + private void onInit(ReActorContext ctx) { if (httpExchange != null) { CompletableFuture.runAsync(() -> Try.ofRunnable(() -> httpExchange.sendResponseHeaders(200, 0)), asyncService) .toCompletableFuture() - .thenAccept(noVal -> raCtx.selfPublish(new ProcessGet(httpExchange.getRequestURI() + .thenAccept(noVal -> ctx.selfPublish(new ProcessGet(httpExchange.getRequestURI() .toString()))); } // start a request in parallel - raCtx.getReActorSystem() + ctx.getReActorSystem() .serviceDiscovery(BasicServiceDiscoverySearchFilter.newBuilder() .setServiceName(Backend.DB_SERVICE_NAME) - .build(), raCtx.getSelf()); + .build(), ctx.getSelf()); } - private void onProcessGet(ReActorContext raCtx, ProcessGet getRequest) { + private void onProcessGet(ReActorContext ctx, ProcessGet getRequest) { try { this.requestKey = extractGetFirstParameter(getRequest.getRequest); if (dbGate != null) { - retrieveEntry(raCtx, requestKey, dbGate); + retrieveEntry(ctx, requestKey, dbGate); } } catch (Exception anyParseException) { sendReplyMessage("Invalid request format"); - raCtx.stop(); + ctx.stop(); } } - private void onDbServiceDiscoveryReply(ReActorContext raCtx, ServiceDiscoveryReply serviceDiscoveryReply) { + private void onDbServiceDiscoveryReply(ReActorContext ctx, ServiceDiscoveryReply serviceDiscoveryReply) { if (serviceDiscoveryReply.getServiceGates().isEmpty()) { /* No db to retrieve data from */ sendReplyMessage("No database could be found"); - raCtx.stop(); + ctx.stop(); return; } this.dbGate = serviceDiscoveryReply.getServiceGates().iterator().next(); if (requestKey != null) { - retrieveEntry(raCtx, requestKey, dbGate); + retrieveEntry(ctx, requestKey, dbGate); } } - private void retrieveEntry(ReActorContext raCtx, String key, ReActorRef dbGate) { - dbGate.ask(new StorageMessages.QueryRequest(key), StorageMessages.QueryReply.class, raCtx.getSelf().getReActorId().toString()) + private void retrieveEntry(ReActorContext ctx, String key, ReActorRef dbGate) { + dbGate.ask(new StorageMessages.QueryRequest(key), StorageMessages.QueryReply.class, ctx.getSelf().getReActorId().toString()) .thenComposeAsync(queryReply -> sendReplyMessage(queryReply.payload()), asyncService) - .thenAccept(sendReturn -> { sendReturn.ifError(error -> raCtx.logError("Unable to send back reply", error)); - raCtx.stop(); }); + .thenAccept(sendReturn -> { sendReturn.ifError(error -> ctx.logError("Unable to send back reply", error)); + ctx.stop(); }); } private static String extractGetFirstParameter(String getRequest) { return getRequest.split("\\?")[1].split("=")[1]; diff --git a/examples/src/main/java/io/reacted/examples/webappbackend/handlers/Post.java b/examples/src/main/java/io/reacted/examples/webappbackend/handlers/Post.java index 8597a5c7..2c87592b 100644 --- a/examples/src/main/java/io/reacted/examples/webappbackend/handlers/Post.java +++ b/examples/src/main/java/io/reacted/examples/webappbackend/handlers/Post.java @@ -50,9 +50,9 @@ public Post(@Nullable HttpExchange httpExchange, String requestId, ExecutorServi @Override public ReActions getReActions() { return ReActions.newBuilder() - .reAct(ReActorInit.class, (raCtx, init) -> onRequestHandlingInit(raCtx)) + .reAct(ReActorInit.class, (ctx, init) -> onRequestHandlingInit(ctx)) .reAct(DataChunkPush.class, this::onNewDataChunk) - .reAct(DataChunksCompleted.class, (raCtx, complete) -> onPostComplete(raCtx)) + .reAct(DataChunksCompleted.class, (ctx, complete) -> onPostComplete(ctx)) .reAct(StorageMessages.StoreReply.class, this::onStoreReply) .reAct(StorageMessages.StoreError.class, this::onStoreError) .build(); @@ -63,85 +63,85 @@ public ReActions getReActions() { public ReActorConfig getConfig() { return ReActorConfig.newBuilder() .setReActorName(requestId) - .setMailBoxProvider(raCtx -> BackpressuringMbox.newBuilder() - .setRealMailboxOwner(raCtx) + .setMailBoxProvider(ctx -> BackpressuringMbox.newBuilder() + .setRealMailboxOwner(ctx) .setAvailableOnStartup(1) .setRealMbox(new UnboundedMbox()) .build()) .build(); } - private void onPostComplete(ReActorContext raCtx) { - raCtx.getMbox().request(1); - raCtx.getReActorSystem() + private void onPostComplete(ReActorContext ctx) { + ctx.getMbox().request(1); + ctx.getReActorSystem() .serviceDiscovery(BasicServiceDiscoverySearchFilter.newBuilder() .setServiceName(Backend.DB_SERVICE_NAME) .build()) - .thenAccept(serviceDiscovery -> onDbServiceReply(raCtx, serviceDiscovery)); + .thenAccept(serviceDiscovery -> onDbServiceReply(ctx, serviceDiscovery)); } - private void onDbServiceReply(ReActorContext raCtx, ServiceDiscoveryReply services) { - raCtx.getMbox().request(1); + private void onDbServiceReply(ReActorContext ctx, ServiceDiscoveryReply services) { + ctx.getMbox().request(1); if (!services.getServiceGates().isEmpty()) { services.getServiceGates().iterator().next() - .publish(raCtx.getSelf(), + .publish(ctx.getSelf(), new StorageMessages.StoreRequest(String.valueOf(Instant.now().toEpochMilli()), payloadBuilder.toString())); } else { - raCtx.selfPublish(new StorageMessages.StoreError(new RuntimeException("No database found"))); + ctx.selfPublish(new StorageMessages.StoreError(new RuntimeException("No database found"))); } } - private void onStoreReply(ReActorContext raCtx, StorageMessages.StoreReply storeReply) { - raCtx.getMbox().request(1); + private void onStoreReply(ReActorContext ctx, StorageMessages.StoreReply storeReply) { + ctx.getMbox().request(1); if (httpExchange != null) { Try.ofRunnable(() -> httpExchange.getResponseBody().close()) - .ifError(error -> raCtx.logError("Error closing output stream", error)); + .ifError(error -> ctx.logError("Error closing output stream", error)); } - raCtx.stop(); + ctx.stop(); } - private void onStoreError(ReActorContext raCtx, StorageMessages.StoreError error) { - raCtx.logError("Error storing payload: ", error); + private void onStoreError(ReActorContext ctx, StorageMessages.StoreError error) { + ctx.logError("Error storing payload: ", error); if (httpExchange != null) { Try.ofRunnable(() -> { httpExchange.getResponseBody().write(error.toString().getBytes()); httpExchange.getResponseBody().close(); }) - .ifError(replyError -> raCtx.logError("Error closing output stream", replyError)); + .ifError(replyError -> ctx.logError("Error closing output stream", replyError)); } - raCtx.stop(); + ctx.stop(); } - private void onNewDataChunk(ReActorContext raCtx, DataChunkPush newChunk) { - raCtx.getMbox().request(1); + private void onNewDataChunk(ReActorContext ctx, DataChunkPush newChunk) { + ctx.getMbox().request(1); payloadBuilder.append(newChunk.lineRead); } - private void onRequestHandlingInit(ReActorContext raCtx) { + private void onRequestHandlingInit(ReActorContext ctx) { if (httpExchange == null) { return; } ioAsyncExecutor.submit(() -> Try.ofRunnable(() -> httpExchange.sendResponseHeaders(200, 0)) - .ifError(error -> { raCtx.logError("Unable to send response headers", error); - raCtx.stop(); })); - readPostDataStream(raCtx); + .ifError(error -> { ctx.logError("Unable to send response headers", error); + ctx.stop(); })); + readPostDataStream(ctx); } /* Backpressured async read from the remote stream */ - private void readPostDataStream(ReActorContext raCtx) { + private void readPostDataStream(ReActorContext ctx) { var requestStream = Objects.requireNonNull(httpExchange).getRequestBody(); var reader = new BufferedReader(new InputStreamReader(requestStream)); CompletionStage whileLoop; - while (sendTillAvailable(raCtx, reader).isDelivered()); + while (sendTillAvailable(ctx, reader).isDelivered()); Try.ofRunnable(reader::close) - .ifSuccessOrElse(noVal -> raCtx.logInfo("Stream closed"), - error -> raCtx.logError("Error closing stream", error)); + .ifSuccessOrElse(noVal -> ctx.logInfo("Stream closed"), + error -> ctx.logError("Error closing stream", error)); } @Nullable - private static DeliveryStatus sendTillAvailable(ReActorContext raCtx, + private static DeliveryStatus sendTillAvailable(ReActorContext ctx, BufferedReader inputStream) { var nextMsg = getNextDataChunk(inputStream); - var nextSend = raCtx.selfPublish(nextMsg); + var nextSend = ctx.selfPublish(nextMsg); return nextMsg.getClass() != DataChunksCompleted.class ? nextSend : DeliveryStatus.BACKPRESSURE_REQUIRED; diff --git a/flow/src/main/java/io/reacted/flow/GraphController.java b/flow/src/main/java/io/reacted/flow/GraphController.java index dbad8fc2..4bdf5704 100644 --- a/flow/src/main/java/io/reacted/flow/GraphController.java +++ b/flow/src/main/java/io/reacted/flow/GraphController.java @@ -71,9 +71,9 @@ class GraphController implements ReActiveEntity { this.operatorNameToOperator = new ConcurrentHashMap<>(operatorsCfgs.size(), 0.5f); this.operatorToInitedRoutees = new HashMap<>(); this.reActions = ReActions.newBuilder() - .reAct(ReActorInit.class, (raCtx, init) -> onInit(raCtx)) - .reAct(InitInputStreams.class, (raCtx, initStreams) -> onInitInputStreams(raCtx)) - .reAct(ReActorStop.class, (raCtx, stop) -> onStop()) + .reAct(ReActorInit.class, (ctx, init) -> onInit(ctx)) + .reAct(InitInputStreams.class, (ctx, initStreams) -> onInitInputStreams(ctx)) + .reAct(ReActorStop.class, (ctx, stop) -> onStop()) .reAct(OperatorInitComplete.class, this::onOperatorInitComplete) .build(); this.inputStreamProcessors = new LinkedList<>(); @@ -86,7 +86,7 @@ class GraphController implements ReActiveEntity { Map getOperatorsByName() { return operatorNameToOperator; } - private void onOperatorInitComplete(ReActorContext raCtx, + private void onOperatorInitComplete(ReActorContext ctx, OperatorInitComplete operatorInitComplete) { if (!Objects.equals(flowName, operatorInitComplete.getFlowName())) { return; // Not Interesting, it's for another flow @@ -98,24 +98,24 @@ private void onOperatorInitComplete(ReActorContext raCtx, entry.getValue().getRouteesNum()) && !inputStreamsHaveBeenInited) { this.inputStreamsHaveBeenInited = true; - raCtx.selfPublish(new InitInputStreams()); + ctx.selfPublish(new InitInputStreams()); } } - private void onInit(ReActorContext raCtx) { - BackpressuringMbox.toBackpressuringMailbox(raCtx.getMbox()) + private void onInit(ReActorContext ctx) { + BackpressuringMbox.toBackpressuringMailbox(ctx.getMbox()) .ifPresent(mbox -> mbox.addNonDelayableTypes(Set.of(OperatorInitComplete.class))); for(var operatorCfg : operatorsCfgsByName.entrySet()) { operatorNameToOperator.put(operatorCfg.getKey(), - spawnOperator(raCtx.getReActorSystem(),operatorCfg.getValue(), - raCtx.getSelf()).orElseSneakyThrow()); + spawnOperator(ctx.getReActorSystem(),operatorCfg.getValue(), + ctx.getSelf()).orElseSneakyThrow()); } } - private void onInitInputStreams(ReActorContext raCtx) { + private void onInitInputStreams(ReActorContext ctx) { for(var operatorCfg : operatorsCfgsByName.entrySet()) { for(var inputStream : operatorCfg.getValue().getInputStreams()) { spawnNewStreamConsumer(operatorNameToOperator.get(operatorCfg.getKey()), - inputStream, raCtx.getReActorSystem(), - raCtx.getSelf().getReActorId().getReActorName(), + inputStream, ctx.getReActorSystem(), + ctx.getSelf().getReActorId().getReActorName(), operatorCfg.getValue()); } } diff --git a/flow/src/main/java/io/reacted/flow/operators/FlowOperator.java b/flow/src/main/java/io/reacted/flow/operators/FlowOperator.java index ce0bc361..f620f1be 100644 --- a/flow/src/main/java/io/reacted/flow/operators/FlowOperator.java +++ b/flow/src/main/java/io/reacted/flow/operators/FlowOperator.java @@ -62,7 +62,7 @@ protected FlowOperator(CfgT operatorCfg) { this.ifPredicateOutputOperatorsRefs = List.of(); this.thenElseOutputOperatorsRefs = List.of(); this.operatorReactions = ReActions.newBuilder() - .reAct(RefreshOperatorRequest.class, (raCtx, payload) -> onRefreshOperatorRequest(raCtx)) + .reAct(RefreshOperatorRequest.class, (ctx, payload) -> onRefreshOperatorRequest(ctx)) .reAct(ReActorInit.class, this::onInit) .reAct(ReActorStop.class, this::onStop) .reAct(OperatorOutputGatesUpdate.class, this::onServiceGatesUpdate) @@ -86,13 +86,13 @@ protected static Try of(ReActorSystem localReActorSystem, ServiceCon return localReActorSystem.spawnService(config); } protected abstract CompletionStage> - onNext(Serializable input, ReActorContext raCtx); - protected void onLinkError(Throwable error, ReActorContext raCtx, Serializable input) { - raCtx.logError("Unable to pass {} to the next stage", input, error); + onNext(Serializable input, ReActorContext ctx); + protected void onLinkError(Throwable error, ReActorContext ctx, Serializable input) { + ctx.logError("Unable to pass {} to the next stage", input, error); } @SuppressWarnings("EmptyMethod") - protected void onInit(ReActorContext raCtx, ReActorInit init) { - BackpressuringMbox.toBackpressuringMailbox(raCtx.getMbox()) + protected void onInit(ReActorContext ctx, ReActorInit init) { + BackpressuringMbox.toBackpressuringMailbox(ctx.getMbox()) .map(mbox -> mbox.addNonDelayableTypes(Set.of(RefreshOperatorRequest.class, OperatorOutputGatesUpdate.class))) /* If this init is not delayed, an slot of the backpressuring buffer size @@ -102,76 +102,76 @@ protected void onInit(ReActorContext raCtx, ReActorInit init) { .filter(mbox -> mbox.isDelayable(ReActorInit.class)) .ifPresent(mbox -> mbox.request(1)); // Constantly refresh the gates. The idea is to automatically discover new available operators - this.operatorsRefreshTask = raCtx.getReActorSystem() + this.operatorsRefreshTask = ctx.getReActorSystem() .getSystemSchedulingService() .scheduleWithFixedDelay(() -> { - if (!raCtx.selfPublish(new RefreshOperatorRequest()).isSent()) { - raCtx.logError("Unable to request refresh of operator outputs"); + if (!ctx.selfPublish(new RefreshOperatorRequest()).isSent()) { + ctx.logError("Unable to request refresh of operator outputs"); }}, 0, operatorCfg.getOutputOperatorsRefreshPeriod() .toNanos(), TimeUnit.NANOSECONDS); } - protected void onServiceGatesUpdate(ReActorContext raCtx, OperatorOutputGatesUpdate newGates) { + protected void onServiceGatesUpdate(ReActorContext ctx, OperatorOutputGatesUpdate newGates) { this.ifPredicateOutputOperatorsRefs = newGates.ifPredicateServices; this.thenElseOutputOperatorsRefs = newGates.thenElseServices; if (isShallAwakeInputStreams()) { this.shallAwakeInputStreams = false; - broadcastOperatorInitializationComplete(raCtx); + broadcastOperatorInitializationComplete(ctx); } } - protected void broadcastOperatorInitializationComplete(ReActorContext raCtx) { - raCtx.getReActorSystem() - .broadcastToLocalSubscribers(raCtx.getSelf(), + protected void broadcastOperatorInitializationComplete(ReActorContext ctx) { + ctx.getReActorSystem() + .broadcastToLocalSubscribers(ctx.getSelf(), new OperatorInitComplete(operatorCfg.getFlowName(), operatorCfg.getReActorName(), - raCtx.getSelf() + ctx.getSelf() .getReActorId() .getReActorName())); } - protected void onStop(ReActorContext raCtx, ReActorStop stop) { + protected void onStop(ReActorContext ctx, ReActorStop stop) { operatorsRefreshTask.cancel(true); } - protected void onRefreshOperatorRequest(ReActorContext raCtx) { + protected void onRefreshOperatorRequest(ReActorContext ctx) { var ifServices = ReActedUtils.resolveServices(operatorCfg.getIfPredicateOutputOperators(), - raCtx.getReActorSystem(), + ctx.getReActorSystem(), GateSelectorPolicies.RANDOM_GATE, - raCtx.getSelf().getReActorId().toString()); + ctx.getSelf().getReActorId().toString()); var thenElseServices = ReActedUtils.resolveServices(operatorCfg.getThenElseOutputOperators(), - raCtx.getReActorSystem(), + ctx.getReActorSystem(), GateSelectorPolicies.RANDOM_GATE, - raCtx.getSelf().getReActorId().toString()); + ctx.getSelf().getReActorId().toString()); ifServices.thenCombine(thenElseServices, OperatorOutputGatesUpdate::new) .thenAccept(operatorOutputGatesUpdate -> { if (isUpdateMatchingRequest(operatorCfg.getIfPredicateOutputOperators().size(), operatorCfg.getThenElseOutputOperators().size(), operatorOutputGatesUpdate)) { - raCtx.selfPublish(operatorOutputGatesUpdate); + ctx.selfPublish(operatorOutputGatesUpdate); } }); } - private void onNext(ReActorContext raCtx, Serializable message) { - backpressuredPropagation(onNext(message, raCtx), message, raCtx); + private void onNext(ReActorContext ctx, Serializable message) { + backpressuredPropagation(onNext(message, ctx), message, ctx); } protected CompletionStage backpressuredPropagation(CompletionStage> operatorOutput, Serializable inputMessage, - ReActorContext raCtx) { - return propagate(operatorOutput, inputMessage, raCtx) - .thenAccept(lastDelivery -> raCtx.getMbox().request(1)); + ReActorContext ctx) { + return propagate(operatorOutput, inputMessage, ctx) + .thenAccept(lastDelivery -> ctx.getMbox().request(1)); } protected CompletionStage propagate(CompletionStage> operatorOutput, - Serializable inputMessage, ReActorContext raCtx) { - Consumer onDeliveryError = error -> onFailedDelivery(error, raCtx, inputMessage); + Serializable inputMessage, ReActorContext ctx) { + Consumer onDeliveryError = error -> onFailedDelivery(error, ctx, inputMessage); return operatorOutput.thenCompose(messages -> routeOutputMessageAfterFiltering(messages).entrySet().stream() .map(msgToDst -> forwardToOperators(onDeliveryError, msgToDst.getValue(), - raCtx, msgToDst.getKey())) + ctx, msgToDst.getKey())) .reduce((first, second) -> ReActedUtils.composeDeliveries(first, second, onDeliveryError)) .orElse(CompletableFuture.completedStage(DeliveryStatus.DELIVERED))); } @@ -186,17 +186,17 @@ protected CompletionStage backpressuredPropagation(CompletionStage forwardToOperators(Consumer onDeliveryError, Collection messages, - ReActorContext raCtx, Collection nextStages) { + ReActorContext ctx, Collection nextStages) { return messages.stream() .flatMap(output -> nextStages.stream() - .map(dst -> dst.apublish(raCtx.getSelf(), output))) + .map(dst -> dst.apublish(ctx.getSelf(), output))) .reduce((first, second) -> composeDeliveries(first, second, onDeliveryError)) .orElseGet(() -> CompletableFuture.completedFuture(DeliveryStatus.DELIVERED)); } @SuppressWarnings("SameReturnValue") protected - DeliveryStatus onFailedDelivery(Throwable error, ReActorContext raCtx, InputT message) { - onLinkError(error, raCtx, message); + DeliveryStatus onFailedDelivery(Throwable error, ReActorContext ctx, InputT message) { + onLinkError(error, ctx, message); return DeliveryStatus.NOT_DELIVERED; } diff --git a/flow/src/main/java/io/reacted/flow/operators/map/MapOperator.java b/flow/src/main/java/io/reacted/flow/operators/map/MapOperator.java index ef8e8f92..4c034c69 100644 --- a/flow/src/main/java/io/reacted/flow/operators/map/MapOperator.java +++ b/flow/src/main/java/io/reacted/flow/operators/map/MapOperator.java @@ -32,7 +32,7 @@ protected MapOperator(MapOperatorConfig config) { @Override protected CompletionStage> - onNext(Serializable input, ReActorContext raCtx) { + onNext(Serializable input, ReActorContext ctx) { return CompletableFuture.completedStage(mappingFunction.apply(input)); } } diff --git a/flow/src/main/java/io/reacted/flow/operators/reduce/ReducingOperator.java b/flow/src/main/java/io/reacted/flow/operators/reduce/ReducingOperator.java index dc369e1d..4bb652ef 100644 --- a/flow/src/main/java/io/reacted/flow/operators/reduce/ReducingOperator.java +++ b/flow/src/main/java/io/reacted/flow/operators/reduce/ReducingOperator.java @@ -39,7 +39,7 @@ protected ReducingOperator(ConfigT config) { @Override protected CompletionStage> - onNext(Serializable input, ReActorContext raCtx) { + onNext(Serializable input, ReActorContext ctx) { Collection result = List.of(); Class inputType = input.getClass(); if (storage.containsKey(inputType)) { diff --git a/flow/src/main/java/io/reacted/flow/operators/service/ServiceOperator.java b/flow/src/main/java/io/reacted/flow/operators/service/ServiceOperator.java index d232f90e..8991fb4c 100644 --- a/flow/src/main/java/io/reacted/flow/operators/service/ServiceOperator.java +++ b/flow/src/main/java/io/reacted/flow/operators/service/ServiceOperator.java @@ -56,7 +56,7 @@ protected ServiceOperator(ServiceOperatorConfig config) { .reAct(ReActorInit.class, this::onServiceOperatorInit) .reAct(ReActorStop.class, this::onServiceOperatorStop) .reAct(RefreshServiceRequest.class, - (raCtx, refreshServiceRequest) -> onRefreshServiceRequest(raCtx)) + (ctx, refreshServiceRequest) -> onRefreshServiceRequest(ctx)) .reAct(RefreshServiceUpdate.class, this::onRefreshServiceUpdate) .reAct(config.getServiceReplyType(), this::onReply) .build(); @@ -68,38 +68,38 @@ protected ServiceOperator(ServiceOperatorConfig config) { @Override protected final CompletionStage> - onNext(Serializable input, ReActorContext raCtx) { + onNext(Serializable input, ReActorContext ctx) { - return AsyncUtils.asyncForeach(request -> service.apublish(raCtx.getSelf(), request), + return AsyncUtils.asyncForeach(request -> service.apublish(ctx.getSelf(), request), getOperatorCfg().getToServiceRequests().apply(input).iterator(), - error -> onFailedDelivery(error, raCtx, input), executorService) - .thenAccept(noVal -> raCtx.getMbox().request(1)) + error -> onFailedDelivery(error, ctx, input), executorService) + .thenAccept(noVal -> ctx.getMbox().request(1)) .thenApply(noVal -> FlowOperator.NO_OUTPUT); } @Override - protected void broadcastOperatorInitializationComplete(ReActorContext raCtx) { + protected void broadcastOperatorInitializationComplete(ReActorContext ctx) { if (!serviceInitializationMissing) { - super.broadcastOperatorInitializationComplete(raCtx); + super.broadcastOperatorInitializationComplete(ctx); } } - private void onServiceOperatorInit(ReActorContext raCtx, ReActorInit init) { - super.onInit(raCtx, init); - BackpressuringMbox.toBackpressuringMailbox(raCtx.getMbox()) + private void onServiceOperatorInit(ReActorContext ctx, ReActorInit init) { + super.onInit(ctx, init); + BackpressuringMbox.toBackpressuringMailbox(ctx.getMbox()) .ifPresent(mbox -> mbox.addNonDelayableTypes(Set.of(RefreshServiceRequest.class))); - this.serviceRefreshTask = raCtx.getReActorSystem() + this.serviceRefreshTask = ctx.getReActorSystem() .getSystemSchedulingService() .scheduleWithFixedDelay(() -> { - if (!raCtx.selfPublish(new RefreshServiceRequest()).isSent()) { - raCtx.logError("Unable to request refresh of service operators"); + if (!ctx.selfPublish(new RefreshServiceRequest()).isSent()) { + ctx.logError("Unable to request refresh of service operators"); } }, 0, getOperatorCfg().getServiceRefreshPeriod() .toNanos(), TimeUnit.NANOSECONDS); } - private void onServiceOperatorStop(ReActorContext raCtx, ReActorStop stop) { - super.onStop(raCtx, stop); + private void onServiceOperatorStop(ReActorContext ctx, ReActorStop stop) { + super.onStop(ctx, stop); if (serviceRefreshTask != null) { serviceRefreshTask.cancel(true); } @@ -108,14 +108,14 @@ private void onServiceOperatorStop(ReActorContext raCtx, ReActorStop stop) { } } - private void onRefreshServiceRequest(ReActorContext raCtx) { + private void onRefreshServiceRequest(ReActorContext ctx) { ReActedUtils.resolveServices(List.of(getOperatorCfg().getServiceSearchFilter()), - raCtx.getReActorSystem(), + ctx.getReActorSystem(), getOperatorCfg().getGateSelector(), - raCtx.getSelf().getReActorId().toString()) + ctx.getSelf().getReActorId().toString()) .thenAccept(selectedService -> { if (!selectedService.isEmpty()) { - raCtx.selfPublish(new RefreshServiceUpdate(selectedService)); + ctx.selfPublish(new RefreshServiceUpdate(selectedService)); } }); @@ -131,10 +131,10 @@ private void onRefreshServiceUpdate(ReActorContext reActorContext, } } } - private void onReply(ReActorContext raCtx, PayloadT reply) { + private void onReply(ReActorContext ctx, PayloadT reply) { propagate(CompletableFuture.supplyAsync(() -> getOperatorCfg().getFromServiceResponse() .apply(reply), executorService), - reply, raCtx); + reply, ctx); } private static class RefreshServiceRequest implements Serializable { diff --git a/streams/src/main/java/io/reacted/streams/BackpressureManager.java b/streams/src/main/java/io/reacted/streams/BackpressureManager.java index d99f60b4..c097d270 100644 --- a/streams/src/main/java/io/reacted/streams/BackpressureManager.java +++ b/streams/src/main/java/io/reacted/streams/BackpressureManager.java @@ -118,66 +118,66 @@ Function getManagerMailbox() { return mboxOwner -> bpMailboxBuilder.setRealMailboxOwner(mboxOwner).build(); } - private void onStop(ReActorContext raCtx, ReActorStop stop) { - feedGate.tell(ReActorRef.NO_REACTOR_REF, new UnsubscriptionRequest(raCtx.getSelf())); + private void onStop(ReActorContext ctx, ReActorStop stop) { + feedGate.tell(ReActorRef.NO_REACTOR_REF, new UnsubscriptionRequest(ctx.getSelf())); } - private void forwarder(ReActorContext raCtx, Object anyPayload) { + private void forwarder(ReActorContext ctx, Object anyPayload) { try { //noinspection unchecked subscriber.onNext((PayloadT) anyPayload); } catch (Exception anyException) { - errorTermination(raCtx, anyException, subscriber); + errorTermination(ctx, anyException, subscriber); } } - private void onSubscriptionReply(ReActorContext raCtx, SubscriptionReply payload) { + private void onSubscriptionReply(ReActorContext ctx, SubscriptionReply payload) { onSubscriptionCompleteTrigger.toCompletableFuture().complete(null); if (payload.isSuccess()) { Try.ofRunnable(() -> subscriber.onSubscribe(this)) - .ifError(error -> errorTermination(raCtx, error, subscriber)); + .ifError(error -> errorTermination(ctx, error, subscriber)); } else { - errorTermination(raCtx, new RemoteRegistrationException(), subscriber); + errorTermination(ctx, new RemoteRegistrationException(), subscriber); } } - private void onSubscriberError(ReActorContext raCtx, SubscriberError error) { - errorTermination(raCtx, error.getError(), subscriber); + private void onSubscriberError(ReActorContext ctx, SubscriberError error) { + errorTermination(ctx, error.getError(), subscriber); } - private void onPublisherComplete(ReActorContext raCtx, PublisherComplete publisherComplete) { - completeTermination(raCtx, subscriber); + private void onPublisherComplete(ReActorContext ctx, PublisherComplete publisherComplete) { + completeTermination(ctx, subscriber); } - private void onPublisherInterrupt(ReActorContext raCtx, PublisherInterrupt interrupt) { - completeTermination(raCtx, subscriber); + private void onPublisherInterrupt(ReActorContext ctx, PublisherInterrupt interrupt) { + completeTermination(ctx, subscriber); } - private void onInit(ReActorContext raCtx, ReActorInit init) { - this.backpressurerCtx = raCtx; - this.backpressuringMbox = raCtx.getMbox(); + private void onInit(ReActorContext ctx, ReActorInit init) { + this.backpressurerCtx = ctx; + this.backpressuringMbox = ctx.getMbox(); Consumer onSubscriptionError; onSubscriptionError = error -> { subscriber.onSubscribe(this); - errorTermination(raCtx, error, subscriber); }; - if (feedGate.tell(raCtx.getSelf(), new SubscriptionRequest(raCtx.getSelf())).isNotSent()) { + errorTermination(ctx, error, subscriber); }; + if (feedGate.tell(ctx.getSelf(), new SubscriptionRequest(ctx.getSelf())).isNotSent()) { onSubscriptionError.accept(new DeliveryException()); } } - private void completeTermination(ReActorContext raCtx, + private void completeTermination(ReActorContext ctx, Flow.Subscriber localSubscriber) { close(); Try.ofRunnable(localSubscriber::onComplete) - .ifError(error -> raCtx.logError("Error in {} onComplete: ", + .ifError(error -> ctx.logError("Error in {} onComplete: ", localSubscriber.getClass().getSimpleName(), error)); } - private void errorTermination(ReActorContext raCtx, Throwable handlingError, + private void errorTermination(ReActorContext ctx, Throwable handlingError, Flow.Subscriber localSubscriber) { close(); Try.ofRunnable(() -> localSubscriber.onError(handlingError)) - .ifError(error -> raCtx.logError("Error in {} onError: ", + .ifError(error -> ctx.logError("Error in {} onError: ", localSubscriber.getClass().getSimpleName(), error)); } } diff --git a/streams/src/main/java/io/reacted/streams/ReactedSubmissionPublisher.java b/streams/src/main/java/io/reacted/streams/ReactedSubmissionPublisher.java index fa83923e..07a5a2b8 100644 --- a/streams/src/main/java/io/reacted/streams/ReactedSubmissionPublisher.java +++ b/streams/src/main/java/io/reacted/streams/ReactedSubmissionPublisher.java @@ -98,7 +98,7 @@ public ReactedSubmissionPublisher(ReActorSystem localReActorSystem, .build(); this.feedGate = localReActorSystem.spawn(ReActions.newBuilder() .reAct(ReActorInit.class, ReActions::noReAction) - .reAct(PublisherShutdown.class, (raCtx, shutdown) -> raCtx.stop()) + .reAct(PublisherShutdown.class, (ctx, shutdown) -> ctx.stop()) .reAct(PublisherInterrupt.class, this::onInterrupt) .reAct(ReActorStop.class, this::onStop) .reAct(SubscriptionRequest.class, this::onSubscriptionRequest) @@ -234,7 +234,7 @@ public DeliveryStatus submit(PayloadT message) { return feedGate.publish(message); } - private void forwardToSubscribers(ReActorContext raCtx, Serializable payload) { + private void forwardToSubscribers(ReActorContext ctx, Serializable payload) { if (subscribers.isEmpty()) { return; } @@ -245,23 +245,23 @@ private void forwardToSubscribers(ReActorContext raCtx, Serializable payload) { Iterator subscribersIterator = subscribers.iterator(); for (int subscriberIdx = 0; subscribersIterator.hasNext(); subscriberIdx++) { subscribersRefs[subscriberIdx] = subscribersIterator.next(); - deliveries[subscriberIdx] = subscribersRefs[subscriberIdx].apublish(raCtx.getSelf(), payload); + deliveries[subscriberIdx] = subscribersRefs[subscriberIdx].apublish(ctx.getSelf(), payload); } CompletionStage result = deliveries[0]; for(int subscriberIdx = 1; subscriberIdx < deliveries.length; subscriberIdx++) { - result = combineStages(raCtx.getSelf(), + result = combineStages(ctx.getSelf(), result, subscribersRefs[subscriberIdx - 1], deliveries[subscriberIdx], subscribersRefs[subscriberIdx]); } result.handle((deliveryStatus, error) -> { if (deliveryStatus.isBackpressureRequired()) { - raCtx.getReActorSystem().getSystemSchedulingService() - .schedule(() -> raCtx.getMbox().request(1), + ctx.getReActorSystem().getSystemSchedulingService() + .schedule(() -> ctx.getMbox().request(1), streamBackpressureTimeout.toMillis(), TimeUnit.MILLISECONDS); streamBackpressureTimeout = streamBackpressureTimeout.multipliedBy(2); } else { - raCtx.getMbox().request(1); + ctx.getMbox().request(1); if (streamBackpressureTimeout.compareTo(BACKPRESSURE_DELAY_BASE) > 0) { this.streamBackpressureTimeout = Duration.ofMillis(Math.max(BACKPRESSURE_DELAY_BASE.toMillis(), streamBackpressureTimeout.toMillis()/2)); @@ -293,30 +293,30 @@ private CompletionStage combineStages(ReActorRef feedGate, })); } - private void onInterrupt(ReActorContext raCtx, PublisherInterrupt interrupt) { - subscribers.forEach(subscriber -> subscriber.publish(raCtx.getSelf(), interrupt)); + private void onInterrupt(ReActorContext ctx, PublisherInterrupt interrupt) { + subscribers.forEach(subscriber -> subscriber.publish(ctx.getSelf(), interrupt)); subscribers.clear(); - raCtx.stop(); + ctx.stop(); } - private void onStop(ReActorContext raCtx, ReActorStop stop) { + private void onStop(ReActorContext ctx, ReActorStop stop) { subscribers.forEach(subscriber -> { - if(subscriber.tell(raCtx.getSelf(), new PublisherComplete()).isNotSent()) { - raCtx.logError("Unable to stop subscriber {}", subscriber); + if(subscriber.tell(ctx.getSelf(), new PublisherComplete()).isNotSent()) { + ctx.logError("Unable to stop subscriber {}", subscriber); } }); subscribers.clear(); } - private void onSubscriptionRequest(ReActorContext raCtx, SubscriptionRequest subscription) { + private void onSubscriptionRequest(ReActorContext ctx, SubscriptionRequest subscription) { var backpressuringManager = subscription.subscriptionBackpressuringManager(); - ifNotDelivered(backpressuringManager.apublish(raCtx.getSelf(), + ifNotDelivered(backpressuringManager.apublish(ctx.getSelf(), new SubscriptionReply(subscribers.add(backpressuringManager))), - error -> raCtx.logError("Unable to deliver subscription confirmation to {}", + error -> ctx.logError("Unable to deliver subscription confirmation to {}", subscription.subscriptionBackpressuringManager(), error)); } - private void onUnSubscriptionRequest(ReActorContext raCtx, UnsubscriptionRequest unsubscriptionRequest) { + private void onUnSubscriptionRequest(ReActorContext ctx, UnsubscriptionRequest unsubscriptionRequest) { subscribers.remove(unsubscriptionRequest.subscriptionBackpressuringManager()); } diff --git a/streams/src/test/java/io/reacted/streams/DistributedPublisherTest.java b/streams/src/test/java/io/reacted/streams/DistributedPublisherTest.java index 4e14c021..30117529 100644 --- a/streams/src/test/java/io/reacted/streams/DistributedPublisherTest.java +++ b/streams/src/test/java/io/reacted/streams/DistributedPublisherTest.java @@ -108,11 +108,11 @@ public ReActions getReActions() { .build(); } - private void onMessage(ReActorContext raCtx, Serializable message) { + private void onMessage(ReActorContext ctx, Serializable message) { publisher.submit(message); subscription.request(1); } - private void onPublisher(ReActorContext raCtx,ReactedSubmissionPublisher publisher) { + private void onPublisher(ReActorContext ctx,ReactedSubmissionPublisher publisher) { this.publisher = publisher; publisher.subscribe(new Subscriber<>() { @Override @@ -122,13 +122,13 @@ public void onSubscribe(Subscription subscription) { } @Override - public void onNext(Serializable item) { raCtx.selfPublish(item); } + public void onNext(Serializable item) { ctx.selfPublish(item); } @Override public void onError(Throwable throwable) { fail(throwable); } @Override - public void onComplete() { subscription.cancel(); raCtx.stop(); } + public void onComplete() { subscription.cancel(); ctx.stop(); } }); } } From 29259e318da7112f041d6c91083cf7fa3f57c8e3 Mon Sep 17 00:00:00 2001 From: wireknight Date: Mon, 12 Dec 2022 19:39:02 +0100 Subject: [PATCH 02/16] Reactor Context default name change Datalink Object removed --- .../io/reacted/core/messages/DataLink.java | 68 ------------------- .../io/reacted/core/messages/Message.java | 39 +++++++---- .../core/drivers/system/LocalDriverTest.java | 12 ++-- .../drivers/channels/kafka/KafkaDriver.java | 4 +- .../channels/replay/ReplayLocalDriver.java | 4 +- .../reacted/flow/operators/FlowOperator.java | 3 +- .../operators/service/ServiceOperator.java | 6 +- 7 files changed, 40 insertions(+), 96 deletions(-) delete mode 100644 core/src/main/java/io/reacted/core/messages/DataLink.java diff --git a/core/src/main/java/io/reacted/core/messages/DataLink.java b/core/src/main/java/io/reacted/core/messages/DataLink.java deleted file mode 100644 index 36080dbc..00000000 --- a/core/src/main/java/io/reacted/core/messages/DataLink.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2020 , [ pierre@reacted.io ] - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. - */ - -package io.reacted.core.messages; - -import io.reacted.core.reactorsystem.ReActorSystemId; -import io.reacted.patterns.NonNullByDefault; - -import java.io.Externalizable; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; -import java.util.Objects; - -@NonNullByDefault -public class DataLink implements Externalizable { - public static final DataLink NO_DATALINK = new DataLink(); - private static final long GENERATING_REACTORSYSTEM_OFFSET = SerializationUtils.getFieldOffset(DataLink.class, - "generatingReActorSystem") - .orElseSneakyThrow(); - private static final long ACKING_POLICY_OFFSET = SerializationUtils.getFieldOffset(DataLink.class, "ackingPolicy") - .orElseSneakyThrow(); - - private final ReActorSystemId generatingReActorSystem; - private final AckingPolicy ackingPolicy; - - public DataLink() { - /* Required by externalizable */ - this.generatingReActorSystem = ReActorSystemId.NO_REACTORSYSTEM_ID; - this.ackingPolicy = AckingPolicy.NONE; - } - - DataLink(ReActorSystemId generatingReActorSystem, AckingPolicy ackingPolicy) { - this.generatingReActorSystem = generatingReActorSystem; - this.ackingPolicy = ackingPolicy; - } - - public ReActorSystemId getGeneratingReActorSystem() { return generatingReActorSystem; } - - public AckingPolicy getAckingPolicy() { return ackingPolicy; } - - @Override - public void writeExternal(ObjectOutput out) throws IOException { - Objects.requireNonNull(generatingReActorSystem).writeExternal(out); - out.writeInt(Objects.requireNonNull(ackingPolicy).ordinal()); - } - - @Override - public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { - var receivedGeneratingReActorSystem = new ReActorSystemId(); - receivedGeneratingReActorSystem.readExternal(in); - setGeneratingReActorSystem(receivedGeneratingReActorSystem); - setAckingPolicy(AckingPolicy.forOrdinal(in.readInt())); - } - - public void setGeneratingReActorSystem(ReActorSystemId generatingReActorSystem) { - SerializationUtils.setObjectField(this, GENERATING_REACTORSYSTEM_OFFSET, generatingReActorSystem); - } - - public void setAckingPolicy(AckingPolicy ackingPolicy) { - SerializationUtils.setObjectField(this, ACKING_POLICY_OFFSET, ackingPolicy); - } -} diff --git a/core/src/main/java/io/reacted/core/messages/Message.java b/core/src/main/java/io/reacted/core/messages/Message.java index e42e2a42..989291e2 100644 --- a/core/src/main/java/io/reacted/core/messages/Message.java +++ b/core/src/main/java/io/reacted/core/messages/Message.java @@ -33,13 +33,18 @@ public final class Message implements Externalizable { .orElseSneakyThrow(); private static final long PAYLOAD_OFFSET = SerializationUtils.getFieldOffset(Message.class, "payload") .orElseSneakyThrow(); - private static final long DATALINK_OFFSET = SerializationUtils.getFieldOffset(Message.class, "dataLink") - .orElseSneakyThrow(); + private static final long GENERATING_REACTORSYSTEM_OFFSET = SerializationUtils.getFieldOffset(Message.class, + "generatingReActorSystem") + .orElseSneakyThrow(); + private static final long ACKING_POLICY_OFFSET = SerializationUtils.getFieldOffset(Message.class, "ackingPolicy") + .orElseSneakyThrow(); + private final ReActorRef sender; private final ReActorRef destination; private final long sequenceNumber; + private final ReActorSystemId generatingReActorSystem; + private final AckingPolicy ackingPolicy; private final Serializable payload; - private final DataLink dataLink; public Message() { /* Required by Externalizable */ @@ -47,7 +52,8 @@ public Message() { this.destination = ReActorRef.NO_REACTOR_REF; this.sequenceNumber = 0; this.payload = SerializationUtils.NO_PAYLOAD; - this.dataLink = DataLink.NO_DATALINK; + this.generatingReActorSystem = ReActorSystemId.NO_REACTORSYSTEM_ID; + this.ackingPolicy = AckingPolicy.NONE; } public Message(ReActorRef sender, ReActorRef dest, long seqNum, ReActorSystemId generatingReActorSystem, @@ -55,7 +61,8 @@ public Message(ReActorRef sender, ReActorRef dest, long seqNum, ReActorSystemId this.sender = sender; this.destination = dest; this.sequenceNumber = seqNum; - this.dataLink = new DataLink(generatingReActorSystem, ackingPolicy); + this.generatingReActorSystem = generatingReActorSystem; + this.ackingPolicy = ackingPolicy; this.payload = payload; } @@ -68,7 +75,9 @@ public Message(ReActorRef sender, ReActorRef dest, long seqNum, ReActorSystemId public long getSequenceNumber() { return sequenceNumber; } - public DataLink getDataLink() { return dataLink; } + public ReActorSystemId getGeneratingReActorSystem() { return generatingReActorSystem; } + + public AckingPolicy getAckingPolicy() { return ackingPolicy; } @Override public boolean equals(@Nullable Object o) { @@ -99,7 +108,8 @@ public String toString() { public void writeExternal(ObjectOutput out) throws IOException { Objects.requireNonNull(sender).writeExternal(out); Objects.requireNonNull(destination).writeExternal(out); - Objects.requireNonNull(dataLink).writeExternal(out); + Objects.requireNonNull(generatingReActorSystem).writeExternal(out); + out.writeInt(ackingPolicy.ordinal()); out.writeLong(sequenceNumber); out.writeObject(payload); } @@ -112,9 +122,10 @@ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundExcept var destinationRef = new ReActorRef(); destinationRef.readExternal(in); setDestination(destinationRef); - var datalink = new DataLink(); - datalink.readExternal(in); - setDataLink(datalink); + var receivedGeneratingReActorSystem = new ReActorSystemId(); + receivedGeneratingReActorSystem.readExternal(in); + setGeneratingReActorSystem(receivedGeneratingReActorSystem); + setAckingPolicy(AckingPolicy.forOrdinal(in.readInt())); setSequenceNumber(in.readLong()); try { setPayload((Serializable)in.readObject()); @@ -134,8 +145,12 @@ private Message setDestination(ReActorRef destination) { } @SuppressWarnings("UnusedReturnValue") - private Message setDataLink(DataLink dataLink) { - return SerializationUtils.setObjectField(this, DATALINK_OFFSET, dataLink); + private void setGeneratingReActorSystem(ReActorSystemId generatingReActorSystem) { + SerializationUtils.setObjectField(this, GENERATING_REACTORSYSTEM_OFFSET, generatingReActorSystem); + } + + private void setAckingPolicy(AckingPolicy ackingPolicy) { + SerializationUtils.setObjectField(this, ACKING_POLICY_OFFSET, ackingPolicy); } @SuppressWarnings("UnusedReturnValue") diff --git a/core/src/test/java/io/reacted/core/drivers/system/LocalDriverTest.java b/core/src/test/java/io/reacted/core/drivers/system/LocalDriverTest.java index a2b509c4..f53cc1e1 100644 --- a/core/src/test/java/io/reacted/core/drivers/system/LocalDriverTest.java +++ b/core/src/test/java/io/reacted/core/drivers/system/LocalDriverTest.java @@ -90,8 +90,8 @@ void localDriverDeliversMessagesInMailBox() { Assertions.assertTrue(localDriver.sendMessage(originalMsg.getSender(), reActorContext, originalMsg.getDestination(), originalMsg.getSequenceNumber(), - originalMsg.getDataLink().getGeneratingReActorSystem(), - originalMsg.getDataLink().getAckingPolicy(), + originalMsg.getGeneratingReActorSystem(), + originalMsg.getAckingPolicy(), originalMsg.getPayload()).isDelivered()); Assertions.assertEquals(1, unboundedMbox.getMsgNum()); @@ -104,8 +104,8 @@ void localDriverForwardsMessageToLocalActor() { Assertions.assertTrue(LocalDriver.syncForwardMessageToLocalActor(originalMsg.getSender(), reActorContext, originalMsg.getDestination(), originalMsg.getSequenceNumber(), - originalMsg.getDataLink().getGeneratingReActorSystem(), - originalMsg.getDataLink().getAckingPolicy(), + originalMsg.getGeneratingReActorSystem(), + originalMsg.getAckingPolicy(), originalMsg.getPayload()) .isDelivered()); Assertions.assertEquals(originalMsg, unboundedMbox.getNextMessage()); @@ -116,8 +116,8 @@ void localDriverCanSendMessage() { Assertions.assertTrue(localDriver.sendMessage(originalMsg.getSender(), reActorContext, originalMsg.getDestination(), originalMsg.getSequenceNumber(), - originalMsg.getDataLink().getGeneratingReActorSystem(), - originalMsg.getDataLink().getAckingPolicy(), + originalMsg.getGeneratingReActorSystem(), + originalMsg.getAckingPolicy(), originalMsg.getPayload()).isDelivered()); Assertions.assertEquals(originalMsg, unboundedMbox.getNextMessage()); } diff --git a/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaDriver.java b/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaDriver.java index 42227120..93f12b1c 100644 --- a/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaDriver.java +++ b/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaDriver.java @@ -140,8 +140,8 @@ private static void kafkaDriverLoop(Consumer kafkaConsumer, Kafka .forEach(record -> thisDriver.offerMessage(record.value().getSender(), record.value().getDestination(), record.value().getSequenceNumber(), - record.value().getDataLink().getGeneratingReActorSystem(), - record.value().getDataLink().getAckingPolicy(), + record.value().getGeneratingReActorSystem(), + record.value().getAckingPolicy(), record.value().getPayload())); } catch (InterruptException interruptException) { Thread.currentThread().interrupt(); diff --git a/drivers/src/main/java/io/reacted/drivers/channels/replay/ReplayLocalDriver.java b/drivers/src/main/java/io/reacted/drivers/channels/replay/ReplayLocalDriver.java index db0b6e66..c80415a6 100644 --- a/drivers/src/main/java/io/reacted/drivers/channels/replay/ReplayLocalDriver.java +++ b/drivers/src/main/java/io/reacted/drivers/channels/replay/ReplayLocalDriver.java @@ -164,8 +164,8 @@ void onNewMessage(ReActorSystem localReActorSystem, Map emptyMap, } else if (syncForwardMessageToLocalActor(originalMessage.getSender(), destinationCtx, originalMessage.getDestination(), originalMessage.getSequenceNumber(), - originalMessage.getDataLink().getGeneratingReActorSystem(), - originalMessage.getDataLink().getAckingPolicy(), + originalMessage.getGeneratingReActorSystem(), + originalMessage.getAckingPolicy(), originalMessage.getPayload()).isNotDelivered()) { LOGGER.error("Unable to delivery message {} for ReActor {}", originalMessage, executionAttempt.getReActorId()); diff --git a/flow/src/main/java/io/reacted/flow/operators/FlowOperator.java b/flow/src/main/java/io/reacted/flow/operators/FlowOperator.java index f620f1be..74a1a2f3 100644 --- a/flow/src/main/java/io/reacted/flow/operators/FlowOperator.java +++ b/flow/src/main/java/io/reacted/flow/operators/FlowOperator.java @@ -44,8 +44,7 @@ @NonNullByDefault @Unstable public abstract class FlowOperator, - CfgT extends FlowOperatorConfig> - implements ReActor { + CfgT extends FlowOperatorConfig> implements ReActor { public static final Collection NO_OUTPUT = List.of(); private final ReActions operatorReactions; private final CfgT operatorCfg; diff --git a/flow/src/main/java/io/reacted/flow/operators/service/ServiceOperator.java b/flow/src/main/java/io/reacted/flow/operators/service/ServiceOperator.java index 8991fb4c..13764a64 100644 --- a/flow/src/main/java/io/reacted/flow/operators/service/ServiceOperator.java +++ b/flow/src/main/java/io/reacted/flow/operators/service/ServiceOperator.java @@ -34,8 +34,7 @@ import java.util.concurrent.TimeUnit; @NonNullByDefault -public class ServiceOperator extends FlowOperator { +public class ServiceOperator extends FlowOperator { private final ReActions reActions; private final ExecutorService executorService; private final boolean shallStopExecutorService; @@ -144,6 +143,5 @@ public String toString() { } } - private record RefreshServiceUpdate(Collection serviceGates) implements Serializable { - } + private record RefreshServiceUpdate(Collection serviceGates) implements Serializable { } } From a04839b76e44eed4aa958208e04ed7c6d86fc5ff Mon Sep 17 00:00:00 2001 From: wireknight Date: Mon, 12 Dec 2022 20:02:24 +0100 Subject: [PATCH 03/16] Reactor Context default name change Datalink Object removed --- .../local/DirectCommunicationDriver.java | 4 +- .../io/reacted/core/messages/Message.java | 107 ++++++++---------- .../core/reactorsystem/ReActorSystem.java | 10 +- .../java/io/reacted/core/MessageHelper.java | 6 +- .../core/drivers/system/LocalDriverTest.java | 4 +- .../drivers/system/LoopbackDriverTest.java | 4 +- .../core/mailboxes/PriorityMailboxTest.java | 10 +- .../core/mailboxes/UnboundedMboxTest.java | 9 +- .../core/reactorsystem/ReActorSystemTest.java | 6 +- .../drivers/channels/kafka/KafkaDriver.java | 6 +- .../channels/replay/ReplayLocalDriver.java | 5 +- 11 files changed, 78 insertions(+), 93 deletions(-) diff --git a/core/src/main/java/io/reacted/core/drivers/local/DirectCommunicationDriver.java b/core/src/main/java/io/reacted/core/drivers/local/DirectCommunicationDriver.java index 01feb7b8..1ab9d173 100644 --- a/core/src/main/java/io/reacted/core/drivers/local/DirectCommunicationDriver.java +++ b/core/src/main/java/io/reacted/core/drivers/local/DirectCommunicationDriver.java @@ -68,7 +68,7 @@ public Properties getChannelProperties() { long seqNum, ReActorSystemId reActorSystemId, AckingPolicy ackingPolicy, PayloadT message) { return destinationCtx.isStop() ? DeliveryStatus.NOT_DELIVERED - : localDeliver(destinationCtx, new Message(source, destination, seqNum, reActorSystemId, - ackingPolicy, message)); + : localDeliver(destinationCtx, + Message.forParams(source, destination, seqNum, reActorSystemId, ackingPolicy, message)); } } diff --git a/core/src/main/java/io/reacted/core/messages/Message.java b/core/src/main/java/io/reacted/core/messages/Message.java index 989291e2..fcd6c020 100644 --- a/core/src/main/java/io/reacted/core/messages/Message.java +++ b/core/src/main/java/io/reacted/core/messages/Message.java @@ -25,28 +25,14 @@ public final class Message implements Externalizable { @Serial private static final long serialVersionUID = 1; - private static final long SENDER_OFFSET = SerializationUtils.getFieldOffset(Message.class, "sender") - .orElseSneakyThrow(); - private static final long DESTINATION_OFFSET = SerializationUtils.getFieldOffset(Message.class, "destination") - .orElseSneakyThrow(); - private static final long SEQ_NUM_OFFSET = SerializationUtils.getFieldOffset(Message.class, "sequenceNumber") - .orElseSneakyThrow(); - private static final long PAYLOAD_OFFSET = SerializationUtils.getFieldOffset(Message.class, "payload") - .orElseSneakyThrow(); - private static final long GENERATING_REACTORSYSTEM_OFFSET = SerializationUtils.getFieldOffset(Message.class, - "generatingReActorSystem") - .orElseSneakyThrow(); - private static final long ACKING_POLICY_OFFSET = SerializationUtils.getFieldOffset(Message.class, "ackingPolicy") - .orElseSneakyThrow(); - - private final ReActorRef sender; - private final ReActorRef destination; - private final long sequenceNumber; - private final ReActorSystemId generatingReActorSystem; - private final AckingPolicy ackingPolicy; - private final Serializable payload; - - public Message() { + private ReActorRef sender; + private ReActorRef destination; + private long sequenceNumber; + private ReActorSystemId generatingReActorSystem; + private AckingPolicy ackingPolicy; + private Serializable payload; + + private Message() { /* Required by Externalizable */ this.sender = ReActorRef.NO_REACTOR_REF; this.destination = ReActorRef.NO_REACTOR_REF; @@ -56,29 +42,17 @@ public Message() { this.ackingPolicy = AckingPolicy.NONE; } - public Message(ReActorRef sender, ReActorRef dest, long seqNum, ReActorSystemId generatingReActorSystem, - AckingPolicy ackingPolicy, Serializable payload) { - this.sender = sender; - this.destination = dest; - this.sequenceNumber = seqNum; - this.generatingReActorSystem = generatingReActorSystem; - this.ackingPolicy = ackingPolicy; - this.payload = payload; + public static Message forParams(ReActorRef sender, ReActorRef dest, long seqNum, ReActorSystemId generatingReActorSystem, + AckingPolicy ackingPolicy, Serializable payload) { + Message message = new Message(); + return message.setSender(sender) + .setDestination(dest) + .setSequenceNumber(seqNum) + .setGeneratingReActorSystem(generatingReActorSystem) + .setAckingPolicy(ackingPolicy) + .setPayload(payload); } - public ReActorRef getSender() { return sender; } - - public ReActorRef getDestination() { return destination; } - - @SuppressWarnings("unchecked") - public PayloadT getPayload() { return (PayloadT)payload; } - - public long getSequenceNumber() { return sequenceNumber; } - - public ReActorSystemId getGeneratingReActorSystem() { return generatingReActorSystem; } - - public AckingPolicy getAckingPolicy() { return ackingPolicy; } - @Override public boolean equals(@Nullable Object o) { if (this == o) return true; @@ -134,32 +108,43 @@ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundExcept } } - @SuppressWarnings("UnusedReturnValue") - private Message setSender(ReActorRef sender) { - return SerializationUtils.setObjectField(this, SENDER_OFFSET, sender); - } + public ReActorRef getSender() { return sender; } + + public ReActorRef getDestination() { return destination; } + + public long getSequenceNumber() { return sequenceNumber; } + + public ReActorSystemId getGeneratingReActorSystem() { return generatingReActorSystem; } - @SuppressWarnings("UnusedReturnValue") - private Message setDestination(ReActorRef destination) { - return SerializationUtils.setObjectField(this, DESTINATION_OFFSET, destination); + public AckingPolicy getAckingPolicy() { return ackingPolicy; } + + public PayloadT getPayload() { return (PayloadT)payload; } + public Message setSender(ReActorRef sender) { + this.sender = sender; + return this; } - @SuppressWarnings("UnusedReturnValue") - private void setGeneratingReActorSystem(ReActorSystemId generatingReActorSystem) { - SerializationUtils.setObjectField(this, GENERATING_REACTORSYSTEM_OFFSET, generatingReActorSystem); + public Message setDestination(ReActorRef destination) { + this.destination = destination; + return this; } - private void setAckingPolicy(AckingPolicy ackingPolicy) { - SerializationUtils.setObjectField(this, ACKING_POLICY_OFFSET, ackingPolicy); + public Message setSequenceNumber(long sequenceNumber) { + this.sequenceNumber = sequenceNumber; + return this; } - @SuppressWarnings("UnusedReturnValue") - private Message setSequenceNumber(long sequenceNumber) { - return SerializationUtils.setLongField(this, SEQ_NUM_OFFSET, sequenceNumber); + public Message setGeneratingReActorSystem(ReActorSystemId generatingReActorSystem) { + this.generatingReActorSystem = generatingReActorSystem; + return this; } - @SuppressWarnings("UnusedReturnValue") - private Message setPayload(Serializable payload) { - return SerializationUtils.setObjectField(this, PAYLOAD_OFFSET, payload); + public Message setAckingPolicy(AckingPolicy ackingPolicy) { + this.ackingPolicy = ackingPolicy; + return this; + } + public Message setPayload(Serializable payload) { + this.payload = payload; + return this; } } diff --git a/core/src/main/java/io/reacted/core/reactorsystem/ReActorSystem.java b/core/src/main/java/io/reacted/core/reactorsystem/ReActorSystem.java index 371da5f9..ff1de2ad 100644 --- a/core/src/main/java/io/reacted/core/reactorsystem/ReActorSystem.java +++ b/core/src/main/java/io/reacted/core/reactorsystem/ReActorSystem.java @@ -159,9 +159,9 @@ private ReActorSystem() { this.gatesCentralizedManager = new RegistryGatesCentralizedManager(localReActorSystemId, new LoopbackDriver<>(this, getSystemConfig().getLocalDriver())); this.newSeqNum = new AtomicLong(Long.MAX_VALUE); - this.reActorStop = new Message(ReActorRef.NO_REACTOR_REF, ReActorRef.NO_REACTOR_REF, - Long.MIN_VALUE, localReActorSystemId, AckingPolicy.NONE, - ReActorStop.STOP); + this.reActorStop = Message.forParams(ReActorRef.NO_REACTOR_REF, ReActorRef.NO_REACTOR_REF, + Long.MIN_VALUE, localReActorSystemId, AckingPolicy.NONE, + ReActorStop.STOP); } public ReActorSystem(ReActorSystemConfig config) { @@ -176,8 +176,8 @@ public ReActorSystem(ReActorSystemConfig config) { this.typedSubscriptionsManager = new TypedSubscriptionsManager(); this.dispatchers = new ConcurrentHashMap<>(10, 0.5f); this.newSeqNum = new AtomicLong(0); - this.reActorStop = new Message(ReActorRef.NO_REACTOR_REF, ReActorRef.NO_REACTOR_REF, Long.MIN_VALUE, - localReActorSystemId, AckingPolicy.NONE, ReActorStop.STOP); + this.reActorStop = Message.forParams(ReActorRef.NO_REACTOR_REF, ReActorRef.NO_REACTOR_REF, Long.MIN_VALUE, + localReActorSystemId, AckingPolicy.NONE, ReActorStop.STOP); } /** * @return The configuration for the reactor system diff --git a/core/src/test/java/io/reacted/core/MessageHelper.java b/core/src/test/java/io/reacted/core/MessageHelper.java index 856fd340..850f98ca 100644 --- a/core/src/test/java/io/reacted/core/MessageHelper.java +++ b/core/src/test/java/io/reacted/core/MessageHelper.java @@ -6,8 +6,8 @@ public class MessageHelper { public static Message getDefaultMessage() { - return new Message(ReActorRef.NO_REACTOR_REF, ReActorRef.NO_REACTOR_REF, 0x31337, - ReactorHelper.TEST_REACTOR_SYSTEM_ID, AckingPolicy.NONE, - CoreConstants.DE_SERIALIZATION_SUCCESSFUL); + return Message.forParams(ReActorRef.NO_REACTOR_REF, ReActorRef.NO_REACTOR_REF, 0x31337, + ReactorHelper.TEST_REACTOR_SYSTEM_ID, AckingPolicy.NONE, + CoreConstants.DE_SERIALIZATION_SUCCESSFUL); } } diff --git a/core/src/test/java/io/reacted/core/drivers/system/LocalDriverTest.java b/core/src/test/java/io/reacted/core/drivers/system/LocalDriverTest.java index f53cc1e1..40567799 100644 --- a/core/src/test/java/io/reacted/core/drivers/system/LocalDriverTest.java +++ b/core/src/test/java/io/reacted/core/drivers/system/LocalDriverTest.java @@ -81,8 +81,8 @@ static void prepareLocalDriver() throws Exception { .setReActions(mock(ReActions.class)) .build(); - originalMsg = new Message(ReActorRef.NO_REACTOR_REF, reActorRef, 0x31337, ReactorHelper.TEST_REACTOR_SYSTEM_ID, - AckingPolicy.NONE, CoreConstants.DE_SERIALIZATION_SUCCESSFUL); + originalMsg = Message.forParams(ReActorRef.NO_REACTOR_REF, reActorRef, 0x31337, ReactorHelper.TEST_REACTOR_SYSTEM_ID, + AckingPolicy.NONE, CoreConstants.DE_SERIALIZATION_SUCCESSFUL); } @Test diff --git a/core/src/test/java/io/reacted/core/drivers/system/LoopbackDriverTest.java b/core/src/test/java/io/reacted/core/drivers/system/LoopbackDriverTest.java index 681eaef1..9a7ce9b9 100644 --- a/core/src/test/java/io/reacted/core/drivers/system/LoopbackDriverTest.java +++ b/core/src/test/java/io/reacted/core/drivers/system/LoopbackDriverTest.java @@ -62,8 +62,8 @@ void prepareEnvironment() throws Exception { destReActorRef = reActorSystem.spawn(new MagicTestReActor(1, true, reActorConfig)) .orElseSneakyThrow(); - message = new Message(ReActorRef.NO_REACTOR_REF, destReActorRef, 0, reActorSystem.getLocalReActorSystemId(), - AckingPolicy.NONE, "payload"); + message = Message.forParams(ReActorRef.NO_REACTOR_REF, destReActorRef, 0, reActorSystem.getLocalReActorSystemId(), + AckingPolicy.NONE, "payload"); } @AfterEach diff --git a/core/src/test/java/io/reacted/core/mailboxes/PriorityMailboxTest.java b/core/src/test/java/io/reacted/core/mailboxes/PriorityMailboxTest.java index 3ad73bc6..b2d7c2ec 100644 --- a/core/src/test/java/io/reacted/core/mailboxes/PriorityMailboxTest.java +++ b/core/src/test/java/io/reacted/core/mailboxes/PriorityMailboxTest.java @@ -35,8 +35,8 @@ static void prepareMessages() { testMsgSrc = ReactorHelper.generateReactor(CoreConstants.SOURCE); testMsgDst = ReactorHelper.generateReactor(CoreConstants.DESTINATION); - originalMsg = new Message(testMsgSrc, testMsgDst, 0x31337, ReactorHelper.TEST_REACTOR_SYSTEM_ID, - AckingPolicy.NONE, "De/Serialization Successful!"); + originalMsg = Message.forParams(testMsgSrc, testMsgDst, 0x31337, ReactorHelper.TEST_REACTOR_SYSTEM_ID, + AckingPolicy.NONE, "De/Serialization Successful!"); } @BeforeEach @@ -90,7 +90,7 @@ void messageWithHigherPriorityProvidedFirstThenNormalPriorityApplied() { ReactorHelper.generateReactor(CoreConstants.DESTINATION + PRIORITY_2); Message message4 = - new Message(highPrioMsgSrc2, highPrioMsgDest2, 0x31337, ReactorHelper.TEST_REACTOR_SYSTEM_ID, + Message.forParams(highPrioMsgSrc2, highPrioMsgDest2, 0x31337, ReactorHelper.TEST_REACTOR_SYSTEM_ID, AckingPolicy.NONE, CoreConstants.HIGH_PRIORITY); priorityMailbox1.deliver(message1); @@ -105,8 +105,8 @@ void messageWithHigherPriorityProvidedFirstThenNormalPriorityApplied() { } private Message createMessage(String payload) { - return new Message(testMsgSrc, testMsgDst, 0x31337, ReactorHelper.TEST_REACTOR_SYSTEM_ID, - AckingPolicy.NONE, payload); + return Message.forParams(testMsgSrc, testMsgDst, 0x31337, ReactorHelper.TEST_REACTOR_SYSTEM_ID, + AckingPolicy.NONE, payload); } private final static Comparator PAYLOAD_COMPARATOR = diff --git a/core/src/test/java/io/reacted/core/mailboxes/UnboundedMboxTest.java b/core/src/test/java/io/reacted/core/mailboxes/UnboundedMboxTest.java index 5c5c4a97..ef8fc346 100644 --- a/core/src/test/java/io/reacted/core/mailboxes/UnboundedMboxTest.java +++ b/core/src/test/java/io/reacted/core/mailboxes/UnboundedMboxTest.java @@ -29,8 +29,8 @@ static void prepareMessages() { testMsgSrc = ReactorHelper.generateReactor(CoreConstants.SOURCE); testMsgDst = ReactorHelper.generateReactor(CoreConstants.DESTINATION); - originalMsg = new Message(testMsgSrc, testMsgDst, 0x31337, ReactorHelper.TEST_REACTOR_SYSTEM_ID, - AckingPolicy.NONE, CoreConstants.DE_SERIALIZATION_SUCCESSFUL); + originalMsg = Message.forParams(testMsgSrc, testMsgDst, 0x31337, ReactorHelper.TEST_REACTOR_SYSTEM_ID, + AckingPolicy.NONE, CoreConstants.DE_SERIALIZATION_SUCCESSFUL); } @BeforeEach @@ -81,9 +81,8 @@ void getNextMessageReturnsMessagesInTheOrderTheyWereSent() { ReActorRef testMsgSrc2 = ReactorHelper.generateReactor("source2"); ReActorRef testMsgDst2 = ReactorHelper.generateReactor("destination2"); - Message originalMsg2 = - new Message(testMsgSrc2, testMsgDst2, 0x31337, ReactorHelper.TEST_REACTOR_SYSTEM_ID, - AckingPolicy.NONE, "De/Serialization Successful!"); + Message originalMsg2 = Message.forParams(testMsgSrc2, testMsgDst2, 0x31337, + ReactorHelper.TEST_REACTOR_SYSTEM_ID, AckingPolicy.NONE, "De/Serialization Successful!"); unboundedMbox.deliver(originalMsg2); Assertions.assertEquals(2, unboundedMbox.getMsgNum()); diff --git a/core/src/test/java/io/reacted/core/reactorsystem/ReActorSystemTest.java b/core/src/test/java/io/reacted/core/reactorsystem/ReActorSystemTest.java index 72fd2ea0..2c37aa41 100644 --- a/core/src/test/java/io/reacted/core/reactorsystem/ReActorSystemTest.java +++ b/core/src/test/java/io/reacted/core/reactorsystem/ReActorSystemTest.java @@ -191,9 +191,9 @@ void reActorSystemCanBroadcastToListeners() { .setReActorName("2nd reactor name") .build())); - Message originalMsg = new Message(ReActorRef.NO_REACTOR_REF, ReActorRef.NO_REACTOR_REF, 0x31337, - reActorSystem.getLocalReActorSystemId(), AckingPolicy.NONE, - CoreConstants.DE_SERIALIZATION_SUCCESSFUL); + Message originalMsg = Message.forParams(ReActorRef.NO_REACTOR_REF, ReActorRef.NO_REACTOR_REF, 0x31337, + reActorSystem.getLocalReActorSystemId(), AckingPolicy.NONE, + CoreConstants.DE_SERIALIZATION_SUCCESSFUL); reActorSystem.broadcastToLocalSubscribers(ReActorRef.NO_REACTOR_REF, originalMsg); diff --git a/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaDriver.java b/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaDriver.java index 93f12b1c..b55d27b0 100644 --- a/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaDriver.java +++ b/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaDriver.java @@ -99,9 +99,9 @@ DeliveryStatus sendMessage(ReActorRef source, ReActorContext destinationCtx, ReA try { Objects.requireNonNull(kafkaProducer) .send(new ProducerRecord<>(getDriverConfig().getTopic(), - new Message(source, destination, seqNum, - reActorSystemId, ackingPolicy, - message))).get(); + Message.forParams(source, destination, seqNum, + reActorSystemId, ackingPolicy, + message))).get(); return DeliveryStatus.SENT; } catch (Exception sendError) { getLocalReActorSystem().logError("Error sending message {}", message.toString(), diff --git a/drivers/src/main/java/io/reacted/drivers/channels/replay/ReplayLocalDriver.java b/drivers/src/main/java/io/reacted/drivers/channels/replay/ReplayLocalDriver.java index c80415a6..7951ad14 100644 --- a/drivers/src/main/java/io/reacted/drivers/channels/replay/ReplayLocalDriver.java +++ b/drivers/src/main/java/io/reacted/drivers/channels/replay/ReplayLocalDriver.java @@ -145,8 +145,9 @@ void onNewMessage(ReActorSystem localReActorSystem, Map emptyMap, if (!(payload instanceof EventExecutionAttempt executionAttempt)) { dstToMessageBySeqNum.computeIfAbsent(destination.getReActorId(), reActorId -> new HashMap<>()) - .put(sequenceNumber, new Message(source, destination, sequenceNumber, - fromReActorSystemId, ackingPolicy, payload)); + .put(sequenceNumber, + Message.forParams(source, destination, sequenceNumber, + fromReActorSystemId, ackingPolicy, payload)); return; } while (!isReactorAlreadySpawned(source)) { From e0c86d45c2dcbad65f6f35bf7e77632154fe7e2d Mon Sep 17 00:00:00 2001 From: wireknight Date: Mon, 19 Dec 2022 22:22:36 +0100 Subject: [PATCH 04/16] Reactor Context default name change Datalink Object removed Kafka driver refactored to include avro --- .../local/DirectCommunicationDriver.java | 2 +- .../io/reacted/core/messages/Message.java | 117 +++++++------- .../io/reacted/core/reactors/ReActorId.java | 2 +- .../core/reactorsystem/ReActorSystem.java | 10 +- .../java/io/reacted/core/MessageHelper.java | 6 +- .../core/drivers/system/LocalDriverTest.java | 12 +- .../drivers/system/LoopbackDriverTest.java | 9 +- .../core/mailboxes/PriorityMailboxTest.java | 12 +- .../core/mailboxes/UnboundedMboxTest.java | 8 +- .../systemreactors/MagicTestReActor.java | 8 +- .../core/reactorsystem/ReActorSystemTest.java | 12 +- drivers/pom.xml | 44 +++++ drivers/src/main/avro/Message.avdl | 49 ++++++ .../drivers/channels/grpc/GrpcDriver.java | 2 +- .../drivers/channels/kafka/KafkaDriver.java | 28 ++-- .../drivers/channels/kafka/KafkaUtils.java | 107 ++++++++++++ .../drivers/channels/kafka/MessageSchema.java | 153 ++++++++++++++++++ .../channels/replay/ReplayLocalDriver.java | 6 +- .../examples/benchmarking/ReactionTime.java | 9 +- .../examples/benchmarking/SingleChannel.java | 2 +- framework/src/test/java/ConsistencyTest.java | 10 +- pom.xml | 37 ++++- 22 files changed, 520 insertions(+), 125 deletions(-) create mode 100644 drivers/src/main/avro/Message.avdl create mode 100644 drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaUtils.java create mode 100644 drivers/src/main/java/io/reacted/drivers/channels/kafka/MessageSchema.java diff --git a/core/src/main/java/io/reacted/core/drivers/local/DirectCommunicationDriver.java b/core/src/main/java/io/reacted/core/drivers/local/DirectCommunicationDriver.java index 1ab9d173..d6a9d25b 100644 --- a/core/src/main/java/io/reacted/core/drivers/local/DirectCommunicationDriver.java +++ b/core/src/main/java/io/reacted/core/drivers/local/DirectCommunicationDriver.java @@ -69,6 +69,6 @@ public Properties getChannelProperties() { return destinationCtx.isStop() ? DeliveryStatus.NOT_DELIVERED : localDeliver(destinationCtx, - Message.forParams(source, destination, seqNum, reActorSystemId, ackingPolicy, message)); + Message.of(source, destination, seqNum, reActorSystemId, ackingPolicy, message)); } } diff --git a/core/src/main/java/io/reacted/core/messages/Message.java b/core/src/main/java/io/reacted/core/messages/Message.java index fcd6c020..18715180 100644 --- a/core/src/main/java/io/reacted/core/messages/Message.java +++ b/core/src/main/java/io/reacted/core/messages/Message.java @@ -12,9 +12,7 @@ import io.reacted.core.reactorsystem.ReActorSystemId; import io.reacted.patterns.NonNullByDefault; -import java.io.Serial; import javax.annotation.Nullable; -import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; @@ -22,35 +20,44 @@ import java.util.Objects; @NonNullByDefault -public final class Message implements Externalizable { - @Serial - private static final long serialVersionUID = 1; - private ReActorRef sender; - private ReActorRef destination; - private long sequenceNumber; - private ReActorSystemId generatingReActorSystem; - private AckingPolicy ackingPolicy; - private Serializable payload; +public final class Message { + private static final long SENDER_OFFSET = SerializationUtils.getFieldOffset(Message.class, "sender") + .orElseSneakyThrow(); + private static final long DESTINATION_OFFSET = SerializationUtils.getFieldOffset(Message.class, "destination") + .orElseSneakyThrow(); + private static final long SEQ_NUM_OFFSET = SerializationUtils.getFieldOffset(Message.class, "sequenceNumber") + .orElseSneakyThrow(); + private static final long CREATING_REACTOR_SYSTEM_ID = SerializationUtils.getFieldOffset(Message.class, "creatingReactorSystemId") + .orElseSneakyThrow(); + private static final long ACKING_POLICY = SerializationUtils.getFieldOffset(Message.class, "ackingPolicy") + .orElseSneakyThrow(); + private static final long PAYLOAD_OFFSET = SerializationUtils.getFieldOffset(Message.class, "payload") + .orElseSneakyThrow(); + private final ReActorRef sender; + private final ReActorRef destination; + private final long sequenceNumber; + private final ReActorSystemId creatingReactorSystemId; + private final AckingPolicy ackingPolicy; + private final Serializable payload; private Message() { - /* Required by Externalizable */ - this.sender = ReActorRef.NO_REACTOR_REF; - this.destination = ReActorRef.NO_REACTOR_REF; - this.sequenceNumber = 0; - this.payload = SerializationUtils.NO_PAYLOAD; - this.generatingReActorSystem = ReActorSystemId.NO_REACTORSYSTEM_ID; - this.ackingPolicy = AckingPolicy.NONE; + this(ReActorRef.NO_REACTOR_REF, ReActorRef.NO_REACTOR_REF, 0L, + ReActorSystemId.NO_REACTORSYSTEM_ID, AckingPolicy.NONE, SerializationUtils.NO_PAYLOAD); } - public static Message forParams(ReActorRef sender, ReActorRef dest, long seqNum, ReActorSystemId generatingReActorSystem, - AckingPolicy ackingPolicy, Serializable payload) { - Message message = new Message(); - return message.setSender(sender) - .setDestination(dest) - .setSequenceNumber(seqNum) - .setGeneratingReActorSystem(generatingReActorSystem) - .setAckingPolicy(ackingPolicy) - .setPayload(payload); + private Message(ReActorRef sender, ReActorRef destination, long sequenceNumber, + ReActorSystemId creatingReActorSystem, AckingPolicy ackingPolicy, Serializable payload) { + this.sender = sender; + this.destination = destination; + this.sequenceNumber = sequenceNumber; + this.creatingReactorSystemId = creatingReActorSystem; + this.ackingPolicy = ackingPolicy; + this.payload = payload; + } + public static Message of(ReActorRef sender, ReActorRef destination, long sequenceNumber, + ReActorSystemId generatingReActorSystem, AckingPolicy ackingPolicy, Serializable payload) { + return new Message(sender, destination, sequenceNumber, generatingReActorSystem, ackingPolicy, + payload); } @Override @@ -70,25 +77,18 @@ public int hashCode() { @Override public String toString() { - return "Message{" + - "sender=" + sender + - ", destination=" + destination + - ", sequenceNumber=" + sequenceNumber + - ", payload=" + payload + - '}'; + return "Message{" + "sender=" + sender + ", destination=" + destination + ", sequenceNumber=" + sequenceNumber + ", creatingReactorSystemId=" + creatingReactorSystemId + ", ackingPolicy=" + ackingPolicy + ", payload=" + payload + '}'; } - @Override public void writeExternal(ObjectOutput out) throws IOException { Objects.requireNonNull(sender).writeExternal(out); Objects.requireNonNull(destination).writeExternal(out); - Objects.requireNonNull(generatingReActorSystem).writeExternal(out); + Objects.requireNonNull(creatingReactorSystemId).writeExternal(out); out.writeInt(ackingPolicy.ordinal()); out.writeLong(sequenceNumber); out.writeObject(payload); } - @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { ReActorRef senderRef = new ReActorRef(); senderRef.readExternal(in); @@ -98,7 +98,7 @@ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundExcept setDestination(destinationRef); var receivedGeneratingReActorSystem = new ReActorSystemId(); receivedGeneratingReActorSystem.readExternal(in); - setGeneratingReActorSystem(receivedGeneratingReActorSystem); + setCreatingReactorSystemId(receivedGeneratingReActorSystem); setAckingPolicy(AckingPolicy.forOrdinal(in.readInt())); setSequenceNumber(in.readLong()); try { @@ -107,44 +107,45 @@ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundExcept exc.printStackTrace(); } } - public ReActorRef getSender() { return sender; } public ReActorRef getDestination() { return destination; } public long getSequenceNumber() { return sequenceNumber; } - public ReActorSystemId getGeneratingReActorSystem() { return generatingReActorSystem; } + public ReActorSystemId getCreatingReactorSystemId() { return creatingReactorSystemId; } public AckingPolicy getAckingPolicy() { return ackingPolicy; } - public PayloadT getPayload() { return (PayloadT)payload; } - public Message setSender(ReActorRef sender) { - this.sender = sender; - return this; + public Serializable getPayload() { return payload; } + + @SuppressWarnings("UnusedReturnValue") + private Message setSender(ReActorRef sender) { + return SerializationUtils.setObjectField(this, SENDER_OFFSET, sender); } - public Message setDestination(ReActorRef destination) { - this.destination = destination; - return this; + @SuppressWarnings("UnusedReturnValue") + private Message setDestination(ReActorRef destination) { + return SerializationUtils.setObjectField(this, DESTINATION_OFFSET, destination); } - public Message setSequenceNumber(long sequenceNumber) { - this.sequenceNumber = sequenceNumber; - return this; + @SuppressWarnings("UnusedReturnValue") + private Message setAckingPolicy(AckingPolicy ackingPolicy) { + return SerializationUtils.setObjectField(this, ACKING_POLICY, ackingPolicy); } - public Message setGeneratingReActorSystem(ReActorSystemId generatingReActorSystem) { - this.generatingReActorSystem = generatingReActorSystem; - return this; + @SuppressWarnings("UnusedReturnValue") + private Message setCreatingReactorSystemId(ReActorSystemId creatingReactorSystemId) { + return SerializationUtils.setObjectField(this, CREATING_REACTOR_SYSTEM_ID, creatingReactorSystemId); } - public Message setAckingPolicy(AckingPolicy ackingPolicy) { - this.ackingPolicy = ackingPolicy; - return this; + @SuppressWarnings("UnusedReturnValue") + private Message setSequenceNumber(long sequenceNumber) { + return SerializationUtils.setLongField(this, SEQ_NUM_OFFSET, sequenceNumber); } - public Message setPayload(Serializable payload) { - this.payload = payload; - return this; + + @SuppressWarnings("UnusedReturnValue") + private Message setPayload(Serializable payload) { + return SerializationUtils.setObjectField(this, PAYLOAD_OFFSET, payload); } } diff --git a/core/src/main/java/io/reacted/core/reactors/ReActorId.java b/core/src/main/java/io/reacted/core/reactors/ReActorId.java index a4613dd4..45a1b41a 100644 --- a/core/src/main/java/io/reacted/core/reactors/ReActorId.java +++ b/core/src/main/java/io/reacted/core/reactors/ReActorId.java @@ -90,7 +90,7 @@ public void writeExternal(ObjectOutput out) throws IOException { if (this == NO_REACTOR_ID) { out.writeInt(NO_REACTOR_ID_MARKER); } else { - out.writeInt(0); + out.writeInt(COMMON_REACTOR_ID_MARKER); out.writeObject(getReActorUUID()); out.writeObject(reActorName); } diff --git a/core/src/main/java/io/reacted/core/reactorsystem/ReActorSystem.java b/core/src/main/java/io/reacted/core/reactorsystem/ReActorSystem.java index ff1de2ad..aa9702bb 100644 --- a/core/src/main/java/io/reacted/core/reactorsystem/ReActorSystem.java +++ b/core/src/main/java/io/reacted/core/reactorsystem/ReActorSystem.java @@ -159,9 +159,9 @@ private ReActorSystem() { this.gatesCentralizedManager = new RegistryGatesCentralizedManager(localReActorSystemId, new LoopbackDriver<>(this, getSystemConfig().getLocalDriver())); this.newSeqNum = new AtomicLong(Long.MAX_VALUE); - this.reActorStop = Message.forParams(ReActorRef.NO_REACTOR_REF, ReActorRef.NO_REACTOR_REF, - Long.MIN_VALUE, localReActorSystemId, AckingPolicy.NONE, - ReActorStop.STOP); + this.reActorStop = Message.of(ReActorRef.NO_REACTOR_REF, ReActorRef.NO_REACTOR_REF, + Long.MIN_VALUE, localReActorSystemId, AckingPolicy.NONE, + ReActorStop.STOP); } public ReActorSystem(ReActorSystemConfig config) { @@ -176,8 +176,8 @@ public ReActorSystem(ReActorSystemConfig config) { this.typedSubscriptionsManager = new TypedSubscriptionsManager(); this.dispatchers = new ConcurrentHashMap<>(10, 0.5f); this.newSeqNum = new AtomicLong(0); - this.reActorStop = Message.forParams(ReActorRef.NO_REACTOR_REF, ReActorRef.NO_REACTOR_REF, Long.MIN_VALUE, - localReActorSystemId, AckingPolicy.NONE, ReActorStop.STOP); + this.reActorStop = Message.of(ReActorRef.NO_REACTOR_REF, ReActorRef.NO_REACTOR_REF, Long.MIN_VALUE, + localReActorSystemId, AckingPolicy.NONE, ReActorStop.STOP); } /** * @return The configuration for the reactor system diff --git a/core/src/test/java/io/reacted/core/MessageHelper.java b/core/src/test/java/io/reacted/core/MessageHelper.java index 850f98ca..08c9fe61 100644 --- a/core/src/test/java/io/reacted/core/MessageHelper.java +++ b/core/src/test/java/io/reacted/core/MessageHelper.java @@ -6,8 +6,8 @@ public class MessageHelper { public static Message getDefaultMessage() { - return Message.forParams(ReActorRef.NO_REACTOR_REF, ReActorRef.NO_REACTOR_REF, 0x31337, - ReactorHelper.TEST_REACTOR_SYSTEM_ID, AckingPolicy.NONE, - CoreConstants.DE_SERIALIZATION_SUCCESSFUL); + return Message.of(ReActorRef.NO_REACTOR_REF, ReActorRef.NO_REACTOR_REF, 0x31337, + ReactorHelper.TEST_REACTOR_SYSTEM_ID, AckingPolicy.NONE, + CoreConstants.DE_SERIALIZATION_SUCCESSFUL); } } diff --git a/core/src/test/java/io/reacted/core/drivers/system/LocalDriverTest.java b/core/src/test/java/io/reacted/core/drivers/system/LocalDriverTest.java index 40567799..799b9098 100644 --- a/core/src/test/java/io/reacted/core/drivers/system/LocalDriverTest.java +++ b/core/src/test/java/io/reacted/core/drivers/system/LocalDriverTest.java @@ -57,7 +57,7 @@ static void prepareLocalDriver() throws Exception { localDriver = SystemLocalDrivers.DIRECT_COMMUNICATION; localDriver.initDriverLoop(reActorSystem); - TypedSubscription subscribedTypes = TypedSubscription.LOCAL.forType(Message.class); + TypedSubscription subscribedTypes = TypedSubscription.LOCAL.forType(String.class); ReActorConfig reActorConfig = ReActorConfig.newBuilder() .setReActorName(CoreConstants.REACTOR_NAME) .setDispatcherName("Dispatcher") @@ -81,8 +81,8 @@ static void prepareLocalDriver() throws Exception { .setReActions(mock(ReActions.class)) .build(); - originalMsg = Message.forParams(ReActorRef.NO_REACTOR_REF, reActorRef, 0x31337, ReactorHelper.TEST_REACTOR_SYSTEM_ID, - AckingPolicy.NONE, CoreConstants.DE_SERIALIZATION_SUCCESSFUL); + originalMsg = Message.of(ReActorRef.NO_REACTOR_REF, reActorRef, 0x31337, ReactorHelper.TEST_REACTOR_SYSTEM_ID, + AckingPolicy.NONE, CoreConstants.DE_SERIALIZATION_SUCCESSFUL); } @Test @@ -90,7 +90,7 @@ void localDriverDeliversMessagesInMailBox() { Assertions.assertTrue(localDriver.sendMessage(originalMsg.getSender(), reActorContext, originalMsg.getDestination(), originalMsg.getSequenceNumber(), - originalMsg.getGeneratingReActorSystem(), + originalMsg.getCreatingReactorSystemId(), originalMsg.getAckingPolicy(), originalMsg.getPayload()).isDelivered()); @@ -104,7 +104,7 @@ void localDriverForwardsMessageToLocalActor() { Assertions.assertTrue(LocalDriver.syncForwardMessageToLocalActor(originalMsg.getSender(), reActorContext, originalMsg.getDestination(), originalMsg.getSequenceNumber(), - originalMsg.getGeneratingReActorSystem(), + originalMsg.getCreatingReactorSystemId(), originalMsg.getAckingPolicy(), originalMsg.getPayload()) .isDelivered()); @@ -116,7 +116,7 @@ void localDriverCanSendMessage() { Assertions.assertTrue(localDriver.sendMessage(originalMsg.getSender(), reActorContext, originalMsg.getDestination(), originalMsg.getSequenceNumber(), - originalMsg.getGeneratingReActorSystem(), + originalMsg.getCreatingReactorSystemId(), originalMsg.getAckingPolicy(), originalMsg.getPayload()).isDelivered()); Assertions.assertEquals(originalMsg, unboundedMbox.getNextMessage()); diff --git a/core/src/test/java/io/reacted/core/drivers/system/LoopbackDriverTest.java b/core/src/test/java/io/reacted/core/drivers/system/LoopbackDriverTest.java index 9a7ce9b9..2f9a7be6 100644 --- a/core/src/test/java/io/reacted/core/drivers/system/LoopbackDriverTest.java +++ b/core/src/test/java/io/reacted/core/drivers/system/LoopbackDriverTest.java @@ -57,13 +57,13 @@ void prepareEnvironment() throws Exception { ReActorConfig reActorConfig = ReActorConfig.newBuilder() .setReActorName("ReActorName") .setDispatcherName(testDispatcher) - .setTypedSubscriptions(TypedSubscription.LOCAL.forType(Message.class)) + .setTypedSubscriptions(TypedSubscription.LOCAL.forType(String.class)) .build(); destReActorRef = reActorSystem.spawn(new MagicTestReActor(1, true, reActorConfig)) .orElseSneakyThrow(); - message = Message.forParams(ReActorRef.NO_REACTOR_REF, destReActorRef, 0, reActorSystem.getLocalReActorSystemId(), - AckingPolicy.NONE, "payload"); + message = Message.of(ReActorRef.NO_REACTOR_REF, destReActorRef, 0, reActorSystem.getLocalReActorSystemId(), + AckingPolicy.NONE, "payload"); } @AfterEach @@ -71,7 +71,8 @@ void prepareEnvironment() throws Exception { @Test void loopbackDriverCanTellMessageToReactor() throws ExecutionException, InterruptedException { - Assertions.assertTrue(loopbackDriver.publish(ReActorRef.NO_REACTOR_REF, destReActorRef, message).isDelivered()); + Assertions.assertTrue(loopbackDriver.publish(ReActorRef.NO_REACTOR_REF, destReActorRef, + message.getPayload()).isDelivered()); // as we have a dispatcher the message was dispatched & it cannot be found in destination mbox Awaitility.await().until(() -> MagicTestReActor.RECEIVED.sum() == 1); } diff --git a/core/src/test/java/io/reacted/core/mailboxes/PriorityMailboxTest.java b/core/src/test/java/io/reacted/core/mailboxes/PriorityMailboxTest.java index b2d7c2ec..ed52ed02 100644 --- a/core/src/test/java/io/reacted/core/mailboxes/PriorityMailboxTest.java +++ b/core/src/test/java/io/reacted/core/mailboxes/PriorityMailboxTest.java @@ -35,8 +35,8 @@ static void prepareMessages() { testMsgSrc = ReactorHelper.generateReactor(CoreConstants.SOURCE); testMsgDst = ReactorHelper.generateReactor(CoreConstants.DESTINATION); - originalMsg = Message.forParams(testMsgSrc, testMsgDst, 0x31337, ReactorHelper.TEST_REACTOR_SYSTEM_ID, - AckingPolicy.NONE, "De/Serialization Successful!"); + originalMsg = Message.of(testMsgSrc, testMsgDst, 0x31337, ReactorHelper.TEST_REACTOR_SYSTEM_ID, + AckingPolicy.NONE, "De/Serialization Successful!"); } @BeforeEach @@ -90,8 +90,8 @@ void messageWithHigherPriorityProvidedFirstThenNormalPriorityApplied() { ReactorHelper.generateReactor(CoreConstants.DESTINATION + PRIORITY_2); Message message4 = - Message.forParams(highPrioMsgSrc2, highPrioMsgDest2, 0x31337, ReactorHelper.TEST_REACTOR_SYSTEM_ID, - AckingPolicy.NONE, CoreConstants.HIGH_PRIORITY); + Message.of(highPrioMsgSrc2, highPrioMsgDest2, 0x31337, ReactorHelper.TEST_REACTOR_SYSTEM_ID, + AckingPolicy.NONE, CoreConstants.HIGH_PRIORITY); priorityMailbox1.deliver(message1); priorityMailbox1.deliver(message2); @@ -105,8 +105,8 @@ void messageWithHigherPriorityProvidedFirstThenNormalPriorityApplied() { } private Message createMessage(String payload) { - return Message.forParams(testMsgSrc, testMsgDst, 0x31337, ReactorHelper.TEST_REACTOR_SYSTEM_ID, - AckingPolicy.NONE, payload); + return Message.of(testMsgSrc, testMsgDst, 0x31337, ReactorHelper.TEST_REACTOR_SYSTEM_ID, + AckingPolicy.NONE, payload); } private final static Comparator PAYLOAD_COMPARATOR = diff --git a/core/src/test/java/io/reacted/core/mailboxes/UnboundedMboxTest.java b/core/src/test/java/io/reacted/core/mailboxes/UnboundedMboxTest.java index ef8fc346..556dc666 100644 --- a/core/src/test/java/io/reacted/core/mailboxes/UnboundedMboxTest.java +++ b/core/src/test/java/io/reacted/core/mailboxes/UnboundedMboxTest.java @@ -29,8 +29,8 @@ static void prepareMessages() { testMsgSrc = ReactorHelper.generateReactor(CoreConstants.SOURCE); testMsgDst = ReactorHelper.generateReactor(CoreConstants.DESTINATION); - originalMsg = Message.forParams(testMsgSrc, testMsgDst, 0x31337, ReactorHelper.TEST_REACTOR_SYSTEM_ID, - AckingPolicy.NONE, CoreConstants.DE_SERIALIZATION_SUCCESSFUL); + originalMsg = Message.of(testMsgSrc, testMsgDst, 0x31337, ReactorHelper.TEST_REACTOR_SYSTEM_ID, + AckingPolicy.NONE, CoreConstants.DE_SERIALIZATION_SUCCESSFUL); } @BeforeEach @@ -81,8 +81,8 @@ void getNextMessageReturnsMessagesInTheOrderTheyWereSent() { ReActorRef testMsgSrc2 = ReactorHelper.generateReactor("source2"); ReActorRef testMsgDst2 = ReactorHelper.generateReactor("destination2"); - Message originalMsg2 = Message.forParams(testMsgSrc2, testMsgDst2, 0x31337, - ReactorHelper.TEST_REACTOR_SYSTEM_ID, AckingPolicy.NONE, "De/Serialization Successful!"); + Message originalMsg2 = Message.of(testMsgSrc2, testMsgDst2, 0x31337, + ReactorHelper.TEST_REACTOR_SYSTEM_ID, AckingPolicy.NONE, "De/Serialization Successful!"); unboundedMbox.deliver(originalMsg2); Assertions.assertEquals(2, unboundedMbox.getMsgNum()); diff --git a/core/src/test/java/io/reacted/core/reactors/systemreactors/MagicTestReActor.java b/core/src/test/java/io/reacted/core/reactors/systemreactors/MagicTestReActor.java index 560088fd..25d3855a 100644 --- a/core/src/test/java/io/reacted/core/reactors/systemreactors/MagicTestReActor.java +++ b/core/src/test/java/io/reacted/core/reactors/systemreactors/MagicTestReActor.java @@ -48,7 +48,7 @@ public MagicTestReActor(int maxMsgValue, boolean checkMsgOrdering, ReActorConfig this.reActorConfig = reActorConfig; this.reActions = ReActions.newBuilder() .reAct(DeadMessage.class, this::onDeadMessage) - .reAct(Message.class, this::onMessage) + .reAct(String.class, this::onMessage) .build(); } @@ -58,9 +58,9 @@ public void onDeadMessage(ReActorContext ctx, DeadMessage deadMessage) { DEADMSG.increment(); } - public void onMessage(ReActorContext ctx, Message message) { - System.err.printf("Dispatcher used [%s] Payload: %s%n", ctx.getDispatcher() - .getName(), message.getPayload()); + public void onMessage(ReActorContext ctx, String message) { + System.err.printf("Dispatcher used [%s] Payload: %s%n", + ctx.getDispatcher().getName(), message); RECEIVED.increment(); } diff --git a/core/src/test/java/io/reacted/core/reactorsystem/ReActorSystemTest.java b/core/src/test/java/io/reacted/core/reactorsystem/ReActorSystemTest.java index 2c37aa41..f8f35d69 100644 --- a/core/src/test/java/io/reacted/core/reactorsystem/ReActorSystemTest.java +++ b/core/src/test/java/io/reacted/core/reactorsystem/ReActorSystemTest.java @@ -28,7 +28,6 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -41,7 +40,6 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; class ReActorSystemTest { private final Logger LOGGER = LoggerFactory.getLogger(ReActorSystemTest.class); @@ -182,7 +180,7 @@ void reActorSystemCanBroadcastToListeners() { ReActorConfig reActorConfig = ReActorConfig.newBuilder() .setReActorName("TR") .setDispatcherName("TestDispatcher") - .setTypedSubscriptions(TypedSubscription.LOCAL.forType(Message.class)) + .setTypedSubscriptions(TypedSubscription.LOCAL.forType(String.class)) .build(); reActorSystem.spawn(new MagicTestReActor(1, true, reActorConfig)); @@ -191,11 +189,11 @@ void reActorSystemCanBroadcastToListeners() { .setReActorName("2nd reactor name") .build())); - Message originalMsg = Message.forParams(ReActorRef.NO_REACTOR_REF, ReActorRef.NO_REACTOR_REF, 0x31337, - reActorSystem.getLocalReActorSystemId(), AckingPolicy.NONE, - CoreConstants.DE_SERIALIZATION_SUCCESSFUL); + Message originalMsg = Message.of(ReActorRef.NO_REACTOR_REF, ReActorRef.NO_REACTOR_REF, 0x31337, + reActorSystem.getLocalReActorSystemId(), AckingPolicy.NONE, + CoreConstants.DE_SERIALIZATION_SUCCESSFUL); - reActorSystem.broadcastToLocalSubscribers(ReActorRef.NO_REACTOR_REF, originalMsg); + reActorSystem.broadcastToLocalSubscribers(ReActorRef.NO_REACTOR_REF, originalMsg.getPayload()); Awaitility.await() .until(MagicTestReActor.RECEIVED::intValue, CoreMatchers.equalTo(2)); diff --git a/drivers/pom.xml b/drivers/pom.xml index ed49ee8d..22152174 100644 --- a/drivers/pom.xml +++ b/drivers/pom.xml @@ -124,6 +124,22 @@ org.apache.curator curator-x-discovery + + org.apache.avro + avro + + + org.apache.avro + avro-compiler + + + org.apache.avro + avro-ipc + + + org.apache.avro + avro-maven-plugin + @@ -134,6 +150,30 @@ + + org.apache.avro + avro-maven-plugin + ${avro.maven.version} + + + generate-sources + + idl-protocol + + + ${project.basedir}/src/main/avro/ + ${project.basedir}/src/main/avro/ + PRIVATE + + **/*.avdl + + + **/*.test + + + + + org.codehaus.mojo build-helper-maven-plugin @@ -156,6 +196,10 @@ org.xolstice.maven.plugins protobuf-maven-plugin + + org.apache.avro + avro-maven-plugin + \ No newline at end of file diff --git a/drivers/src/main/avro/Message.avdl b/drivers/src/main/avro/Message.avdl new file mode 100644 index 00000000..2c054369 --- /dev/null +++ b/drivers/src/main/avro/Message.avdl @@ -0,0 +1,49 @@ +@namespace("io.reacted.drivers.channels.kafka.avro") +protocol ReactedMessageProtocol { + record Message { + ReActorRef? source; + ReActorRef? destination; + long sequence_number; + ReactorSystemId creator_reactor_system; + AckingPolicy acking_policy; + bytes payload; + } + + record AckingPolicy { + int acking_policy_ordinal; + } + + record ReActorRef { + ReActorId reactor_id; + ReactorSystemRef reactor_system_ref; + } + + record ReactorSystemRef { + ReactorSystemId reactor_system_id; + ChannelId channel_id; + } + + record ReactorSystemId { + UUID reactor_system_id; + string reactor_system_name; + } + + record ChannelId { + ChannelType channel_type; + string channel_name; + } + + record ChannelType { + int channel_type_ordinal; + } + + record ReActorId { + UUID id; + string name; + } + + record UUID { + long most_significant = 0; + long least_significant = 0; + } +} \ No newline at end of file diff --git a/drivers/src/main/java/io/reacted/drivers/channels/grpc/GrpcDriver.java b/drivers/src/main/java/io/reacted/drivers/channels/grpc/GrpcDriver.java index 3a410a48..641445fc 100644 --- a/drivers/src/main/java/io/reacted/drivers/channels/grpc/GrpcDriver.java +++ b/drivers/src/main/java/io/reacted/drivers/channels/grpc/GrpcDriver.java @@ -24,7 +24,7 @@ import io.grpc.Server; import io.grpc.Status; import io.grpc.netty.NettyServerBuilder; -import io.grpc.services.HealthStatusManager; +import io.grpc.protobuf.services.HealthStatusManager; import io.grpc.stub.StreamObserver; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; diff --git a/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaDriver.java b/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaDriver.java index b55d27b0..d3bff0b7 100644 --- a/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaDriver.java +++ b/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaDriver.java @@ -20,6 +20,7 @@ import io.reacted.patterns.NonNullByDefault; import io.reacted.patterns.Try; import io.reacted.patterns.UnChecked; +import org.apache.avro.Protocol; import org.apache.kafka.clients.consumer.Consumer; import org.apache.kafka.clients.consumer.ConsumerConfig; import org.apache.kafka.clients.consumer.KafkaConsumer; @@ -57,9 +58,9 @@ public class KafkaDriver extends RemotingDriver { private static final byte[] NO_SERIALIZED_PAYLOAD = null; private static final Duration POLL_TIMEOUT = Duration.ofSeconds(1); @Nullable - private Consumer kafkaConsumer; + private Consumer kafkaConsumer; @Nullable - private Producer kafkaProducer; + private Producer kafkaProducer; public KafkaDriver(KafkaDriverConfig config) { super(config); @@ -94,23 +95,24 @@ public ChannelId getChannelId() { @Override public DeliveryStatus sendMessage(ReActorRef source, ReActorContext destinationCtx, ReActorRef destination, - long seqNum, ReActorSystemId reActorSystemId, AckingPolicy ackingPolicy, - PayloadT message) { + long sequenceNumber, ReActorSystemId reActorSystemId, AckingPolicy ackingPolicy, + PayloadT payload) { + try { Objects.requireNonNull(kafkaProducer) .send(new ProducerRecord<>(getDriverConfig().getTopic(), - Message.forParams(source, destination, seqNum, - reActorSystemId, ackingPolicy, - message))).get(); + KafkaUtils.toKafkaMessage(source, destination, sequenceNumber, + reActorSystemId, ackingPolicy, payload))) + .get(); return DeliveryStatus.SENT; } catch (Exception sendError) { - getLocalReActorSystem().logError("Error sending message {}", message.toString(), + getLocalReActorSystem().logError("Error sending message {}", payload.toString(), sendError); return DeliveryStatus.NOT_SENT; } } - private static Consumer createConsumer(KafkaDriverConfig driverConfig) { + private static Consumer createConsumer(KafkaDriverConfig driverConfig) { Properties props = new Properties(); props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, driverConfig.getBootstrapEndpoint()); props.put(ConsumerConfig.GROUP_ID_CONFIG, driverConfig.getGroupId()); @@ -119,12 +121,12 @@ private static Consumer createConsumer(KafkaDriverConfig driverCo props.put(ConsumerConfig.MAX_POLL_RECORDS_CONFIG, driverConfig.getMaxPollRecords()); props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "false"); props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "latest"); - Consumer consumer = new KafkaConsumer<>(props); + Consumer consumer = new KafkaConsumer<>(props); consumer.subscribe(List.of(driverConfig.getTopic())); return consumer; } - public static Producer createProducer(KafkaDriverConfig driverConfig) { + public static Producer createProducer(KafkaDriverConfig driverConfig) { Properties props = new Properties(); props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, driverConfig.getBootstrapEndpoint()); props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, LongSerializer.class.getName()); @@ -132,7 +134,7 @@ public static Producer createProducer(KafkaDriverConfig driverCon return new KafkaProducer<>(props); } - private static void kafkaDriverLoop(Consumer kafkaConsumer, KafkaDriver thisDriver, + private static void kafkaDriverLoop(Consumer kafkaConsumer, KafkaDriver thisDriver, ReActorSystem localReActorSystem) { while(!Thread.currentThread().isInterrupted()) { try { @@ -140,7 +142,7 @@ private static void kafkaDriverLoop(Consumer kafkaConsumer, Kafka .forEach(record -> thisDriver.offerMessage(record.value().getSender(), record.value().getDestination(), record.value().getSequenceNumber(), - record.value().getGeneratingReActorSystem(), + record.value().getCreatingReactorSystemId(), record.value().getAckingPolicy(), record.value().getPayload())); } catch (InterruptException interruptException) { diff --git a/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaUtils.java b/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaUtils.java new file mode 100644 index 00000000..4eb6413d --- /dev/null +++ b/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaUtils.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2022 , [ pierre@reacted.io ] + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + +package io.reacted.drivers.channels.kafka; + +import io.reacted.core.messages.AckingPolicy; +import io.reacted.core.reactorsystem.ReActorContext; +import io.reacted.core.reactorsystem.ReActorRef; +import io.reacted.core.reactorsystem.ReActorSystemId; +import io.reacted.core.reactorsystem.ReActorSystemRef; +import io.reacted.drivers.channels.kafka.avro.ChannelId; +import io.reacted.drivers.channels.kafka.avro.ChannelType; +import io.reacted.drivers.channels.kafka.avro.Message; +import io.reacted.drivers.channels.kafka.avro.ReActorId; +import io.reacted.drivers.channels.kafka.avro.ReactorSystemId; +import io.reacted.drivers.channels.kafka.avro.ReactorSystemRef; +import io.reacted.drivers.channels.kafka.avro.UUID; + +import javax.annotation.Nullable; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.nio.ByteBuffer; + +final class KafkaUtils { + private KafkaUtils() { throw new AssertionError("We are not supposed to be called"); } + + @Nullable + static + Message toKafkaMessage(ReActorRef source, ReActorRef destination, long sequenceNumber, + ReActorSystemId reActorSystemId, AckingPolicy ackingPolicy, + PayloadT payload) throws IOException { + Message.Builder avroMessageBuilder = Message.newBuilder() + .setSequenceNumber(sequenceNumber) + .setAckingPolicy(fromAckingPolicy(ackingPolicy)) + .setCreatorReactorSystem(fromReActorSystemId(reActorSystemId)); + if (!source.equals(ReActorRef.NO_REACTOR_REF)) { + avroMessageBuilder.setSource(fromReActorRef(source)); + } + if (!destination.equals(ReActorRef.NO_REACTOR_REF)) { + avroMessageBuilder.setDestination(fromReActorRef(destination)); + } + try(ByteArrayOutputStream byteArray = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(byteArray)) { + oos.writeObject(payload); + avroMessageBuilder.setPayload(ByteBuffer.wrap(byteArray.toByteArray())); + } + return avroMessageBuilder.build(); + } + + private static io.reacted.drivers.channels.kafka.avro.AckingPolicy fromAckingPolicy(AckingPolicy ackingPolicy) { + return io.reacted.drivers.channels.kafka.avro.AckingPolicy.newBuilder() + .setAckingPolicyOrdinal(ackingPolicy.ordinal()) + .build(); + } + + private static io.reacted.drivers.channels.kafka.avro.ReActorRef fromReActorRef(ReActorRef reActorRef) { + return io.reacted.drivers.channels.kafka.avro.ReActorRef.newBuilder() + .setReactorId(fromReActorId(reActorRef.getReActorId())) + .setReactorSystemRef(fromReActorSystemRef(reActorRef.getReActorSystemRef())) + .build(); + } + + private static ReactorSystemRef fromReActorSystemRef(ReActorSystemRef reActorSystemRef) { + return ReactorSystemRef.newBuilder() + .setChannelId(fromChannelId(reActorSystemRef.getChannelId())) + .setReactorSystemId(fromReActorSystemId(reActorSystemRef.getReActorSystemId())) + .build(); + } + private static ReActorId fromReActorId(io.reacted.core.reactors.ReActorId reActorId) { + return ReActorId.newBuilder() + .setId(fromUUID(reActorId.getReActorUUID())) + .setName(reActorId.getReActorName()) + .build(); + } + private static ReactorSystemId fromReActorSystemId(ReActorSystemId reActorSystemId) { + return ReactorSystemId.newBuilder() + .setReactorSystemId(fromUUID(reActorSystemId.getReActorSystemUUID())) + .setReactorSystemName(reActorSystemId.getReActorSystemName()) + .build(); + } + + private static ChannelId fromChannelId(io.reacted.core.config.ChannelId channelId) { + return ChannelId.newBuilder() + .setChannelName(channelId.getChannelName()) + .setChannelType(fromChannelType(channelId.getChannelType())) + .build(); + } + + private static ChannelType fromChannelType(io.reacted.core.config.ChannelId.ChannelType channelType) { + return ChannelType.newBuilder() + .setChannelTypeOrdinal(channelType.ordinal()) + .build(); + } + private static UUID fromUUID(java.util.UUID uuid) { + return UUID.newBuilder() + .setMostSignificant(uuid.getMostSignificantBits()) + .setLeastSignificant(uuid.getLeastSignificantBits()) + .build(); + } +} diff --git a/drivers/src/main/java/io/reacted/drivers/channels/kafka/MessageSchema.java b/drivers/src/main/java/io/reacted/drivers/channels/kafka/MessageSchema.java new file mode 100644 index 00000000..d475331d --- /dev/null +++ b/drivers/src/main/java/io/reacted/drivers/channels/kafka/MessageSchema.java @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2022 , [ pierre@reacted.io ] + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + +package io.reacted.drivers.channels.kafka; + +import io.reacted.core.config.ChannelId; +import io.reacted.core.messages.AckingPolicy; +import io.reacted.core.messages.Message; +import io.reacted.core.reactors.ReActorId; +import io.reacted.core.reactorsystem.ReActorRef; +import io.reacted.core.reactorsystem.ReActorSystemId; +import io.reacted.drivers.channels.grpc.ReActedLinkProtocol; +import org.apache.avro.Schema; +import org.apache.avro.SchemaBuilder; + +import java.util.Arrays; + + +final class MessageSchema { + + static final String REACTOR_ID = "RI"; + static final String REACTOR_NAME = "RN"; + static final String SENDER = "S"; + static final String DESTINATION = "D"; + static final String SEQUENCE_NUMBER = "s"; + static final String CREATOR_REACTOR_SYSTEM_ID = "CRSI"; + static final String ACKING_POLICY = "A"; + + static final String PAYLOAD = "P"; + static final String REACTOR_SYSTEM_NAME = "RSN"; + static final String REACTOR_SYSTEM_ID = "RSI"; + + static final String REACTOR_SYSTEM_REF = "RSR"; + static final String CHANNEL_ID = "CI"; + static final String CHANNEL_TYPE = "CT"; + static final String CHANNEL_NAME = "CN"; + static final String UUID = "U"; + static final String UUID_MOST_SIGNIFICANT = "UM"; + static final String UUID_LEAST_SIGNIFICANT = "UL"; + static final String MARKER = "MK"; + private MessageSchema() { throw new AssertionError("This is not supposed to be called"); } + + static final Schema UUID_SCHEMA = SchemaBuilder.record(java.util.UUID.class.getSimpleName()) + .fields() + .name(UUID_MOST_SIGNIFICANT) + .type() + .longType() + .longDefault(0) + .name(UUID_LEAST_SIGNIFICANT) + .type() + .longType() + .longDefault(0) + .endRecord(); + + static final Schema CHANNEL_TYPE_SCHEMA = SchemaBuilder.enumeration(ChannelId.ChannelType.class.getSimpleName()) + .symbols(Arrays.stream(ChannelId.ChannelType.values()) + .map(ChannelId.ChannelType::toString) + .toArray(String[]::new)); + + static final Schema CHANNEL_ID_SCHEMA = SchemaBuilder.record(ChannelId.class.getSimpleName()) + .fields() + .requiredString(CHANNEL_NAME) + .name(CHANNEL_TYPE) + .type(CHANNEL_TYPE_SCHEMA) + .noDefault() + .endRecord(); + + + static final Schema REACTOR_SYSTEM_ID_SCHEMA = SchemaBuilder.record(ReActorSystemId.class.getSimpleName()) + .fields() + .name(MARKER) + .type() + .intType() + .intDefault(ReActorSystemId.NO_REACTORSYSTEM_ID_MARKER) + .optionalString(REACTOR_SYSTEM_NAME) + .name(UUID) + .type() + .optional() + .type(UUID_SCHEMA) + .endRecord(); + static final Schema REACTOR_SYSTEM_REF_SCHEMA = SchemaBuilder.record(ReActedLinkProtocol.ReActorSystemRef.class.getSimpleName()) + .fields() + .name(REACTOR_SYSTEM_ID) + .type(REACTOR_SYSTEM_ID_SCHEMA) + .noDefault() + .name(CHANNEL_ID) + .type(CHANNEL_ID_SCHEMA) + .noDefault() + .endRecord(); + static final Schema REACTOR_ID_SCHEMA = SchemaBuilder.record(ReActorId.class.getSimpleName()) + .fields() + .name(MARKER) + .type() + .intType() + .intDefault(ReActorId.NO_REACTOR_ID_MARKER) + .optionalString(REACTOR_NAME) + .name(UUID) + .type() + .optional() + .type(UUID_SCHEMA) + .endRecord(); + + static final Schema REACTOR_REF_SCHEMA = SchemaBuilder.record(ReActorRef.class.getSimpleName()) + .fields() + .name(MARKER) + .type() + .intType() + .intDefault(ReActorRef.NO_REACTOR_REF_MARKER) + .name(REACTOR_ID) + .type() + .optional() + .type(REACTOR_ID_SCHEMA) + .name(REACTOR_SYSTEM_REF) + .type() + .optional() + .type(REACTOR_SYSTEM_REF_SCHEMA) + .endRecord(); + static final Schema ACKING_POLICY_SCHEMA = SchemaBuilder.enumeration(AckingPolicy.class.getSimpleName()) + .defaultSymbol(AckingPolicy.NONE.toString()) + .symbols(Arrays.stream(AckingPolicy.values()) + .map(AckingPolicy::toString) + .toArray(String[]::new)); + + public static final Schema MESSAGE_SCHEMA = SchemaBuilder.record(Message.class.getSimpleName()) + .fields() + .name(SENDER) + .type(REACTOR_REF_SCHEMA) + .noDefault() + .name(DESTINATION) + .type(REACTOR_REF_SCHEMA) + .noDefault() + .requiredLong(SEQUENCE_NUMBER) + .name(CREATOR_REACTOR_SYSTEM_ID) + .type(REACTOR_SYSTEM_ID_SCHEMA) + .noDefault() + .name(ACKING_POLICY) + .type(ACKING_POLICY_SCHEMA) + .noDefault() + .name(PAYLOAD) + .type() + .bytesType() + .noDefault() + .endRecord(); + + public static void main(String[] args) { + System.out.println(MESSAGE_SCHEMA); + } +} diff --git a/drivers/src/main/java/io/reacted/drivers/channels/replay/ReplayLocalDriver.java b/drivers/src/main/java/io/reacted/drivers/channels/replay/ReplayLocalDriver.java index 7951ad14..0f3f1697 100644 --- a/drivers/src/main/java/io/reacted/drivers/channels/replay/ReplayLocalDriver.java +++ b/drivers/src/main/java/io/reacted/drivers/channels/replay/ReplayLocalDriver.java @@ -146,8 +146,8 @@ void onNewMessage(ReActorSystem localReActorSystem, Map emptyMap, if (!(payload instanceof EventExecutionAttempt executionAttempt)) { dstToMessageBySeqNum.computeIfAbsent(destination.getReActorId(), reActorId -> new HashMap<>()) .put(sequenceNumber, - Message.forParams(source, destination, sequenceNumber, - fromReActorSystemId, ackingPolicy, payload)); + Message.of(source, destination, sequenceNumber, + fromReActorSystemId, ackingPolicy, payload)); return; } while (!isReactorAlreadySpawned(source)) { @@ -165,7 +165,7 @@ void onNewMessage(ReActorSystem localReActorSystem, Map emptyMap, } else if (syncForwardMessageToLocalActor(originalMessage.getSender(), destinationCtx, originalMessage.getDestination(), originalMessage.getSequenceNumber(), - originalMessage.getGeneratingReActorSystem(), + originalMessage.getCreatingReactorSystemId(), originalMessage.getAckingPolicy(), originalMessage.getPayload()).isNotDelivered()) { LOGGER.error("Unable to delivery message {} for ReActor {}", diff --git a/examples/src/main/java/io/reacted/examples/benchmarking/ReactionTime.java b/examples/src/main/java/io/reacted/examples/benchmarking/ReactionTime.java index a2bbe6d2..33a60e43 100644 --- a/examples/src/main/java/io/reacted/examples/benchmarking/ReactionTime.java +++ b/examples/src/main/java/io/reacted/examples/benchmarking/ReactionTime.java @@ -11,6 +11,9 @@ import io.reacted.core.config.dispatchers.DispatcherConfig; import io.reacted.core.config.reactors.ReActorConfig; import io.reacted.core.config.reactorsystem.ReActorSystemConfig; +import io.reacted.core.mailboxes.FastBoundedMbox; +import io.reacted.core.mailboxes.FastUnboundedMbox; +import io.reacted.core.mailboxes.UnboundedMbox; import io.reacted.core.messages.reactors.ReActorInit; import io.reacted.core.reactors.ReActions; import io.reacted.core.reactors.ReActiveEntity; @@ -44,11 +47,11 @@ public static void main(String[] args) throws InterruptedException { .setDispatcherThreadsNum(1) .build()) .build()).initReActorSystem(); - int iterations = 10_000_000; + int iterations = 5_000_000; MessageGrabber latencyGrabberBody = new MessageGrabber(iterations); ReActorRef latencyGrabber = benchmarkSystem.spawn(latencyGrabberBody.getReActions(), ReActorConfig.newBuilder() - //.setMailBoxProvider((ctx) -> new FastUnboundedMbox()) + .setMailBoxProvider((ctx) -> new FastUnboundedMbox()) //.setMailBoxProvider((ctx) -> new BoundedMbox(iterations)) //.setMailBoxProvider((ctx) -> new FastUnboundedMbox()) //.setMailBoxProvider((ctx) -> new TypeCoalescingMailbox()) @@ -68,10 +71,12 @@ public static void main(String[] args) throws InterruptedException { long end; long elapsed = 0; for(long cycle = 0; cycle < iterations; cycle++) { + while (elapsed < pauseWindowDuration) { end = System.nanoTime(); elapsed = end - start; } + elapsed = 0; start = System.nanoTime(); latencyGrabber.tell(start); diff --git a/examples/src/main/java/io/reacted/examples/benchmarking/SingleChannel.java b/examples/src/main/java/io/reacted/examples/benchmarking/SingleChannel.java index 1858a43a..3a7d6ab2 100644 --- a/examples/src/main/java/io/reacted/examples/benchmarking/SingleChannel.java +++ b/examples/src/main/java/io/reacted/examples/benchmarking/SingleChannel.java @@ -22,7 +22,7 @@ public class SingleChannel { public static void main(String[] args) { - final int cycles = 1_000_000_000; + final int cycles = 1_00_000_000; ReActorSystem singleChanelSystem = new ReActorSystem(ReActorSystemConfig.newBuilder() .setExpectedReActorsNum(256) .setReactorSystemName(SingleChannel.class.getSimpleName()) diff --git a/framework/src/test/java/ConsistencyTest.java b/framework/src/test/java/ConsistencyTest.java index e67e6059..637c15e7 100644 --- a/framework/src/test/java/ConsistencyTest.java +++ b/framework/src/test/java/ConsistencyTest.java @@ -23,7 +23,7 @@ import java.time.temporal.ChronoUnit; public class ConsistencyTest { - private static final int CYCLES = 9_999_999; + private static final int CYCLES = 999_999_999; public static void main(String[] args) { @@ -44,9 +44,9 @@ public static void main(String[] args) { Instant start = Instant.now(); - BenchmarkingUtils.initAndWaitForMessageProducersToCompleteWithDedicatedExecutors(BenchmarkingUtils.constantWindowMessageSender(CYCLES/3, worker, Duration.ofNanos(10000)), - BenchmarkingUtils.constantWindowMessageSender(CYCLES/3, worker, Duration.ofNanos(500000)), - BenchmarkingUtils.constantWindowMessageSender(CYCLES/3, worker, Duration.ofNanos(5000))); + BenchmarkingUtils.initAndWaitForMessageProducersToCompleteWithDedicatedExecutors(BenchmarkingUtils.nonStopMessageSender(CYCLES/3, worker), //Duration.ofNanos(10000)), + BenchmarkingUtils.nonStopMessageSender(CYCLES/3, worker), //Duration.ofNanos(500000)), + BenchmarkingUtils.nonStopMessageSender(CYCLES/3, worker)); //, Duration.ofNanos(5000))); System.err.println("Completed in " + ChronoUnit.SECONDS.between(start, Instant.now())); @@ -95,7 +95,7 @@ private void onPayload(ReActorContext ctx, Long payLoad) { } marker = 1; counter++; - BenchmarkingUtils.nanoSleep(100); + //BenchmarkingUtils.nanoSleep(100); if (marker != 1) { System.err.println("CRITIC!"); System.exit(2); diff --git a/pom.xml b/pom.xml index 0e614942..cf8d87ba 100644 --- a/pom.xml +++ b/pom.xml @@ -102,6 +102,7 @@ 1.51.0 3.21.9 0.6.1 + 1.11.1 6.0.53 3.0.0 3.3.1 @@ -288,6 +289,41 @@ commons-io ${commons-io.version} + + org.apache.avro + avro + ${avro.maven.version} + + + org.apache.avro + avro-maven-plugin + ${avro.maven.version} + + + org.apache.avro + avro-compiler + ${avro.maven.version} + + + org.apache.avro + avro-ipc + ${avro.maven.version} + + + org.apache.avro + avro + ${avro.maven.version} + + + org.apache.avro + avro-compiler + ${avro.maven.version} + + + org.apache.avro + avro-ipc + ${avro.maven.version} + @@ -302,7 +338,6 @@ ${jmh.version} test - From b61f98d5481b2d9cae0f1206f2e77b062ea168f6 Mon Sep 17 00:00:00 2001 From: wireknight Date: Tue, 20 Dec 2022 23:05:55 +0100 Subject: [PATCH 05/16] Reactor Context default name change Datalink Object removed Kafka driver refactored to include avro --- drivers/pom.xml | 4 + drivers/src/main/avro/Message.avdl | 14 +- .../drivers/channels/kafka/KafkaDriver.java | 87 ++++------ .../drivers/channels/kafka/KafkaUtils.java | 86 ++++++++-- .../drivers/channels/kafka/MessageSchema.java | 153 ------------------ pom.xml | 13 +- 6 files changed, 124 insertions(+), 233 deletions(-) delete mode 100644 drivers/src/main/java/io/reacted/drivers/channels/kafka/MessageSchema.java diff --git a/drivers/pom.xml b/drivers/pom.xml index 22152174..32881499 100644 --- a/drivers/pom.xml +++ b/drivers/pom.xml @@ -43,6 +43,10 @@ reacted-drivers + + io.confluent + kafka-avro-serializer + org.junit.jupiter junit-jupiter-api diff --git a/drivers/src/main/avro/Message.avdl b/drivers/src/main/avro/Message.avdl index 2c054369..a7a472d9 100644 --- a/drivers/src/main/avro/Message.avdl +++ b/drivers/src/main/avro/Message.avdl @@ -4,7 +4,7 @@ protocol ReactedMessageProtocol { ReActorRef? source; ReActorRef? destination; long sequence_number; - ReactorSystemId creator_reactor_system; + ReActorSystemId creator_reactor_system; AckingPolicy acking_policy; bytes payload; } @@ -15,16 +15,16 @@ protocol ReactedMessageProtocol { record ReActorRef { ReActorId reactor_id; - ReactorSystemRef reactor_system_ref; + ReActorSystemRef reactor_system_ref; } - record ReactorSystemRef { - ReactorSystemId reactor_system_id; + record ReActorSystemRef { + ReActorSystemId reactor_system_id; ChannelId channel_id; } - record ReactorSystemId { - UUID reactor_system_id; + record ReActorSystemId { + UUID? reactor_system_id; string reactor_system_name; } @@ -38,7 +38,7 @@ protocol ReactedMessageProtocol { } record ReActorId { - UUID id; + UUID? id; string name; } diff --git a/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaDriver.java b/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaDriver.java index d3bff0b7..423ed50f 100644 --- a/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaDriver.java +++ b/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaDriver.java @@ -8,7 +8,11 @@ package io.reacted.drivers.channels.kafka; +import io.confluent.kafka.serializers.KafkaAvroDeserializer; +import io.confluent.kafka.serializers.KafkaAvroSerializer; import io.reacted.core.config.ChannelId; +import io.reacted.core.drivers.DriverCtx; +import io.reacted.core.drivers.system.ReActorSystemDriver; import io.reacted.core.drivers.system.RemotingDriver; import io.reacted.core.messages.AckingPolicy; import io.reacted.core.messages.Message; @@ -20,7 +24,6 @@ import io.reacted.patterns.NonNullByDefault; import io.reacted.patterns.Try; import io.reacted.patterns.UnChecked; -import org.apache.avro.Protocol; import org.apache.kafka.clients.consumer.Consumer; import org.apache.kafka.clients.consumer.ConsumerConfig; import org.apache.kafka.clients.consumer.KafkaConsumer; @@ -29,18 +32,12 @@ import org.apache.kafka.clients.producer.ProducerConfig; import org.apache.kafka.clients.producer.ProducerRecord; import org.apache.kafka.common.errors.InterruptException; -import org.apache.kafka.common.serialization.Deserializer; -import org.apache.kafka.common.serialization.LongDeserializer; -import org.apache.kafka.common.serialization.LongSerializer; -import org.apache.kafka.common.serialization.Serializer; +import org.apache.kafka.common.serialization.StringDeserializer; +import org.apache.kafka.common.serialization.StringSerializer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.annotation.Nullable; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; import java.io.Serializable; import java.time.Duration; import java.util.List; @@ -58,9 +55,9 @@ public class KafkaDriver extends RemotingDriver { private static final byte[] NO_SERIALIZED_PAYLOAD = null; private static final Duration POLL_TIMEOUT = Duration.ofSeconds(1); @Nullable - private Consumer kafkaConsumer; + private Consumer kafkaConsumer; @Nullable - private Producer kafkaProducer; + private Producer kafkaProducer; public KafkaDriver(KafkaDriverConfig config) { super(config); @@ -99,6 +96,7 @@ DeliveryStatus sendMessage(ReActorRef source, ReActorContext destinationCtx, ReA PayloadT payload) { try { + Objects.requireNonNull(kafkaProducer) .send(new ProducerRecord<>(getDriverConfig().getTopic(), KafkaUtils.toKafkaMessage(source, destination, sequenceNumber, @@ -112,72 +110,47 @@ DeliveryStatus sendMessage(ReActorRef source, ReActorContext destinationCtx, ReA } } - private static Consumer createConsumer(KafkaDriverConfig driverConfig) { + private static Consumer createConsumer(KafkaDriverConfig driverConfig) { Properties props = new Properties(); props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, driverConfig.getBootstrapEndpoint()); props.put(ConsumerConfig.GROUP_ID_CONFIG, driverConfig.getGroupId()); - props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, LongDeserializer.class.getName()); - props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, MessageDecoder.class.getName()); + props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName()); + props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, KafkaAvroDeserializer.class.getName()); props.put(ConsumerConfig.MAX_POLL_RECORDS_CONFIG, driverConfig.getMaxPollRecords()); props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "false"); props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "latest"); - Consumer consumer = new KafkaConsumer<>(props); + Consumer consumer = new KafkaConsumer<>(props); consumer.subscribe(List.of(driverConfig.getTopic())); return consumer; } - public static Producer createProducer(KafkaDriverConfig driverConfig) { + public static Producer createProducer(KafkaDriverConfig driverConfig) { Properties props = new Properties(); props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, driverConfig.getBootstrapEndpoint()); - props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, LongSerializer.class.getName()); - props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, MessageEncoder.class.getName()); + props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName()); + props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, KafkaAvroSerializer.class.getName()); return new KafkaProducer<>(props); } - private static void kafkaDriverLoop(Consumer kafkaConsumer, KafkaDriver thisDriver, - ReActorSystem localReActorSystem) { + private static void kafkaDriverLoop(Consumer kafkaConsumer, + KafkaDriver thisDriver, ReActorSystem localReActorSystem) { + DriverCtx driverCtx = ReActorSystemDriver.getDriverCtx(); while(!Thread.currentThread().isInterrupted()) { try { - kafkaConsumer.poll(POLL_TIMEOUT) - .forEach(record -> thisDriver.offerMessage(record.value().getSender(), - record.value().getDestination(), - record.value().getSequenceNumber(), - record.value().getCreatingReactorSystemId(), - record.value().getAckingPolicy(), - record.value().getPayload())); + for(var record : kafkaConsumer.poll(POLL_TIMEOUT)) { + thisDriver.offerMessage(KafkaUtils.toReActorRef(record.value().getSource(), driverCtx), + KafkaUtils.toReActorRef(record.value().getDestination(), driverCtx), + record.value().getSequenceNumber(), + KafkaUtils.toReActorSystemId(record.value().getCreatorReactorSystem()), + KafkaUtils.toAckingPolicy(record.value().getAckingPolicy()), + KafkaUtils.fromSerializedPayload(record.value().getPayload())); + + } } catch (InterruptException interruptException) { Thread.currentThread().interrupt(); break; - } catch (Exception exchetionWhileOffering) { - localReActorSystem.logError("Unable to fetch messages from kafka", exchetionWhileOffering); - } - } - } - - public static class MessageDecoder implements Deserializer { - @Override - @Nullable - public Message deserialize(String topic, byte[] data) { - try (var inputStream = new ObjectInputStream(new ByteArrayInputStream(data))) { - return (Message)inputStream.readObject(); - } catch (Exception anyMessageDecodeError) { - LOGGER.error("Unable to properly decode message", anyMessageDecodeError); - return NO_VALID_PAYLOAD; - } - } - } - - public static class MessageEncoder implements Serializer { - @Override - @Nullable - public byte[] serialize(String topic, Message data) { - try (var byteArrayOutputStream = new ByteArrayOutputStream(); - var objectOutputStream = new ObjectOutputStream(byteArrayOutputStream)) { - objectOutputStream.writeObject(data); - return byteArrayOutputStream.toByteArray(); - } catch (Exception anyMessageEncodeError) { - LOGGER.error("Unable to encode message", anyMessageEncodeError); - return NO_SERIALIZED_PAYLOAD; + } catch (Exception exceptionWhileOffering) { + localReActorSystem.logError("Unable to fetch messages from kafka", exceptionWhileOffering); } } } diff --git a/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaUtils.java b/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaUtils.java index 4eb6413d..60e12542 100644 --- a/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaUtils.java +++ b/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaUtils.java @@ -8,8 +8,8 @@ package io.reacted.drivers.channels.kafka; +import io.reacted.core.drivers.DriverCtx; import io.reacted.core.messages.AckingPolicy; -import io.reacted.core.reactorsystem.ReActorContext; import io.reacted.core.reactorsystem.ReActorRef; import io.reacted.core.reactorsystem.ReActorSystemId; import io.reacted.core.reactorsystem.ReActorSystemRef; @@ -17,16 +17,17 @@ import io.reacted.drivers.channels.kafka.avro.ChannelType; import io.reacted.drivers.channels.kafka.avro.Message; import io.reacted.drivers.channels.kafka.avro.ReActorId; -import io.reacted.drivers.channels.kafka.avro.ReactorSystemId; -import io.reacted.drivers.channels.kafka.avro.ReactorSystemRef; import io.reacted.drivers.channels.kafka.avro.UUID; import javax.annotation.Nullable; +import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.nio.ByteBuffer; +import java.util.Objects; final class KafkaUtils { private KafkaUtils() { throw new AssertionError("We are not supposed to be called"); } @@ -46,14 +47,37 @@ Message toKafkaMessage(ReActorRef source, ReActorRef destination, long sequenceN if (!destination.equals(ReActorRef.NO_REACTOR_REF)) { avroMessageBuilder.setDestination(fromReActorRef(destination)); } + avroMessageBuilder.setPayload(toSerializedPayload(payload)); + return avroMessageBuilder.build(); + } + + static ByteBuffer toSerializedPayload(Serializable payload) throws IOException { try(ByteArrayOutputStream byteArray = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(byteArray)) { oos.writeObject(payload); - avroMessageBuilder.setPayload(ByteBuffer.wrap(byteArray.toByteArray())); + return ByteBuffer.wrap(byteArray.toByteArray()); } - return avroMessageBuilder.build(); } + static Serializable fromSerializedPayload(ByteBuffer serializedPayload) throws IOException, ClassNotFoundException { + try (var bais = new ByteArrayInputStream(serializedPayload.array()); + var inputStream = new ObjectInputStream(bais)) { + return (Serializable) inputStream.readObject(); + } + } + + static ReActorRef toReActorRef(@Nullable io.reacted.drivers.channels.kafka.avro.ReActorRef reActorRef, + DriverCtx driverCtx) { + if (reActorRef == null) { + return ReActorRef.NO_REACTOR_REF; + } + return new ReActorRef(toReActorId(reActorRef.getReactorId()), + toReActorSystemRef(reActorRef.getReactorSystemRef(), driverCtx)); + } + + static AckingPolicy toAckingPolicy(io.reacted.drivers.channels.kafka.avro.AckingPolicy ackingPolicy) { + return AckingPolicy.forOrdinal(ackingPolicy.getAckingPolicyOrdinal()); + } private static io.reacted.drivers.channels.kafka.avro.AckingPolicy fromAckingPolicy(AckingPolicy ackingPolicy) { return io.reacted.drivers.channels.kafka.avro.AckingPolicy.newBuilder() .setAckingPolicyOrdinal(ackingPolicy.ordinal()) @@ -67,11 +91,28 @@ private static io.reacted.drivers.channels.kafka.avro.ReActorRef fromReActorRef( .build(); } - private static ReactorSystemRef fromReActorSystemRef(ReActorSystemRef reActorSystemRef) { - return ReactorSystemRef.newBuilder() - .setChannelId(fromChannelId(reActorSystemRef.getChannelId())) - .setReactorSystemId(fromReActorSystemId(reActorSystemRef.getReActorSystemId())) - .build(); + private static ReActorSystemRef toReActorSystemRef(io.reacted.drivers.channels.kafka.avro.ReActorSystemRef reActorSystemRef, + DriverCtx driverCtx) { + var newRef = new ReActorSystemRef(); + var reActorSystemId = toReActorSystemId(reActorSystemRef.getReactorSystemId()); + var channelId = toChannelId(reActorSystemRef.getChannelId()); + ReActorSystemRef.setGateForReActorSystem(newRef, reActorSystemId, channelId, driverCtx); + return newRef; + } + private static io.reacted.drivers.channels.kafka.avro.ReActorSystemRef fromReActorSystemRef(ReActorSystemRef reActorSystemRef) { + return io.reacted.drivers.channels.kafka.avro.ReActorSystemRef.newBuilder() + .setChannelId(fromChannelId(reActorSystemRef.getChannelId())) + .setReactorSystemId(fromReActorSystemId(reActorSystemRef.getReActorSystemId())) + .build(); + } + + private static io.reacted.core.reactors.ReActorId toReActorId(ReActorId reActorId) { + java.util.UUID uuid = toUUID(reActorId.getId()); + String reActorName = reActorId.getName().toString(); + return new io.reacted.core.reactors.ReActorId() + .setReActorName(reActorName) + .setReActorUUID(uuid) + .setHashCode(Objects.hash(uuid, reActorName)); } private static ReActorId fromReActorId(io.reacted.core.reactors.ReActorId reActorId) { return ReActorId.newBuilder() @@ -79,13 +120,19 @@ private static ReActorId fromReActorId(io.reacted.core.reactors.ReActorId reActo .setName(reActorId.getReActorName()) .build(); } - private static ReactorSystemId fromReActorSystemId(ReActorSystemId reActorSystemId) { - return ReactorSystemId.newBuilder() - .setReactorSystemId(fromUUID(reActorSystemId.getReActorSystemUUID())) - .setReactorSystemName(reActorSystemId.getReActorSystemName()) - .build(); + + static ReActorSystemId toReActorSystemId(io.reacted.drivers.channels.kafka.avro.ReActorSystemId reactorSystemId) { + return new ReActorSystemId(reactorSystemId.getReactorSystemName().toString()); + } + private static io.reacted.drivers.channels.kafka.avro.ReActorSystemId fromReActorSystemId(ReActorSystemId reActorSystemId) { + return io.reacted.drivers.channels.kafka.avro.ReActorSystemId.newBuilder() + .setReactorSystemName(reActorSystemId.getReActorSystemName()) + .build(); } + private static io.reacted.core.config.ChannelId toChannelId(ChannelId channelId) { + return toChannelType(channelId.getChannelType()).forChannelName(channelId.getChannelName().toString()); + } private static ChannelId fromChannelId(io.reacted.core.config.ChannelId channelId) { return ChannelId.newBuilder() .setChannelName(channelId.getChannelName()) @@ -93,11 +140,20 @@ private static ChannelId fromChannelId(io.reacted.core.config.ChannelId channelI .build(); } + private static io.reacted.core.config.ChannelId.ChannelType toChannelType(ChannelType channelType) { + return io.reacted.core.config.ChannelId.ChannelType.forOrdinal(channelType.getChannelTypeOrdinal()); + } + private static ChannelType fromChannelType(io.reacted.core.config.ChannelId.ChannelType channelType) { return ChannelType.newBuilder() .setChannelTypeOrdinal(channelType.ordinal()) .build(); } + + private static java.util.UUID toUUID(UUID uuid) { + return new java.util.UUID(uuid.getMostSignificant(), + uuid.getLeastSignificant()); + } private static UUID fromUUID(java.util.UUID uuid) { return UUID.newBuilder() .setMostSignificant(uuid.getMostSignificantBits()) diff --git a/drivers/src/main/java/io/reacted/drivers/channels/kafka/MessageSchema.java b/drivers/src/main/java/io/reacted/drivers/channels/kafka/MessageSchema.java deleted file mode 100644 index d475331d..00000000 --- a/drivers/src/main/java/io/reacted/drivers/channels/kafka/MessageSchema.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (c) 2022 , [ pierre@reacted.io ] - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. - */ - -package io.reacted.drivers.channels.kafka; - -import io.reacted.core.config.ChannelId; -import io.reacted.core.messages.AckingPolicy; -import io.reacted.core.messages.Message; -import io.reacted.core.reactors.ReActorId; -import io.reacted.core.reactorsystem.ReActorRef; -import io.reacted.core.reactorsystem.ReActorSystemId; -import io.reacted.drivers.channels.grpc.ReActedLinkProtocol; -import org.apache.avro.Schema; -import org.apache.avro.SchemaBuilder; - -import java.util.Arrays; - - -final class MessageSchema { - - static final String REACTOR_ID = "RI"; - static final String REACTOR_NAME = "RN"; - static final String SENDER = "S"; - static final String DESTINATION = "D"; - static final String SEQUENCE_NUMBER = "s"; - static final String CREATOR_REACTOR_SYSTEM_ID = "CRSI"; - static final String ACKING_POLICY = "A"; - - static final String PAYLOAD = "P"; - static final String REACTOR_SYSTEM_NAME = "RSN"; - static final String REACTOR_SYSTEM_ID = "RSI"; - - static final String REACTOR_SYSTEM_REF = "RSR"; - static final String CHANNEL_ID = "CI"; - static final String CHANNEL_TYPE = "CT"; - static final String CHANNEL_NAME = "CN"; - static final String UUID = "U"; - static final String UUID_MOST_SIGNIFICANT = "UM"; - static final String UUID_LEAST_SIGNIFICANT = "UL"; - static final String MARKER = "MK"; - private MessageSchema() { throw new AssertionError("This is not supposed to be called"); } - - static final Schema UUID_SCHEMA = SchemaBuilder.record(java.util.UUID.class.getSimpleName()) - .fields() - .name(UUID_MOST_SIGNIFICANT) - .type() - .longType() - .longDefault(0) - .name(UUID_LEAST_SIGNIFICANT) - .type() - .longType() - .longDefault(0) - .endRecord(); - - static final Schema CHANNEL_TYPE_SCHEMA = SchemaBuilder.enumeration(ChannelId.ChannelType.class.getSimpleName()) - .symbols(Arrays.stream(ChannelId.ChannelType.values()) - .map(ChannelId.ChannelType::toString) - .toArray(String[]::new)); - - static final Schema CHANNEL_ID_SCHEMA = SchemaBuilder.record(ChannelId.class.getSimpleName()) - .fields() - .requiredString(CHANNEL_NAME) - .name(CHANNEL_TYPE) - .type(CHANNEL_TYPE_SCHEMA) - .noDefault() - .endRecord(); - - - static final Schema REACTOR_SYSTEM_ID_SCHEMA = SchemaBuilder.record(ReActorSystemId.class.getSimpleName()) - .fields() - .name(MARKER) - .type() - .intType() - .intDefault(ReActorSystemId.NO_REACTORSYSTEM_ID_MARKER) - .optionalString(REACTOR_SYSTEM_NAME) - .name(UUID) - .type() - .optional() - .type(UUID_SCHEMA) - .endRecord(); - static final Schema REACTOR_SYSTEM_REF_SCHEMA = SchemaBuilder.record(ReActedLinkProtocol.ReActorSystemRef.class.getSimpleName()) - .fields() - .name(REACTOR_SYSTEM_ID) - .type(REACTOR_SYSTEM_ID_SCHEMA) - .noDefault() - .name(CHANNEL_ID) - .type(CHANNEL_ID_SCHEMA) - .noDefault() - .endRecord(); - static final Schema REACTOR_ID_SCHEMA = SchemaBuilder.record(ReActorId.class.getSimpleName()) - .fields() - .name(MARKER) - .type() - .intType() - .intDefault(ReActorId.NO_REACTOR_ID_MARKER) - .optionalString(REACTOR_NAME) - .name(UUID) - .type() - .optional() - .type(UUID_SCHEMA) - .endRecord(); - - static final Schema REACTOR_REF_SCHEMA = SchemaBuilder.record(ReActorRef.class.getSimpleName()) - .fields() - .name(MARKER) - .type() - .intType() - .intDefault(ReActorRef.NO_REACTOR_REF_MARKER) - .name(REACTOR_ID) - .type() - .optional() - .type(REACTOR_ID_SCHEMA) - .name(REACTOR_SYSTEM_REF) - .type() - .optional() - .type(REACTOR_SYSTEM_REF_SCHEMA) - .endRecord(); - static final Schema ACKING_POLICY_SCHEMA = SchemaBuilder.enumeration(AckingPolicy.class.getSimpleName()) - .defaultSymbol(AckingPolicy.NONE.toString()) - .symbols(Arrays.stream(AckingPolicy.values()) - .map(AckingPolicy::toString) - .toArray(String[]::new)); - - public static final Schema MESSAGE_SCHEMA = SchemaBuilder.record(Message.class.getSimpleName()) - .fields() - .name(SENDER) - .type(REACTOR_REF_SCHEMA) - .noDefault() - .name(DESTINATION) - .type(REACTOR_REF_SCHEMA) - .noDefault() - .requiredLong(SEQUENCE_NUMBER) - .name(CREATOR_REACTOR_SYSTEM_ID) - .type(REACTOR_SYSTEM_ID_SCHEMA) - .noDefault() - .name(ACKING_POLICY) - .type(ACKING_POLICY_SCHEMA) - .noDefault() - .name(PAYLOAD) - .type() - .bytesType() - .noDefault() - .endRecord(); - - public static void main(String[] args) { - System.out.println(MESSAGE_SCHEMA); - } -} diff --git a/pom.xml b/pom.xml index cf8d87ba..43cc9700 100644 --- a/pom.xml +++ b/pom.xml @@ -52,7 +52,12 @@ - + + + confluent + https://packages.confluent.io/maven/ + + ossrh @@ -103,6 +108,7 @@ 3.21.9 0.6.1 1.11.1 + 7.3.1 6.0.53 3.0.0 3.3.1 @@ -122,6 +128,11 @@ + + io.confluent + kafka-avro-serializer + ${kafka.avro.serializer.version} + org.apache.commons commons-lang3 From d7ec4f59612ebad66d78a5dab4b9e31c6f8df9b5 Mon Sep 17 00:00:00 2001 From: wireknight Date: Wed, 21 Dec 2022 00:05:52 +0100 Subject: [PATCH 06/16] Reactor Context default name change Datalink Object removed Kafka driver refactored to include avro --- .../drivers/channels/kafka/KafkaDriver.java | 12 +-- .../drivers/channels/kafka/KafkaUtils.java | 84 +++++++++---------- 2 files changed, 48 insertions(+), 48 deletions(-) diff --git a/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaDriver.java b/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaDriver.java index 423ed50f..d902a28b 100644 --- a/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaDriver.java +++ b/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaDriver.java @@ -99,8 +99,8 @@ DeliveryStatus sendMessage(ReActorRef source, ReActorContext destinationCtx, ReA Objects.requireNonNull(kafkaProducer) .send(new ProducerRecord<>(getDriverConfig().getTopic(), - KafkaUtils.toKafkaMessage(source, destination, sequenceNumber, - reActorSystemId, ackingPolicy, payload))) + KafkaUtils.toAvroMessage(source, destination, sequenceNumber, + reActorSystemId, ackingPolicy, payload))) .get(); return DeliveryStatus.SENT; } catch (Exception sendError) { @@ -138,11 +138,11 @@ private static void kafkaDriverLoop(Consumer - Message toKafkaMessage(ReActorRef source, ReActorRef destination, long sequenceNumber, - ReActorSystemId reActorSystemId, AckingPolicy ackingPolicy, - PayloadT payload) throws IOException { + Message toAvroMessage(ReActorRef source, ReActorRef destination, long sequenceNumber, + ReActorSystemId reActorSystemId, AckingPolicy ackingPolicy, + PayloadT payload) throws IOException { Message.Builder avroMessageBuilder = Message.newBuilder() .setSequenceNumber(sequenceNumber) - .setAckingPolicy(fromAckingPolicy(ackingPolicy)) - .setCreatorReactorSystem(fromReActorSystemId(reActorSystemId)); + .setAckingPolicy(toAvroAckingPolicy(ackingPolicy)) + .setCreatorReactorSystem(toAvroReActorSystemId(reActorSystemId)); if (!source.equals(ReActorRef.NO_REACTOR_REF)) { - avroMessageBuilder.setSource(fromReActorRef(source)); + avroMessageBuilder.setSource(toAvroReActorRef(source)); } if (!destination.equals(ReActorRef.NO_REACTOR_REF)) { - avroMessageBuilder.setDestination(fromReActorRef(destination)); + avroMessageBuilder.setDestination(toAvroReActorRef(destination)); } avroMessageBuilder.setPayload(toSerializedPayload(payload)); return avroMessageBuilder.build(); @@ -66,95 +66,95 @@ static Serializable fromSerializedPayload(ByteBuffer serializedPayload) throws I } } - static ReActorRef toReActorRef(@Nullable io.reacted.drivers.channels.kafka.avro.ReActorRef reActorRef, - DriverCtx driverCtx) { + static ReActorRef fromAvroReActorRef(@Nullable io.reacted.drivers.channels.kafka.avro.ReActorRef reActorRef, + DriverCtx driverCtx) { if (reActorRef == null) { return ReActorRef.NO_REACTOR_REF; } - return new ReActorRef(toReActorId(reActorRef.getReactorId()), - toReActorSystemRef(reActorRef.getReactorSystemRef(), driverCtx)); + return new ReActorRef(fromAvroReActorId(reActorRef.getReactorId()), + fromAvroReActorSystemRef(reActorRef.getReactorSystemRef(), driverCtx)); } - static AckingPolicy toAckingPolicy(io.reacted.drivers.channels.kafka.avro.AckingPolicy ackingPolicy) { + static AckingPolicy fromAvroAckingPolicy(io.reacted.drivers.channels.kafka.avro.AckingPolicy ackingPolicy) { return AckingPolicy.forOrdinal(ackingPolicy.getAckingPolicyOrdinal()); } - private static io.reacted.drivers.channels.kafka.avro.AckingPolicy fromAckingPolicy(AckingPolicy ackingPolicy) { + + static ReActorSystemId fromAvroReActorSystemId(io.reacted.drivers.channels.kafka.avro.ReActorSystemId reactorSystemId) { + return new ReActorSystemId(reactorSystemId.getReactorSystemName().toString()); + } + + private static io.reacted.drivers.channels.kafka.avro.AckingPolicy toAvroAckingPolicy(AckingPolicy ackingPolicy) { return io.reacted.drivers.channels.kafka.avro.AckingPolicy.newBuilder() .setAckingPolicyOrdinal(ackingPolicy.ordinal()) .build(); } - - private static io.reacted.drivers.channels.kafka.avro.ReActorRef fromReActorRef(ReActorRef reActorRef) { + private static io.reacted.drivers.channels.kafka.avro.ReActorRef toAvroReActorRef(ReActorRef reActorRef) { return io.reacted.drivers.channels.kafka.avro.ReActorRef.newBuilder() - .setReactorId(fromReActorId(reActorRef.getReActorId())) - .setReactorSystemRef(fromReActorSystemRef(reActorRef.getReActorSystemRef())) + .setReactorId(toAvroReActorId(reActorRef.getReActorId())) + .setReactorSystemRef(toAvroReActorSystemRef(reActorRef.getReActorSystemRef())) .build(); } - - private static ReActorSystemRef toReActorSystemRef(io.reacted.drivers.channels.kafka.avro.ReActorSystemRef reActorSystemRef, - DriverCtx driverCtx) { + private static ReActorSystemRef fromAvroReActorSystemRef(io.reacted.drivers.channels.kafka.avro.ReActorSystemRef reActorSystemRef, + DriverCtx driverCtx) { var newRef = new ReActorSystemRef(); - var reActorSystemId = toReActorSystemId(reActorSystemRef.getReactorSystemId()); - var channelId = toChannelId(reActorSystemRef.getChannelId()); + var reActorSystemId = fromAvroReActorSystemId(reActorSystemRef.getReactorSystemId()); + var channelId = fromAvroChannelId(reActorSystemRef.getChannelId()); ReActorSystemRef.setGateForReActorSystem(newRef, reActorSystemId, channelId, driverCtx); return newRef; } - private static io.reacted.drivers.channels.kafka.avro.ReActorSystemRef fromReActorSystemRef(ReActorSystemRef reActorSystemRef) { + private static io.reacted.drivers.channels.kafka.avro.ReActorSystemRef toAvroReActorSystemRef(ReActorSystemRef reActorSystemRef) { return io.reacted.drivers.channels.kafka.avro.ReActorSystemRef.newBuilder() - .setChannelId(fromChannelId(reActorSystemRef.getChannelId())) - .setReactorSystemId(fromReActorSystemId(reActorSystemRef.getReActorSystemId())) + .setChannelId(toAvroChannelId(reActorSystemRef.getChannelId())) + .setReactorSystemId(toAvroReActorSystemId(reActorSystemRef.getReActorSystemId())) .build(); } - - private static io.reacted.core.reactors.ReActorId toReActorId(ReActorId reActorId) { - java.util.UUID uuid = toUUID(reActorId.getId()); + private static io.reacted.core.reactors.ReActorId fromAvroReActorId(ReActorId reActorId) { + java.util.UUID uuid = fromAvroUUID(reActorId.getId()); String reActorName = reActorId.getName().toString(); return new io.reacted.core.reactors.ReActorId() .setReActorName(reActorName) .setReActorUUID(uuid) .setHashCode(Objects.hash(uuid, reActorName)); } - private static ReActorId fromReActorId(io.reacted.core.reactors.ReActorId reActorId) { + + private static ReActorId toAvroReActorId(io.reacted.core.reactors.ReActorId reActorId) { return ReActorId.newBuilder() - .setId(fromUUID(reActorId.getReActorUUID())) + .setId(toAvroUUID(reActorId.getReActorUUID())) .setName(reActorId.getReActorName()) .build(); } - static ReActorSystemId toReActorSystemId(io.reacted.drivers.channels.kafka.avro.ReActorSystemId reactorSystemId) { - return new ReActorSystemId(reactorSystemId.getReactorSystemName().toString()); - } - private static io.reacted.drivers.channels.kafka.avro.ReActorSystemId fromReActorSystemId(ReActorSystemId reActorSystemId) { + private static io.reacted.drivers.channels.kafka.avro.ReActorSystemId toAvroReActorSystemId(ReActorSystemId reActorSystemId) { return io.reacted.drivers.channels.kafka.avro.ReActorSystemId.newBuilder() .setReactorSystemName(reActorSystemId.getReActorSystemName()) .build(); } - private static io.reacted.core.config.ChannelId toChannelId(ChannelId channelId) { - return toChannelType(channelId.getChannelType()).forChannelName(channelId.getChannelName().toString()); + private static io.reacted.core.config.ChannelId fromAvroChannelId(ChannelId channelId) { + return fromAvroChannelType(channelId.getChannelType()).forChannelName(channelId.getChannelName().toString()); } - private static ChannelId fromChannelId(io.reacted.core.config.ChannelId channelId) { + private static ChannelId toAvroChannelId(io.reacted.core.config.ChannelId channelId) { return ChannelId.newBuilder() .setChannelName(channelId.getChannelName()) - .setChannelType(fromChannelType(channelId.getChannelType())) + .setChannelType(toAvroChannelType(channelId.getChannelType())) .build(); } - private static io.reacted.core.config.ChannelId.ChannelType toChannelType(ChannelType channelType) { + private static io.reacted.core.config.ChannelId.ChannelType fromAvroChannelType(ChannelType channelType) { return io.reacted.core.config.ChannelId.ChannelType.forOrdinal(channelType.getChannelTypeOrdinal()); } - private static ChannelType fromChannelType(io.reacted.core.config.ChannelId.ChannelType channelType) { + private static ChannelType toAvroChannelType(io.reacted.core.config.ChannelId.ChannelType channelType) { return ChannelType.newBuilder() .setChannelTypeOrdinal(channelType.ordinal()) .build(); } - private static java.util.UUID toUUID(UUID uuid) { + private static java.util.UUID fromAvroUUID(UUID uuid) { return new java.util.UUID(uuid.getMostSignificant(), uuid.getLeastSignificant()); } - private static UUID fromUUID(java.util.UUID uuid) { + private static UUID toAvroUUID(java.util.UUID uuid) { return UUID.newBuilder() .setMostSignificant(uuid.getMostSignificantBits()) .setLeastSignificant(uuid.getLeastSignificantBits()) From 51c527d559c7d09b818d56e00dd6a24e0f46bebb Mon Sep 17 00:00:00 2001 From: wireknight Date: Wed, 21 Dec 2022 00:12:54 +0100 Subject: [PATCH 07/16] Reactor Context default name change Datalink Object removed Kafka driver refactored to include avro --- .../core/mailboxes/BackpressuringMbox.java | 3 ++- .../core/reactorsystem/ReActorContext.java | 17 +++++------- drivers/pom.xml | 4 --- .../benchmarking/BenchmarkingUtils.java | 4 +-- .../examples/benchmarking/MessageTsunami.java | 27 ++++++++----------- .../examples/benchmarking/ReactionTime.java | 2 -- pom.xml | 15 ----------- 7 files changed, 21 insertions(+), 51 deletions(-) diff --git a/core/src/main/java/io/reacted/core/mailboxes/BackpressuringMbox.java b/core/src/main/java/io/reacted/core/mailboxes/BackpressuringMbox.java index 713ab3c8..31dcf31a 100644 --- a/core/src/main/java/io/reacted/core/mailboxes/BackpressuringMbox.java +++ b/core/src/main/java/io/reacted/core/mailboxes/BackpressuringMbox.java @@ -129,7 +129,8 @@ public boolean isDelayable(Class payloadType) { return !notDelayable.get().contains(payloadType); } - public BackpressuringMbox addNonDelayableTypes(Class ...notDelayedToAdd) { + @SafeVarargs + public final BackpressuringMbox addNonDelayableTypes(Class... notDelayedToAdd) { return addNonDelayableTypes(Arrays.stream(notDelayedToAdd).collect(Collectors.toSet())); } public BackpressuringMbox addNonDelayableTypes(Set> notDelayedToAdd) { diff --git a/core/src/main/java/io/reacted/core/reactorsystem/ReActorContext.java b/core/src/main/java/io/reacted/core/reactorsystem/ReActorContext.java index 60f32e54..f8b7c829 100644 --- a/core/src/main/java/io/reacted/core/reactorsystem/ReActorContext.java +++ b/core/src/main/java/io/reacted/core/reactorsystem/ReActorContext.java @@ -21,6 +21,8 @@ import io.reacted.core.typedsubscriptions.TypedSubscriptionsManager; import io.reacted.patterns.NonNullByDefault; import io.reacted.patterns.Try; + +import javax.annotation.Nullable; import java.io.Serializable; import java.time.Duration; import java.util.Arrays; @@ -38,7 +40,6 @@ import java.util.function.BiConsumer; import java.util.function.Function; import java.util.stream.Stream; -import javax.annotation.Nullable; @NonNullByDefault public class ReActorContext { @@ -108,18 +109,12 @@ private ReActorContext(Builder reActorCtxBuilder) { public long getNextMsgExecutionId() { return msgExecutionId.getAndIncrement(); } - public synchronized boolean acquireScheduling() { - if (isNaiveScheduled) { return false; } - this.isNaiveScheduled = true; - return true; - //return isScheduled.compareAndSet(false, true); + public boolean acquireScheduling() { + return isScheduled.compareAndSet(false, true); } - public synchronized boolean releaseScheduling() { - if (!isNaiveScheduled) { return false; } - this.isNaiveScheduled = false; - return true; - //return isScheduled.compareAndSet(true, false); + public boolean releaseScheduling() { + return isScheduled.compareAndSet(true, false); } @SuppressWarnings("UnusedReturnValue") diff --git a/drivers/pom.xml b/drivers/pom.xml index 32881499..9ed267c4 100644 --- a/drivers/pom.xml +++ b/drivers/pom.xml @@ -200,10 +200,6 @@ org.xolstice.maven.plugins protobuf-maven-plugin - - org.apache.avro - avro-maven-plugin - \ No newline at end of file diff --git a/examples/src/main/java/io/reacted/examples/benchmarking/BenchmarkingUtils.java b/examples/src/main/java/io/reacted/examples/benchmarking/BenchmarkingUtils.java index cf55e36c..337a02c2 100644 --- a/examples/src/main/java/io/reacted/examples/benchmarking/BenchmarkingUtils.java +++ b/examples/src/main/java/io/reacted/examples/benchmarking/BenchmarkingUtils.java @@ -73,7 +73,7 @@ static Runnable backpressureAwareMessageSender(long messageNum, ReActorRef desti static Runnable backpressureAwareMessageSender(long messageNum, ReActorRef destination, Supplier payloadProducer) { - Runnable sender = UnChecked.runnable(() -> { + return UnChecked.runnable(() -> { long baseNanosDelay = 100; long delay = baseNanosDelay; for (int msg = 0; msg < messageNum; msg++) { @@ -90,7 +90,6 @@ static Runnable backpressureAwareMessageSender(long messageNum, ReActorRef desti } } }); - return sender; } static Runnable nonStopMessageSender(long messageNum, ReActorRef destination) { @@ -184,6 +183,7 @@ static Map initStatisticsCollectorProcessor(ReActedGraph sta .build(); } + @SuppressWarnings("unchecked") static List fromRequestsPerIntervalSnapshotsToPrintableOutput(Map, List> payloadByType) { List requestsPerInterval = (List)payloadByType.get(RPISnapshot.class); diff --git a/examples/src/main/java/io/reacted/examples/benchmarking/MessageTsunami.java b/examples/src/main/java/io/reacted/examples/benchmarking/MessageTsunami.java index 4413d619..4bdbb8d9 100644 --- a/examples/src/main/java/io/reacted/examples/benchmarking/MessageTsunami.java +++ b/examples/src/main/java/io/reacted/examples/benchmarking/MessageTsunami.java @@ -13,7 +13,6 @@ import io.reacted.core.mailboxes.BackpressuringMbox; import io.reacted.core.mailboxes.FastUnboundedMbox; import io.reacted.core.mailboxes.PriorityMailbox; -import io.reacted.core.messages.Message; import io.reacted.core.reactors.ReActions; import io.reacted.core.reactors.ReActor; import io.reacted.core.reactorsystem.ReActorContext; @@ -26,7 +25,6 @@ import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.Arrays; -import java.util.Comparator; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.IntStream; @@ -93,25 +91,22 @@ private static class CrunchingWorker implements ReActor { private final ReActorConfig cfg; private final ReActions reActions; private int counted = 0; - private long[] latencies; + private final long[] latencies; private volatile int marker; private CrunchingWorker(String dispatcher, String name, int iterations) { this.cfg = ReActorConfig.newBuilder() - .setMailBoxProvider(ctx -> new PriorityMailbox(new Comparator() { - @Override - public int compare(Message o1, Message o2) { - Class p1 = o1.getPayload().getClass(); - Class p2 = o2.getPayload().getClass(); - if (p1 == p2) { return 0; } - if (p1 == BenchmarkingUtils.DiagnosticRequest.class) { - return -1; - } - if (p2 == BenchmarkingUtils.DiagnosticRequest.class) { - return 1; - } - return 0; + .setMailBoxProvider(ctx -> new PriorityMailbox((o1, o2) -> { + Class p1 = o1.getPayload().getClass(); + Class p2 = o2.getPayload().getClass(); + if (p1 == p2) { return 0; } + if (p1 == BenchmarkingUtils.DiagnosticRequest.class) { + return -1; } + if (p2 == BenchmarkingUtils.DiagnosticRequest.class) { + return 1; + } + return 0; })) .setReActorName(name) .setDispatcherName(dispatcher) diff --git a/examples/src/main/java/io/reacted/examples/benchmarking/ReactionTime.java b/examples/src/main/java/io/reacted/examples/benchmarking/ReactionTime.java index 33a60e43..b312038c 100644 --- a/examples/src/main/java/io/reacted/examples/benchmarking/ReactionTime.java +++ b/examples/src/main/java/io/reacted/examples/benchmarking/ReactionTime.java @@ -11,9 +11,7 @@ import io.reacted.core.config.dispatchers.DispatcherConfig; import io.reacted.core.config.reactors.ReActorConfig; import io.reacted.core.config.reactorsystem.ReActorSystemConfig; -import io.reacted.core.mailboxes.FastBoundedMbox; import io.reacted.core.mailboxes.FastUnboundedMbox; -import io.reacted.core.mailboxes.UnboundedMbox; import io.reacted.core.messages.reactors.ReActorInit; import io.reacted.core.reactors.ReActions; import io.reacted.core.reactors.ReActiveEntity; diff --git a/pom.xml b/pom.xml index 43cc9700..7587d479 100644 --- a/pom.xml +++ b/pom.xml @@ -320,21 +320,6 @@ avro-ipc ${avro.maven.version} - - org.apache.avro - avro - ${avro.maven.version} - - - org.apache.avro - avro-compiler - ${avro.maven.version} - - - org.apache.avro - avro-ipc - ${avro.maven.version} - From 04b8cb0a36d265516ec9cd2bd67a61c53dd9c5b9 Mon Sep 17 00:00:00 2001 From: wireknight Date: Wed, 21 Dec 2022 00:14:58 +0100 Subject: [PATCH 08/16] Reactor Context default name change Datalink Object removed Kafka driver refactored to include avro --- core/src/main/java/io/reacted/core/runtime/Dispatcher.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/io/reacted/core/runtime/Dispatcher.java b/core/src/main/java/io/reacted/core/runtime/Dispatcher.java index c226bd94..98ab13c9 100644 --- a/core/src/main/java/io/reacted/core/runtime/Dispatcher.java +++ b/core/src/main/java/io/reacted/core/runtime/Dispatcher.java @@ -136,8 +136,8 @@ public boolean dispatch(ReActorContext reActor) { claimIdx = selectedRing.tryClaim(MESSAGE_MSG_TYPE, Long.BYTES); if (claimIdx < 1 && (getDispatcherConfig().getDispatcherThreadsNum() < 2 || failures++ > 100)) { if (!slowpathQueue.offer(reActor)) { - LOGGER.error("CRITIC! Unable to activate slowpath mode for {} . Reactor may be stale!", reActor.getSelf() - .getReActorId()); + LOGGER.error("CRITIC! Unable to activate slowpath mode for {} . Reactor may be stale!", + reActor.getSelf().getReActorId()); reActor.releaseScheduling(); return false; } else { From d98f3dad120f8d813ff21f89785b0c111cb83943 Mon Sep 17 00:00:00 2001 From: wireknight Date: Wed, 21 Dec 2022 00:38:34 +0100 Subject: [PATCH 09/16] Reactor Context default name change Datalink Object removed Kafka driver refactored to include avro --- .../drivers/channels/kafka/KafkaDriver.java | 12 ++++-------- .../drivers/channels/kafka/KafkaDriverConfig.java | 14 +++++++++++++- .../reacted/drivers/channels/kafka/KafkaUtils.java | 1 + 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaDriver.java b/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaDriver.java index d902a28b..c70e5816 100644 --- a/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaDriver.java +++ b/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaDriver.java @@ -15,7 +15,6 @@ import io.reacted.core.drivers.system.ReActorSystemDriver; import io.reacted.core.drivers.system.RemotingDriver; import io.reacted.core.messages.AckingPolicy; -import io.reacted.core.messages.Message; import io.reacted.core.messages.reactors.DeliveryStatus; import io.reacted.core.reactorsystem.ReActorContext; import io.reacted.core.reactorsystem.ReActorRef; @@ -34,8 +33,6 @@ import org.apache.kafka.common.errors.InterruptException; import org.apache.kafka.common.serialization.StringDeserializer; import org.apache.kafka.common.serialization.StringSerializer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import javax.annotation.Nullable; import java.io.Serializable; @@ -48,11 +45,6 @@ @NonNullByDefault public class KafkaDriver extends RemotingDriver { - private static final Logger LOGGER = LoggerFactory.getLogger(KafkaDriver.class); - @Nullable - private static final Message NO_VALID_PAYLOAD = null; - @Nullable - private static final byte[] NO_SERIALIZED_PAYLOAD = null; private static final Duration POLL_TIMEOUT = Duration.ofSeconds(1); @Nullable private Consumer kafkaConsumer; @@ -119,6 +111,8 @@ private static Consumer props.put(ConsumerConfig.MAX_POLL_RECORDS_CONFIG, driverConfig.getMaxPollRecords()); props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "false"); props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "latest"); + props.put("schema.registry.url", driverConfig.getAvroSchemaRegistryUrl()); + props.put("schema.registry.url", driverConfig.getAvroSchemaRegistryUrl()); Consumer consumer = new KafkaConsumer<>(props); consumer.subscribe(List.of(driverConfig.getTopic())); return consumer; @@ -129,6 +123,8 @@ public static Producer c props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, driverConfig.getBootstrapEndpoint()); props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName()); props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, KafkaAvroSerializer.class.getName()); + props.put("schema.registry.url", driverConfig.getAvroSchemaRegistryUrl()); + props.put("schema.registry.url", driverConfig.getAvroSchemaRegistryUrl()); return new KafkaProducer<>(props); } diff --git a/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaDriverConfig.java b/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaDriverConfig.java index 54071187..be3d77ec 100644 --- a/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaDriverConfig.java +++ b/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaDriverConfig.java @@ -9,8 +9,8 @@ package io.reacted.drivers.channels.kafka; import io.reacted.core.config.drivers.ChannelDriverConfig; -import io.reacted.patterns.ObjectUtils; import io.reacted.patterns.NonNullByDefault; +import io.reacted.patterns.ObjectUtils; import java.util.Objects; import java.util.Properties; @@ -21,11 +21,14 @@ public class KafkaDriverConfig extends ChannelDriverConfig Date: Wed, 21 Dec 2022 21:29:54 +0100 Subject: [PATCH 10/16] Rollback from avro --- .../io/reacted/core/messages/Message.java | 4 +- .../drivers/channels/kafka/KafkaDriver.java | 90 +++++++++++++------ 2 files changed, 64 insertions(+), 30 deletions(-) diff --git a/core/src/main/java/io/reacted/core/messages/Message.java b/core/src/main/java/io/reacted/core/messages/Message.java index 18715180..f22e1498 100644 --- a/core/src/main/java/io/reacted/core/messages/Message.java +++ b/core/src/main/java/io/reacted/core/messages/Message.java @@ -20,7 +20,7 @@ import java.util.Objects; @NonNullByDefault -public final class Message { +public final class Message implements Serializable { private static final long SENDER_OFFSET = SerializationUtils.getFieldOffset(Message.class, "sender") .orElseSneakyThrow(); private static final long DESTINATION_OFFSET = SerializationUtils.getFieldOffset(Message.class, "destination") @@ -40,7 +40,7 @@ public final class Message { private final AckingPolicy ackingPolicy; private final Serializable payload; - private Message() { + public Message() { this(ReActorRef.NO_REACTOR_REF, ReActorRef.NO_REACTOR_REF, 0L, ReActorSystemId.NO_REACTORSYSTEM_ID, AckingPolicy.NONE, SerializationUtils.NO_PAYLOAD); } diff --git a/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaDriver.java b/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaDriver.java index c70e5816..75871b40 100644 --- a/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaDriver.java +++ b/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaDriver.java @@ -8,13 +8,10 @@ package io.reacted.drivers.channels.kafka; -import io.confluent.kafka.serializers.KafkaAvroDeserializer; -import io.confluent.kafka.serializers.KafkaAvroSerializer; import io.reacted.core.config.ChannelId; -import io.reacted.core.drivers.DriverCtx; -import io.reacted.core.drivers.system.ReActorSystemDriver; import io.reacted.core.drivers.system.RemotingDriver; import io.reacted.core.messages.AckingPolicy; +import io.reacted.core.messages.Message; import io.reacted.core.messages.reactors.DeliveryStatus; import io.reacted.core.reactorsystem.ReActorContext; import io.reacted.core.reactorsystem.ReActorRef; @@ -31,10 +28,18 @@ import org.apache.kafka.clients.producer.ProducerConfig; import org.apache.kafka.clients.producer.ProducerRecord; import org.apache.kafka.common.errors.InterruptException; +import org.apache.kafka.common.serialization.Deserializer; +import org.apache.kafka.common.serialization.Serializer; import org.apache.kafka.common.serialization.StringDeserializer; import org.apache.kafka.common.serialization.StringSerializer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.annotation.Nullable; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.io.Serializable; import java.time.Duration; import java.util.List; @@ -45,12 +50,16 @@ @NonNullByDefault public class KafkaDriver extends RemotingDriver { + private static final Logger LOGGER = LoggerFactory.getLogger(KafkaDriver.class); + @Nullable + private static final Message NO_VALID_PAYLOAD = null; + @Nullable + private static final byte[] NO_SERIALIZED_PAYLOAD = null; private static final Duration POLL_TIMEOUT = Duration.ofSeconds(1); @Nullable - private Consumer kafkaConsumer; + private Consumer kafkaConsumer; @Nullable - private Producer kafkaProducer; - + private Producer kafkaProducer; public KafkaDriver(KafkaDriverConfig config) { super(config); } @@ -91,8 +100,8 @@ DeliveryStatus sendMessage(ReActorRef source, ReActorContext destinationCtx, ReA Objects.requireNonNull(kafkaProducer) .send(new ProducerRecord<>(getDriverConfig().getTopic(), - KafkaUtils.toAvroMessage(source, destination, sequenceNumber, - reActorSystemId, ackingPolicy, payload))) + Message.of(source, destination, sequenceNumber, + reActorSystemId, ackingPolicy, payload))) .get(); return DeliveryStatus.SENT; } catch (Exception sendError) { @@ -102,51 +111,76 @@ DeliveryStatus sendMessage(ReActorRef source, ReActorContext destinationCtx, ReA } } - private static Consumer createConsumer(KafkaDriverConfig driverConfig) { + private static Consumer createConsumer(KafkaDriverConfig driverConfig) { Properties props = new Properties(); props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, driverConfig.getBootstrapEndpoint()); props.put(ConsumerConfig.GROUP_ID_CONFIG, driverConfig.getGroupId()); props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName()); - props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, KafkaAvroDeserializer.class.getName()); + props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, MessageDecoder.class.getName()); props.put(ConsumerConfig.MAX_POLL_RECORDS_CONFIG, driverConfig.getMaxPollRecords()); props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "false"); props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "latest"); props.put("schema.registry.url", driverConfig.getAvroSchemaRegistryUrl()); props.put("schema.registry.url", driverConfig.getAvroSchemaRegistryUrl()); - Consumer consumer = new KafkaConsumer<>(props); + Consumer consumer = new KafkaConsumer<>(props); consumer.subscribe(List.of(driverConfig.getTopic())); return consumer; } - public static Producer createProducer(KafkaDriverConfig driverConfig) { + public static Producer createProducer(KafkaDriverConfig driverConfig) { Properties props = new Properties(); props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, driverConfig.getBootstrapEndpoint()); props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName()); - props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, KafkaAvroSerializer.class.getName()); + props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, MessageEncoder.class.getName()); props.put("schema.registry.url", driverConfig.getAvroSchemaRegistryUrl()); props.put("schema.registry.url", driverConfig.getAvroSchemaRegistryUrl()); return new KafkaProducer<>(props); } - private static void kafkaDriverLoop(Consumer kafkaConsumer, - KafkaDriver thisDriver, ReActorSystem localReActorSystem) { - DriverCtx driverCtx = ReActorSystemDriver.getDriverCtx(); + private static void kafkaDriverLoop(Consumer kafkaConsumer, KafkaDriver thisDriver, + ReActorSystem localReActorSystem) { while(!Thread.currentThread().isInterrupted()) { try { - for(var record : kafkaConsumer.poll(POLL_TIMEOUT)) { - thisDriver.offerMessage(KafkaUtils.fromAvroReActorRef(record.value().getSource(), driverCtx), - KafkaUtils.fromAvroReActorRef(record.value().getDestination(), driverCtx), - record.value().getSequenceNumber(), - KafkaUtils.fromAvroReActorSystemId(record.value().getCreatorReactorSystem()), - KafkaUtils.fromAvroAckingPolicy(record.value().getAckingPolicy()), - KafkaUtils.fromSerializedPayload(record.value().getPayload())); - - } + kafkaConsumer.poll(POLL_TIMEOUT) + .forEach(record -> thisDriver.offerMessage(record.value().getSender(), + record.value().getDestination(), + record.value().getSequenceNumber(), + record.value().getCreatingReactorSystemId(), + record.value().getAckingPolicy(), + record.value().getPayload())); } catch (InterruptException interruptException) { Thread.currentThread().interrupt(); break; - } catch (Exception exceptionWhileOffering) { - localReActorSystem.logError("Unable to fetch messages from kafka", exceptionWhileOffering); + } catch (Exception exchetionWhileOffering) { + localReActorSystem.logError("Unable to fetch messages from kafka", exchetionWhileOffering); + } + } + } + + public static class MessageDecoder implements Deserializer { + @Override + @Nullable + public Message deserialize(String topic, byte[] data) { + try (var inputStream = new ObjectInputStream(new ByteArrayInputStream(data))) { + return (Message)inputStream.readObject(); + } catch (Exception anyMessageDecodeError) { + LOGGER.error("Unable to properly decode message", anyMessageDecodeError); + return NO_VALID_PAYLOAD; + } + } + } + + public static class MessageEncoder implements Serializer { + @Override + @Nullable + public byte[] serialize(String topic, Message data) { + try (var byteArrayOutputStream = new ByteArrayOutputStream(); + var objectOutputStream = new ObjectOutputStream(byteArrayOutputStream)) { + objectOutputStream.writeObject(data); + return byteArrayOutputStream.toByteArray(); + } catch (Exception anyMessageEncodeError) { + LOGGER.error("Unable to encode message", anyMessageEncodeError); + return NO_SERIALIZED_PAYLOAD; } } } From 9b428461f9f442b3f670da3fa3cb0068fc4c0de8 Mon Sep 17 00:00:00 2001 From: wireknight Date: Tue, 27 Dec 2022 09:20:59 +0100 Subject: [PATCH 11/16] Work in progress on the serialization system change --- .../io/reacted/core/config/ChannelId.java | 24 ++- .../local/DirectCommunicationDriver.java | 4 +- .../DirectCommunicationLoggerDriver.java | 4 +- ...ctCommunicationSimplifiedLoggerDriver.java | 4 +- .../core/drivers/system/LocalDriver.java | 22 +-- .../core/drivers/system/LoopbackDriver.java | 27 ++-- .../core/drivers/system/NullDriver.java | 20 +-- .../core/drivers/system/NullLocalDriver.java | 6 +- .../drivers/system/ReActorSystemDriver.java | 38 ++--- .../core/drivers/system/RemotingDriver.java | 29 ++-- .../core/mailboxes/BackpressuringMbox.java | 24 +-- .../core/mailboxes/TypeCoalescingMailbox.java | 8 +- .../io/reacted/core/messages/Message.java | 53 ++++--- .../core/messages/SerializationUtils.java | 16 +- .../core/messages/reactors/DeadMessage.java | 24 ++- .../reactors/DeliveryStatusUpdate.java | 5 +- .../reactors/EventExecutionAttempt.java | 25 ++-- .../core/messages/reactors/LogMessage.java | 14 +- .../core/messages/reactors/ReActedError.java | 2 +- .../core/messages/reactors/ReActedInfo.java | 2 +- .../core/messages/reactors/ReActorInit.java | 18 +-- .../core/messages/reactors/ReActorStop.java | 17 +-- .../reactors/SystemMonitorReport.java | 4 +- .../DuplicatedPublicationError.java | 4 +- .../FilterServiceDiscoveryRequest.java | 4 +- ...torSystemChannelIdCancellationRequest.java | 4 +- ...eActorSystemChannelIdPublicationError.java | 4 +- ...ctorSystemChannelIdPublicationRequest.java | 7 +- .../RegistryConnectionLost.java | 4 +- .../RegistryDriverInitComplete.java | 5 +- .../serviceregistry/RegistryGateRemoved.java | 4 +- .../serviceregistry/RegistryGateUpserted.java | 4 +- .../RegistryServicePublicationFailed.java | 4 +- .../ServiceCancellationRequest.java | 4 +- .../ServicePublicationRequest.java | 4 +- .../ServicePublicationRequestError.java | 4 +- .../ServiceRegistryNotAvailable.java | 4 +- ...ronizationWithServiceRegistryComplete.java | 5 +- ...chronizationWithServiceRegistryFailed.java | 4 +- ...hronizationWithServiceRegistryRequest.java | 5 +- .../core/messages/services/FilterItem.java | 4 +- .../services/ServiceDiscoveryReply.java | 4 +- .../services/ServiceDiscoveryRequest.java | 5 +- .../ServiceDiscoverySearchFilter.java | 4 +- .../io/reacted/core/reactors/ReActions.java | 24 +-- .../io/reacted/core/reactors/ReActorId.java | 33 +++-- .../core/reactors/systemreactors/Ask.java | 10 +- .../reactors/systemreactors/DeadLetter.java | 7 +- .../reactors/systemreactors/RemotingRoot.java | 4 +- .../reactorsystem/NullReActorSystemRef.java | 6 +- .../core/reactorsystem/ReActorContext.java | 23 +-- .../core/reactorsystem/ReActorCtxConfig.java | 10 +- .../core/reactorsystem/ReActorRef.java | 71 +++++---- .../core/reactorsystem/ReActorSystem.java | 36 ++--- .../core/reactorsystem/ReActorSystemId.java | 32 ++-- .../core/reactorsystem/ReActorSystemRef.java | 47 +++--- .../core/serialization/Deserializer.java | 23 +++ .../core/serialization/ReActedMessage.java | 138 ++++++++++++++++++ .../core/serialization/Serializer.java | 32 ++++ .../core/services/LoadBalancingPolicies.java | 10 +- .../core/services/LoadBalancingPolicy.java | 5 +- .../io/reacted/core/services/Service.java | 12 +- .../SubscriptionsManager.java | 13 +- .../typedsubscriptions/TypedSubscription.java | 11 +- .../TypedSubscriptionsManager.java | 14 +- .../io/reacted/core/utils/ReActedUtils.java | 4 +- .../java/io/reacted/core/CoreConstants.java | 4 +- .../core/drivers/system/LocalDriverTest.java | 7 +- .../drivers/system/LoopbackDriverTest.java | 7 +- .../core/mailboxes/PriorityMailboxTest.java | 16 +- .../core/mailboxes/UnboundedMboxTest.java | 4 +- .../systemreactors/DeadLetterTest.java | 9 +- .../systemreactors/MagicTestReActor.java | 10 +- .../core/reactorsystem/ReActorSystemTest.java | 6 +- .../chroniclequeue/CQLocalDriver.java | 26 ++-- .../chroniclequeue/CQRemoteDriver.java | 16 +- .../drivers/channels/grpc/GrpcDriver.java | 9 +- .../drivers/channels/kafka/KafkaDriver.java | 4 +- .../drivers/channels/kafka/KafkaUtils.java | 10 +- .../channels/replay/ReplayLocalDriver.java | 23 +-- .../zookeeper/ZooKeeperRootPathsCreated.java | 4 +- .../benchmarking/BenchmarkingUtils.java | 58 +++++--- .../examples/benchmarking/MessageTsunami.java | 12 +- .../examples/benchmarking/ReactionTime.java | 16 +- .../examples/benchmarking/SingleChannel.java | 12 +- .../communication/ask/TimeRequest.java | 4 +- .../tell/ping/PreparationRequest.java | 4 +- .../communication/tell/pingpong/Ping.java | 4 +- .../communication/tell/pingpong/Pong.java | 4 +- .../examples/httpserver/ReactiveServer.java | 15 +- .../examples/quickstart/GreeterService.java | 4 +- .../remoting/services/TimeRequest.java | 4 +- .../examples/services/TimeRequest.java | 4 +- .../spawning/ReActorRelationsApp.java | 10 +- .../RemoteBroadcastingApp.java | 4 +- .../examples/typedsubscription/Update.java | 4 +- .../examples/webappbackend/ServerGate.java | 4 +- .../webappbackend/db/DatabaseService.java | 4 +- .../webappbackend/db/StorageMessages.java | 31 +++- .../examples/webappbackend/handlers/Get.java | 4 +- .../examples/webappbackend/handlers/Post.java | 10 +- .../java/io/reacted/flow/GraphController.java | 9 +- .../java/io/reacted/flow/SourceStream.java | 19 +-- .../reacted/flow/operators/FlowOperator.java | 32 ++-- .../flow/operators/FlowOperatorConfig.java | 22 +-- .../flow/operators/map/MapOperator.java | 10 +- .../flow/operators/map/MapOperatorConfig.java | 11 +- .../messages/OperatorInitComplete.java | 7 +- .../operators/reduce/ReducingOperator.java | 29 ++-- .../reduce/ReducingOperatorConfig.java | 33 +++-- .../operators/service/ServiceOperator.java | 12 +- .../service/ServiceOperatorConfig.java | 31 ++-- .../flow/operators/zip/ZipOperatorConfig.java | 16 +- .../src/test/java/BenchmarkingUtils.java | 22 +-- .../reacted/streams/BackpressureManager.java | 8 +- .../streams/ReactedSubmissionPublisher.java | 25 ++-- .../streams/messages/PublisherComplete.java | 5 +- .../streams/messages/PublisherInterrupt.java | 5 +- .../streams/messages/PublisherShutdown.java | 4 +- .../streams/messages/SubscriberError.java | 5 +- .../streams/messages/SubscriptionReply.java | 5 +- .../streams/messages/SubscriptionRequest.java | 5 +- .../messages/UnsubscriptionRequest.java | 5 +- .../streams/DistributedPublisherTest.java | 32 ++-- .../io/reacted/streams/PublisherTCKTest.java | 20 +-- 125 files changed, 1022 insertions(+), 763 deletions(-) create mode 100644 core/src/main/java/io/reacted/core/serialization/Deserializer.java create mode 100644 core/src/main/java/io/reacted/core/serialization/ReActedMessage.java create mode 100644 core/src/main/java/io/reacted/core/serialization/Serializer.java diff --git a/core/src/main/java/io/reacted/core/config/ChannelId.java b/core/src/main/java/io/reacted/core/config/ChannelId.java index 68123c07..181ba5ee 100644 --- a/core/src/main/java/io/reacted/core/config/ChannelId.java +++ b/core/src/main/java/io/reacted/core/config/ChannelId.java @@ -9,14 +9,13 @@ package io.reacted.core.config; import io.reacted.core.messages.SerializationUtils; +import io.reacted.core.serialization.Deserializer; +import io.reacted.core.serialization.ReActedMessage; +import io.reacted.core.serialization.Serializer; import io.reacted.patterns.NonNullByDefault; import io.reacted.patterns.Try; import javax.annotation.concurrent.Immutable; -import java.io.Externalizable; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; import java.util.Arrays; import java.util.Map; import java.util.Objects; @@ -27,7 +26,7 @@ @Immutable @NonNullByDefault -public class ChannelId implements Externalizable { +public class ChannelId implements ReActedMessage { public static final ChannelId NO_CHANNEL_ID = ChannelType.NULL_CHANNEL_TYPE.forChannelName(""); public static final ChannelId INVALID_CHANNEL_ID = ChannelType.INVALID_CHANNEL_TYPE .forChannelName("INVALID CHANNEL NAME"); @@ -57,20 +56,17 @@ private ChannelId(ChannelType channelType, String channelName) { } @Override - public void writeExternal(ObjectOutput out) throws IOException { - out.writeInt(channelType.ordinal()); - //out.writeObject(channelType); - out.writeObject(channelName); - //out.writeInt(hashCode); + public void encode(Serializer serializer) { + serializer.put(channelType.ordinal()); + serializer.put(channelName); } @Override - public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { - setChannelType(ChannelType.forOrdinal(in.readInt())); - setChannelName((String)in.readObject()); + public void decode(Deserializer deserializer) { + setChannelType(ChannelType.forOrdinal(deserializer.getInt())); + setChannelName(deserializer.getString()); setHashCode(Objects.hash(getChannelType(), getChannelName())); } - public static Optional fromToString(String inputString) { return Try.of(() -> inputString.split(SEPARATOR)) .map(split -> new ChannelId(ChannelType.valueOf(split[0]), split[1])) diff --git a/core/src/main/java/io/reacted/core/drivers/local/DirectCommunicationDriver.java b/core/src/main/java/io/reacted/core/drivers/local/DirectCommunicationDriver.java index d6a9d25b..6c2cd6f4 100644 --- a/core/src/main/java/io/reacted/core/drivers/local/DirectCommunicationDriver.java +++ b/core/src/main/java/io/reacted/core/drivers/local/DirectCommunicationDriver.java @@ -18,11 +18,11 @@ import io.reacted.core.reactorsystem.ReActorRef; import io.reacted.core.reactorsystem.ReActorSystem; import io.reacted.core.reactorsystem.ReActorSystemId; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; import io.reacted.patterns.Try; import io.reacted.patterns.UnChecked; -import java.io.Serializable; import java.util.Properties; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; @@ -63,7 +63,7 @@ public Properties getChannelProperties() { } @Override - public DeliveryStatus + public DeliveryStatus sendMessage(ReActorRef source, ReActorContext destinationCtx, ReActorRef destination, long seqNum, ReActorSystemId reActorSystemId, AckingPolicy ackingPolicy, PayloadT message) { return destinationCtx.isStop() diff --git a/core/src/main/java/io/reacted/core/drivers/local/DirectCommunicationLoggerDriver.java b/core/src/main/java/io/reacted/core/drivers/local/DirectCommunicationLoggerDriver.java index 4d56b6b9..d3044517 100644 --- a/core/src/main/java/io/reacted/core/drivers/local/DirectCommunicationLoggerDriver.java +++ b/core/src/main/java/io/reacted/core/drivers/local/DirectCommunicationLoggerDriver.java @@ -17,6 +17,7 @@ import io.reacted.core.reactorsystem.ReActorRef; import io.reacted.core.reactorsystem.ReActorSystem; import io.reacted.core.reactorsystem.ReActorSystemId; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; import io.reacted.patterns.Try; import io.reacted.patterns.UnChecked; @@ -24,7 +25,6 @@ import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; -import java.io.Serializable; import java.io.UncheckedIOException; import java.util.Properties; import java.util.concurrent.CompletableFuture; @@ -76,7 +76,7 @@ public CompletionStage> cleanDriverLoop() { public Properties getChannelProperties() { return new Properties(); } @Override - public DeliveryStatus + public DeliveryStatus sendMessage(ReActorRef source, ReActorContext destinationCtx, ReActorRef destination, long seqNum, ReActorSystemId reActorSystemId, AckingPolicy ackingPolicy, PayloadT message) { logFile.println(message); diff --git a/core/src/main/java/io/reacted/core/drivers/local/DirectCommunicationSimplifiedLoggerDriver.java b/core/src/main/java/io/reacted/core/drivers/local/DirectCommunicationSimplifiedLoggerDriver.java index 1f1ea223..2e1aa183 100644 --- a/core/src/main/java/io/reacted/core/drivers/local/DirectCommunicationSimplifiedLoggerDriver.java +++ b/core/src/main/java/io/reacted/core/drivers/local/DirectCommunicationSimplifiedLoggerDriver.java @@ -17,12 +17,12 @@ import io.reacted.core.reactorsystem.ReActorRef; import io.reacted.core.reactorsystem.ReActorSystem; import io.reacted.core.reactorsystem.ReActorSystemId; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; import io.reacted.patterns.Try; import io.reacted.patterns.UnChecked; import java.io.PrintWriter; -import java.io.Serializable; import java.io.UncheckedIOException; import java.time.Instant; import java.util.Properties; @@ -79,7 +79,7 @@ public CompletionStage> cleanDriverLoop() { public Properties getChannelProperties() { return new Properties(); } @Override - public DeliveryStatus + public DeliveryStatus sendMessage(ReActorRef src, ReActorContext destinationCtx, ReActorRef destination, long seqNum, ReActorSystemId reActorSystemId, AckingPolicy ackingPolicy, PayloadT message) { synchronized (logFile) { diff --git a/core/src/main/java/io/reacted/core/drivers/system/LocalDriver.java b/core/src/main/java/io/reacted/core/drivers/system/LocalDriver.java index 0f48a2cb..12f95708 100644 --- a/core/src/main/java/io/reacted/core/drivers/system/LocalDriver.java +++ b/core/src/main/java/io/reacted/core/drivers/system/LocalDriver.java @@ -17,11 +17,11 @@ import io.reacted.core.reactorsystem.ReActorContext; import io.reacted.core.reactorsystem.ReActorRef; import io.reacted.core.reactorsystem.ReActorSystemId; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; import io.reacted.patterns.UnChecked.TriConsumer; import javax.annotation.Nullable; -import java.io.Serializable; import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; @@ -34,40 +34,40 @@ protected LocalDriver(ConfigT config) { } @Override - public final + public final DeliveryStatus publish(ReActorRef src, ReActorRef dst, PayloadT message) { throw new UnsupportedOperationException(); } @Override - public final DeliveryStatus publish(ReActorRef src, ReActorRef dst, - @Nullable TriConsumer propagateToSubscribers, PayloadT message) { + public final DeliveryStatus publish(ReActorRef src, ReActorRef dst, + @Nullable TriConsumer propagateToSubscribers, PayloadT message) { throw new UnsupportedOperationException(); } @Override - public DeliveryStatus tell(ReActorRef src, ReActorRef dst, PayloadT message) { + public DeliveryStatus tell(ReActorRef src, ReActorRef dst, PayloadT message) { throw new UnsupportedOperationException(); } @Override - public CompletionStage apublish(ReActorRef src, ReActorRef dst, AckingPolicy ackingPolicy, PayloadT message) { + public CompletionStage apublish(ReActorRef src, ReActorRef dst, AckingPolicy ackingPolicy, PayloadT message) { return CompletableFuture.failedStage(new UnsupportedOperationException()); } @Override - public CompletionStage apublish(ReActorRef src, ReActorRef dst, AckingPolicy ackingPolicy, - TriConsumer propagateToSubscribers, PayloadT message) { + public CompletionStage apublish(ReActorRef src, ReActorRef dst, AckingPolicy ackingPolicy, + TriConsumer propagateToSubscribers, PayloadT message) { return CompletableFuture.failedStage(new UnsupportedOperationException()); } @Override - public CompletionStage atell(ReActorRef src, ReActorRef dst, AckingPolicy ackingPolicy, PayloadT message) { + public CompletionStage atell(ReActorRef src, ReActorRef dst, AckingPolicy ackingPolicy, PayloadT message) { return CompletableFuture.failedStage(new UnsupportedOperationException()); } @Override - protected final void + protected final void offerMessage(ReActorRef source, ReActorRef destination, long sequenceNumber, ReActorSystemId fromReActorSystemId, AckingPolicy ackingPolicy, PayloadT payload) { ReActorId destinationId = destination.getReActorId(); @@ -91,7 +91,7 @@ public CompletionStage atell(ReA } } } - protected static DeliveryStatus + protected static DeliveryStatus syncForwardMessageToLocalActor(ReActorRef source, ReActorContext destinationCtx, ReActorRef destination, long sequenceNumber, ReActorSystemId fromReActorSystemId, AckingPolicy ackingPolicy, PayloadT payload) { diff --git a/core/src/main/java/io/reacted/core/drivers/system/LoopbackDriver.java b/core/src/main/java/io/reacted/core/drivers/system/LoopbackDriver.java index 8e9795d4..e319b6b7 100644 --- a/core/src/main/java/io/reacted/core/drivers/system/LoopbackDriver.java +++ b/core/src/main/java/io/reacted/core/drivers/system/LoopbackDriver.java @@ -17,13 +17,13 @@ import io.reacted.core.reactorsystem.ReActorRef; import io.reacted.core.reactorsystem.ReActorSystem; import io.reacted.core.reactorsystem.ReActorSystemId; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; import io.reacted.patterns.Try; import io.reacted.patterns.UnChecked; import io.reacted.patterns.UnChecked.TriConsumer; import javax.annotation.Nullable; -import java.io.Serializable; import java.util.List; import java.util.Objects; import java.util.Properties; @@ -33,7 +33,7 @@ @NonNullByDefault public class LoopbackDriver> extends ReActorSystemDriver { private static final int SUBSCRIBERS_THRESHOLD_TO_USE_ASYNC_PROPAGATION = 6; - private final TriConsumer propagateToSubscribers = this::propagateMessage; + private final TriConsumer propagateToSubscribers = this::propagateMessage; private final LocalDriver localDriver; private final ReActorSystem localReActorSystem; private final ExecutorService fanOutPool; @@ -49,12 +49,13 @@ public LoopbackDriver(ReActorSystem reActorSystem, LocalDriver localDri } @Override - public DeliveryStatus publish(ReActorRef src, ReActorRef dst, PayloadT payload) { + public DeliveryStatus publish(ReActorRef src, ReActorRef dst, PayloadT payload) { return publish(src, dst, propagateToSubscribers, payload); } @Override - public DeliveryStatus publish(ReActorRef source, ReActorRef destination, - @Nullable TriConsumer toSubscribers, PayloadT payload){ + public DeliveryStatus publish(ReActorRef source, ReActorRef destination, + @Nullable TriConsumer toSubscribers, + PayloadT payload){ ReActorContext dstCtx = localReActorSystem.getReActorCtx(destination.getReActorId()); DeliveryStatus tellResult; long seqNum = localReActorSystem.getNewSeqNum(); @@ -80,23 +81,23 @@ public DeliveryStatus publish(ReActorRef source, } @Override - public DeliveryStatus tell(ReActorRef src, ReActorRef dst, PayloadT payload) { + public DeliveryStatus tell(ReActorRef src, ReActorRef dst, PayloadT payload) { return publish(src, dst, DO_NOT_PROPAGATE, payload); } @Override - public CompletionStage apublish(ReActorRef src, ReActorRef dst, AckingPolicy ackingPolicy, PayloadT payload) { + public CompletionStage apublish(ReActorRef src, ReActorRef dst, AckingPolicy ackingPolicy, PayloadT payload) { return apublish(src, dst, ackingPolicy, propagateToSubscribers, payload); } @Override - public CompletionStage atell(ReActorRef src, ReActorRef dst, AckingPolicy ackingPolicy, PayloadT payload) { + public CompletionStage atell(ReActorRef src, ReActorRef dst, AckingPolicy ackingPolicy, PayloadT payload) { return apublish(src, dst, ackingPolicy, DO_NOT_PROPAGATE, payload); } @Override - public CompletionStage apublish(ReActorRef source, ReActorRef destnation, AckingPolicy ackingPolicy, - TriConsumer toSubscribers, PayloadT payload) { + public CompletionStage apublish(ReActorRef source, ReActorRef destnation, AckingPolicy ackingPolicy, + TriConsumer toSubscribers, PayloadT payload) { ReActorContext destinationContext = localReActorSystem.getReActorCtx(destnation.getReActorId()); CompletionStage tellResult; long seqNum = localReActorSystem.getNewSeqNum(); @@ -157,7 +158,7 @@ public UnChecked.CheckedRunnable getDriverLoop() { public final ChannelId getChannelId() { return localDriver.getChannelId(); } @Override - public DeliveryStatus + public DeliveryStatus sendMessage(ReActorRef src, ReActorContext destinationCtx, ReActorRef destination, long seqNum, ReActorSystemId reActorSystemId, AckingPolicy ackingPolicy, PayloadT message) { throw new UnsupportedOperationException(); @@ -165,7 +166,7 @@ public UnChecked.CheckedRunnable getDriverLoop() { @Override public Properties getChannelProperties() { return localDriver.getChannelProperties(); } - private void propagateMessage(ReActorId originalDst, Serializable msgPayload, ReActorRef src) { + private void propagateMessage(ReActorId originalDst, ReActedMessage msgPayload, ReActorRef src) { var subscribers = localReActorSystem.getTypedSubscriptionsManager() .getLocalSubscribers(msgPayload.getClass()); if (!subscribers.isEmpty()) { @@ -180,7 +181,7 @@ private void propagateMessage(ReActorId originalDst, Serializable msgPayload, Re private void propagateToSubscribers(LocalDriver localDriver, List subscribers, ReActorId originalDestination, ReActorSystem localReActorSystem, - ReActorRef source, Serializable payload) { + ReActorRef source, ReActedMessage payload) { for (ReActorContext ctx : subscribers) { if (!ctx.getSelf().getReActorId().equals(originalDestination)) { localDriver.sendMessage(source, ctx, ctx.getSelf(), localReActorSystem.getNewSeqNum(), diff --git a/core/src/main/java/io/reacted/core/drivers/system/NullDriver.java b/core/src/main/java/io/reacted/core/drivers/system/NullDriver.java index 258b39f7..43f47a60 100644 --- a/core/src/main/java/io/reacted/core/drivers/system/NullDriver.java +++ b/core/src/main/java/io/reacted/core/drivers/system/NullDriver.java @@ -19,13 +19,13 @@ import io.reacted.core.reactorsystem.ReActorRef; import io.reacted.core.reactorsystem.ReActorSystem; import io.reacted.core.reactorsystem.ReActorSystemId; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; import io.reacted.patterns.Try; import io.reacted.patterns.UnChecked; import io.reacted.patterns.UnChecked.TriConsumer; import javax.annotation.Nullable; -import java.io.Serializable; import java.util.Objects; import java.util.Properties; import java.util.concurrent.CompletableFuture; @@ -75,19 +75,19 @@ public UnChecked.CheckedRunnable getDriverLoop() { } @Override - public DeliveryStatus publish(ReActorRef src, ReActorRef dst, + public DeliveryStatus publish(ReActorRef src, ReActorRef dst, PayloadT message) { return DeliveryStatus.NOT_DELIVERED; } @Override - public DeliveryStatus publish(ReActorRef src, ReActorRef dst, - @Nullable TriConsumer propagateToSubscribers, PayloadT message) { + public DeliveryStatus publish(ReActorRef src, ReActorRef dst, + @Nullable TriConsumer propagateToSubscribers, PayloadT message) { return DeliveryStatus.NOT_DELIVERED; } @Override - public DeliveryStatus tell(ReActorRef src, ReActorRef dst, PayloadT message) { + public DeliveryStatus tell(ReActorRef src, ReActorRef dst, PayloadT message) { if (message instanceof Recyclable recyclable) { recyclable.revalidate(); } @@ -95,26 +95,26 @@ public DeliveryStatus tell(ReActorRef src, ReAct } @Override - public + public CompletionStage apublish(ReActorRef src, ReActorRef dst, AckingPolicy ackingPolicy, PayloadT message) { return CompletableFuture.failedStage(new NoRouteToReActorSystem()); } @Override - public CompletionStage apublish(ReActorRef src, ReActorRef dst, AckingPolicy ackingPolicy, - TriConsumer propagateToSubscribers, + public CompletionStage apublish(ReActorRef src, ReActorRef dst, AckingPolicy ackingPolicy, + TriConsumer propagateToSubscribers, PayloadT message) { return CompletableFuture.failedStage(new NoRouteToReActorSystem()); } @Override - public CompletionStage atell(ReActorRef src, ReActorRef dst, AckingPolicy ackingPolicy, PayloadT message) { + public CompletionStage atell(ReActorRef src, ReActorRef dst, AckingPolicy ackingPolicy, PayloadT message) { return CompletableFuture.failedStage(new NoRouteToReActorSystem()); } @Override - public DeliveryStatus + public DeliveryStatus sendMessage(ReActorRef source, ReActorContext destinationCtx, ReActorRef destination, long seqNum, ReActorSystemId reActorSystemId, AckingPolicy ackingPolicy, PayloadT message) { diff --git a/core/src/main/java/io/reacted/core/drivers/system/NullLocalDriver.java b/core/src/main/java/io/reacted/core/drivers/system/NullLocalDriver.java index ac07a355..fd13f895 100644 --- a/core/src/main/java/io/reacted/core/drivers/system/NullLocalDriver.java +++ b/core/src/main/java/io/reacted/core/drivers/system/NullLocalDriver.java @@ -16,11 +16,11 @@ import io.reacted.core.reactorsystem.ReActorRef; import io.reacted.core.reactorsystem.ReActorSystem; import io.reacted.core.reactorsystem.ReActorSystemId; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; import io.reacted.patterns.Try; import io.reacted.patterns.UnChecked; -import java.io.Serializable; import java.util.Objects; import java.util.Properties; import java.util.concurrent.CompletableFuture; @@ -68,11 +68,11 @@ public UnChecked.CheckedRunnable getDriverLoop() { @Override - public DeliveryStatus tell(ReActorRef src, ReActorRef dst, PayloadT message) { + public DeliveryStatus tell(ReActorRef src, ReActorRef dst, PayloadT message) { return DeliveryStatus.NOT_DELIVERED; } @Override - public + public DeliveryStatus sendMessage(ReActorRef source, ReActorContext destinationCtx, ReActorRef destination, long seqNum, ReActorSystemId reActorSystemId, AckingPolicy ackingPolicy, PayloadT message) { diff --git a/core/src/main/java/io/reacted/core/drivers/system/ReActorSystemDriver.java b/core/src/main/java/io/reacted/core/drivers/system/ReActorSystemDriver.java index fd740505..f1f3b205 100644 --- a/core/src/main/java/io/reacted/core/drivers/system/ReActorSystemDriver.java +++ b/core/src/main/java/io/reacted/core/drivers/system/ReActorSystemDriver.java @@ -26,6 +26,7 @@ import io.reacted.core.reactorsystem.ReActorRef; import io.reacted.core.reactorsystem.ReActorSystem; import io.reacted.core.reactorsystem.ReActorSystemId; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; import io.reacted.patterns.Try; import io.reacted.patterns.UnChecked; @@ -35,7 +36,6 @@ import org.slf4j.LoggerFactory; import javax.annotation.Nullable; -import java.io.Serializable; import java.util.Arrays; import java.util.Objects; import java.util.Properties; @@ -51,7 +51,7 @@ @NonNullByDefault public abstract class ReActorSystemDriver> { @Nullable - public static final TriConsumer DO_NOT_PROPAGATE = null; + public static final TriConsumer DO_NOT_PROPAGATE = null; public static final ThreadLocal REACTOR_SYSTEM_CTX = new InheritableThreadLocal<>(); protected static final Logger LOGGER = LoggerFactory.getLogger(ReActorSystemDriver.class); @SuppressWarnings("unchecked") @@ -88,10 +88,10 @@ protected ReActorSystemDriver(ConfigT config) { /** * @throws io.reacted.core.exceptions.DeliveryException when a driver specific delivery error occurs */ - public abstract DeliveryStatus + public abstract DeliveryStatus sendMessage(ReActorRef src, ReActorContext destinationCtx, ReActorRef destination, long seqNum, ReActorSystemId reActorSystemId, AckingPolicy ackingPolicy, PayloadT message); - public CompletionStage + public CompletionStage sendAsyncMessage(ReActorRef src, ReActorContext destinationCtx, ReActorRef destination, long seqNum, ReActorSystemId reActorSystemId, AckingPolicy ackingPolicy, PayloadT message) { @@ -106,12 +106,12 @@ protected ReActorSystemDriver(ConfigT config) { * @param src source of the message * @param dst destination of the message * @param message payload - * @param any Serializable object + * @param any ReActedMessage object * @return A {@link DeliveryStatus} representing the outcome of the operation. Different drivers * may offer different guarantees regarding the returned {@link DeliveryStatus}. The common * baseline for this method is providing delivery guarantee to the local driver bus */ - public abstract DeliveryStatus publish(ReActorRef src, ReActorRef dst, PayloadT message); + public abstract DeliveryStatus publish(ReActorRef src, ReActorRef dst, PayloadT message); /** * Sends a message through this driver @@ -122,13 +122,13 @@ protected ReActorSystemDriver(ConfigT config) { * for propagating that message to its type-subscribers. * @see io.reacted.core.typedsubscriptions.TypedSubscription * @param message payload - * @param any Serializable object + * @param any ReActedMessage object * @return A {@link DeliveryStatus} representing the outcome of the operation. Different drivers * may offer different guarantees regarding the returned {@link DeliveryStatus}. The common * baseline for this method is providing delivery guarantee to the local driver bus */ - public abstract DeliveryStatus publish(ReActorRef src, ReActorRef dst, - @Nullable TriConsumer propagateToSubscribers, PayloadT message); + public abstract DeliveryStatus publish(ReActorRef src, ReActorRef dst, + @Nullable TriConsumer propagateToSubscribers, PayloadT message); /** * Sends a message through this driver. Type subscribers will not be notified * @see io.reacted.core.typedsubscriptions.TypedSubscription @@ -136,12 +136,12 @@ public abstract DeliveryStatus publish(ReActorR * @param src source of the message * @param dst destination of the message * @param message payload - * @param any Serializable object + * @param any ReActedMessage object * @return A {@link DeliveryStatus} representing the outcome of the operation. Different drivers * may offer different guarantees regarding the returned {@link DeliveryStatus}. The common * baseline for this method is providing delivery guarantee to the local driver bus */ - public abstract DeliveryStatus tell(ReActorRef src, ReActorRef dst, PayloadT message); + public abstract DeliveryStatus tell(ReActorRef src, ReActorRef dst, PayloadT message); /** * Sends a message through this driver requiring an ack as a confirmation of the delivery into the target reactor's * mailbox. Type subscribers will not be notified. @@ -151,11 +151,11 @@ public abstract DeliveryStatus publish(ReActorR * @param dst destination of the message * @param ackingPolicy the {@link AckingPolicy} that should be used for managing the ack control for this message * @param message payload - * @param any Serializable object + * @param any ReActedMessage object * @return A {@link CompletionStage} that is going to be completed when an ack from the destination reactor system * is received containing the outcome of the delivery of the message into the target actor mailbox */ - public abstract CompletionStage atell(ReActorRef src, ReActorRef dst, AckingPolicy ackingPolicy, PayloadT message); + public abstract CompletionStage atell(ReActorRef src, ReActorRef dst, AckingPolicy ackingPolicy, PayloadT message); /** * Sends a message through this driver requiring an ack as a confirmation of the delivery into the target reactor's * mailbox. @@ -164,11 +164,11 @@ public abstract DeliveryStatus publish(ReActorR * @param dst destination of the message * @param ackingPolicy the {@link AckingPolicy} that should be used for managing the ack control for this message * @param message payload - * @param any Serializable object + * @param any ReActedMessage object * @return A {@link CompletionStage} that is going to be completed when an ack from the destination reactor system * is received containing the outcome of the delivery of the message into the target actor mailbox */ - public abstract CompletionStage apublish(ReActorRef src, ReActorRef dst, AckingPolicy ackingPolicy, PayloadT message); + public abstract CompletionStage apublish(ReActorRef src, ReActorRef dst, AckingPolicy ackingPolicy, PayloadT message); /** * Sends a message through this driver requiring an ack as a confirmation of the delivery into the target reactor's * mailbox. @@ -180,14 +180,14 @@ public abstract DeliveryStatus publish(ReActorR * for propagating that message to its type-subscribers. * @see io.reacted.core.typedsubscriptions.TypedSubscription * @param message payload - * @param any Serializable object + * @param any ReActedMessage object * @return A {@link CompletionStage} that is going to be completed when an ack from the destination reactor system * is received containing the outcome of the delivery of the message into the target actor mailbox */ - public abstract CompletionStage apublish(ReActorRef src, ReActorRef dst, AckingPolicy ackingPolicy, - TriConsumer propagateToSubscribers, PayloadT message); + public abstract CompletionStage apublish(ReActorRef src, ReActorRef dst, AckingPolicy ackingPolicy, + TriConsumer propagateToSubscribers, PayloadT message); - protected void offerMessage(ReActorRef source, ReActorRef destination, + protected void offerMessage(ReActorRef source, ReActorRef destination, long sequenceNumber, ReActorSystemId fromReActorSystemId, AckingPolicy ackingPolicy, diff --git a/core/src/main/java/io/reacted/core/drivers/system/RemotingDriver.java b/core/src/main/java/io/reacted/core/drivers/system/RemotingDriver.java index 43036383..196b7a5f 100644 --- a/core/src/main/java/io/reacted/core/drivers/system/RemotingDriver.java +++ b/core/src/main/java/io/reacted/core/drivers/system/RemotingDriver.java @@ -18,13 +18,14 @@ import io.reacted.core.reactorsystem.ReActorSystem; import io.reacted.core.reactorsystem.ReActorSystemId; import io.reacted.core.reactorsystem.ReActorSystemRef; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; import io.reacted.patterns.UnChecked.TriConsumer; -import java.io.Serializable; + +import javax.annotation.Nullable; import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; -import javax.annotation.Nullable; @NonNullByDefault public abstract class RemotingDriver> @@ -32,22 +33,22 @@ public abstract class RemotingDriver + public final DeliveryStatus publish(ReActorRef src, ReActorRef dst, PayloadT message) { //While sending towards a remote peer, propagation towards subscribers never takes place return publish(src, dst, DO_NOT_PROPAGATE, message); } @Override - public final DeliveryStatus publish(ReActorRef source, ReActorRef destination, - @Nullable TriConsumer propagateToSubscribers, PayloadT message) { + public final DeliveryStatus publish(ReActorRef source, ReActorRef destination, + @Nullable TriConsumer propagateToSubscribers, PayloadT message) { long nextSeqNum = getLocalReActorSystem().getNewSeqNum(); return sendMessage(source, ReActorContext.NO_REACTOR_CTX, destination, nextSeqNum, getLocalReActorSystem().getLocalReActorSystemId(), AckingPolicy.NONE, message); } @Override - public DeliveryStatus tell(ReActorRef src, ReActorRef dst, PayloadT message) { + public DeliveryStatus tell(ReActorRef src, ReActorRef dst, PayloadT message) { return publish(src, dst, DO_NOT_PROPAGATE, message); } @@ -62,7 +63,7 @@ public DeliveryStatus tell(ReActorRef src, ReAct * has been delivered into the target's mailbox and has been ACK-ed accordingly with the specified policy */ @Override - public + public CompletionStage apublish(ReActorRef source, ReActorRef destination, AckingPolicy ackingPolicy, PayloadT message) { long nextSeqNum = getLocalReActorSystem().getNewSeqNum(); @@ -83,14 +84,14 @@ CompletionStage apublish(ReActorRef source, ReActorRef destinati } @Override - public final CompletionStage apublish(ReActorRef src, ReActorRef dst, AckingPolicy ackingPolicy, - TriConsumer propagateToSubscribers, PayloadT message) { + public final CompletionStage apublish(ReActorRef src, ReActorRef dst, AckingPolicy ackingPolicy, + TriConsumer propagateToSubscribers, PayloadT message) { //While sending towards a remote peer, propagation towards subscribers never takes place return apublish(src, dst, ackingPolicy, message); } @Override - public final CompletionStage atell(ReActorRef src, ReActorRef dst, AckingPolicy ackingPolicy, PayloadT message) { + public final CompletionStage atell(ReActorRef src, ReActorRef dst, AckingPolicy ackingPolicy, PayloadT message) { //While sending towards a remote peer, propagation towards subscribers never takes place, //so tell and publish behave in the same way return apublish(src, dst, ackingPolicy, message); @@ -114,7 +115,7 @@ public boolean equals(@Nullable Object o) { * Forward a message just received by a channel to ReActed for propagating it towards the destination mailbox */ @Override - protected void offerMessage(ReActorRef source, ReActorRef destination, + protected void offerMessage(ReActorRef source, ReActorRef destination, long sequenceNumber, ReActorSystemId fromReActorSystemId, AckingPolicy ackingPolicy, @@ -128,7 +129,7 @@ protected void offerMessage(ReActorRef source, R return; } - Class payloadType = payload.getClass(); + Class payloadType = payload.getClass(); boolean hasBeenSniffed = false; //If the message destination is within reactor system. We might have just intercepted a message for some other @@ -206,7 +207,7 @@ protected void offerMessage(ReActorRef source, R } } - private void + private void forwardMessageToSenderDriverInstance(ReActorRef source, ReActorRef destination, long sequenceNumber, ReActorSystemId fromReActorSystemId, AckingPolicy ackingPolicy, PayloadT payload, DeliveryStatusUpdate deliveryStatusUpdate) { @@ -224,7 +225,7 @@ private boolean messageWasNotSentFromThisDriverInstance(DeliveryStatusUpdate del } private static boolean isTypeSubscribed(ReActorSystem localReActorSystem, - Class payloadType) { + Class payloadType) { return localReActorSystem.getTypedSubscriptionsManager().hasFullSubscribers(payloadType); } } diff --git a/core/src/main/java/io/reacted/core/mailboxes/BackpressuringMbox.java b/core/src/main/java/io/reacted/core/mailboxes/BackpressuringMbox.java index 31dcf31a..1dc049d9 100644 --- a/core/src/main/java/io/reacted/core/mailboxes/BackpressuringMbox.java +++ b/core/src/main/java/io/reacted/core/mailboxes/BackpressuringMbox.java @@ -13,11 +13,11 @@ import io.reacted.core.messages.reactors.ReActorInit; import io.reacted.core.messages.reactors.ReActorStop; import io.reacted.core.reactorsystem.ReActorContext; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; import io.reacted.patterns.ObjectUtils; import javax.annotation.Nonnull; -import java.io.Serializable; import java.util.Arrays; import java.util.Objects; import java.util.Optional; @@ -32,8 +32,8 @@ public class BackpressuringMbox implements MailBox { public static final long DEFAULT_MESSAGES_REQUESTED_ON_STARTUP = 1L; private final MailBox realMbox; - private final AtomicReference>> notDelayable; - private final Set outOfStreamControl; + private final AtomicReference>> notDelayable; + private final Set> outOfStreamControl; private final ReActorContext realMailboxOwner; private final long backpressuringThreshold; private final BlockingDeque bufferQueue = new LinkedBlockingDeque<>(); @@ -125,17 +125,17 @@ public static Optional toBackpressuringMailbox(MailBox mailB ? Optional.of((BackpressuringMbox)mailBox) : Optional.empty(); } - public boolean isDelayable(Class payloadType) { + public boolean isDelayable(Class payloadType) { return !notDelayable.get().contains(payloadType); } @SafeVarargs - public final BackpressuringMbox addNonDelayableTypes(Class... notDelayedToAdd) { + public final BackpressuringMbox addNonDelayableTypes(Class... notDelayedToAdd) { return addNonDelayableTypes(Arrays.stream(notDelayedToAdd).collect(Collectors.toSet())); } - public BackpressuringMbox addNonDelayableTypes(Set> notDelayedToAdd) { - Set> notDelayedCache; - Set> notDelayedMerge; + public BackpressuringMbox addNonDelayableTypes(Set> notDelayedToAdd) { + Set> notDelayedCache; + Set> notDelayedMerge; do { notDelayedCache = notDelayable.get(); notDelayedMerge = Stream.concat(notDelayedCache.stream(), @@ -161,9 +161,9 @@ public static class Builder { @SuppressWarnings("NotNullFieldNotInitialized") private ReActorContext realMailboxOwner; - private Set> notDelayable = Set.of(ReActorInit.class, + private Set> notDelayable = Set.of(ReActorInit.class, ReActorStop.class); - private Set> outOfStreamControl = Set.of(); + private Set> outOfStreamControl = Set.of(); private Builder() { } @@ -177,7 +177,7 @@ private Builder() { } * @return this {@link Builder} */ @SafeVarargs - public final Builder setOutOfStreamControl(Class ...notRegulatedByStreamControl) { + public final Builder setOutOfStreamControl(Class ...notRegulatedByStreamControl) { this.outOfStreamControl = Set.of(notRegulatedByStreamControl); return this; } @@ -229,7 +229,7 @@ public final Builder setAvailableOnStartup(int availableOnStartup) { * @return this {@link Builder} */ @SafeVarargs - public final Builder setNonDelayable(Class ...notDelayable) { + public final Builder setNonDelayable(Class ...notDelayable) { this.notDelayable = Set.of(notDelayable); return this; } diff --git a/core/src/main/java/io/reacted/core/mailboxes/TypeCoalescingMailbox.java b/core/src/main/java/io/reacted/core/mailboxes/TypeCoalescingMailbox.java index 26368c97..a5bcb891 100644 --- a/core/src/main/java/io/reacted/core/mailboxes/TypeCoalescingMailbox.java +++ b/core/src/main/java/io/reacted/core/mailboxes/TypeCoalescingMailbox.java @@ -10,10 +10,10 @@ import io.reacted.core.messages.Message; import io.reacted.core.messages.reactors.DeliveryStatus; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; import javax.annotation.Nonnull; -import java.io.Serializable; import java.util.Deque; import java.util.HashMap; import java.util.Map; @@ -24,9 +24,9 @@ @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter") @NonNullByDefault public class TypeCoalescingMailbox implements MailBox { - private final Map, Message> latestByPayloadType; - private final Set> pendingUpdatedTypes; - private final Deque> lastAdded; + private final Map, Message> latestByPayloadType; + private final Set> pendingUpdatedTypes; + private final Deque> lastAdded; public TypeCoalescingMailbox() { this.latestByPayloadType = new HashMap<>(); diff --git a/core/src/main/java/io/reacted/core/messages/Message.java b/core/src/main/java/io/reacted/core/messages/Message.java index f22e1498..054f596f 100644 --- a/core/src/main/java/io/reacted/core/messages/Message.java +++ b/core/src/main/java/io/reacted/core/messages/Message.java @@ -10,17 +10,16 @@ import io.reacted.core.reactorsystem.ReActorRef; import io.reacted.core.reactorsystem.ReActorSystemId; +import io.reacted.core.serialization.Deserializer; +import io.reacted.core.serialization.ReActedMessage; +import io.reacted.core.serialization.Serializer; import io.reacted.patterns.NonNullByDefault; import javax.annotation.Nullable; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; -import java.io.Serializable; import java.util.Objects; @NonNullByDefault -public final class Message implements Serializable { +public final class Message implements ReActedMessage { private static final long SENDER_OFFSET = SerializationUtils.getFieldOffset(Message.class, "sender") .orElseSneakyThrow(); private static final long DESTINATION_OFFSET = SerializationUtils.getFieldOffset(Message.class, "destination") @@ -38,7 +37,7 @@ public final class Message implements Serializable { private final long sequenceNumber; private final ReActorSystemId creatingReactorSystemId; private final AckingPolicy ackingPolicy; - private final Serializable payload; + private final ReActedMessage payload; public Message() { this(ReActorRef.NO_REACTOR_REF, ReActorRef.NO_REACTOR_REF, 0L, @@ -46,7 +45,7 @@ public Message() { } private Message(ReActorRef sender, ReActorRef destination, long sequenceNumber, - ReActorSystemId creatingReActorSystem, AckingPolicy ackingPolicy, Serializable payload) { + ReActorSystemId creatingReActorSystem, AckingPolicy ackingPolicy, ReActedMessage payload) { this.sender = sender; this.destination = destination; this.sequenceNumber = sequenceNumber; @@ -55,7 +54,7 @@ private Message(ReActorRef sender, ReActorRef destination, long sequenceNumber, this.payload = payload; } public static Message of(ReActorRef sender, ReActorRef destination, long sequenceNumber, - ReActorSystemId generatingReActorSystem, AckingPolicy ackingPolicy, Serializable payload) { + ReActorSystemId generatingReActorSystem, AckingPolicy ackingPolicy, ReActedMessage payload) { return new Message(sender, destination, sequenceNumber, generatingReActorSystem, ackingPolicy, payload); } @@ -80,32 +79,30 @@ public String toString() { return "Message{" + "sender=" + sender + ", destination=" + destination + ", sequenceNumber=" + sequenceNumber + ", creatingReactorSystemId=" + creatingReactorSystemId + ", ackingPolicy=" + ackingPolicy + ", payload=" + payload + '}'; } - public void writeExternal(ObjectOutput out) throws IOException { - Objects.requireNonNull(sender).writeExternal(out); - Objects.requireNonNull(destination).writeExternal(out); - Objects.requireNonNull(creatingReactorSystemId).writeExternal(out); - out.writeInt(ackingPolicy.ordinal()); - out.writeLong(sequenceNumber); - out.writeObject(payload); + @Override + public void encode(Serializer serializer) { + Objects.requireNonNull(sender).encode(serializer); + Objects.requireNonNull(destination).encode(serializer); + Objects.requireNonNull(creatingReactorSystemId).encode(serializer); + serializer.put(ackingPolicy.ordinal()); + serializer.put(sequenceNumber); + payload.encode(serializer); } - public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + @Override + public void decode(Deserializer deserializer) { ReActorRef senderRef = new ReActorRef(); - senderRef.readExternal(in); + senderRef.decode(deserializer); setSender(senderRef); var destinationRef = new ReActorRef(); - destinationRef.readExternal(in); + destinationRef.decode(deserializer); setDestination(destinationRef); var receivedGeneratingReActorSystem = new ReActorSystemId(); - receivedGeneratingReActorSystem.readExternal(in); + receivedGeneratingReActorSystem.decode(deserializer); setCreatingReactorSystemId(receivedGeneratingReActorSystem); - setAckingPolicy(AckingPolicy.forOrdinal(in.readInt())); - setSequenceNumber(in.readLong()); - try { - setPayload((Serializable)in.readObject()); - } catch (Exception exc) { - exc.printStackTrace(); - } + setAckingPolicy(AckingPolicy.forOrdinal(deserializer.getInt())); + setSequenceNumber(deserializer.getLong()); + setPayload((ReActedMessage)deserializer.getObject()); } public ReActorRef getSender() { return sender; } @@ -117,7 +114,7 @@ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundExcept public AckingPolicy getAckingPolicy() { return ackingPolicy; } - public Serializable getPayload() { return payload; } + public ReActedMessage getPayload() { return payload; } @SuppressWarnings("UnusedReturnValue") private Message setSender(ReActorRef sender) { @@ -145,7 +142,7 @@ private Message setSequenceNumber(long sequenceNumber) { } @SuppressWarnings("UnusedReturnValue") - private Message setPayload(Serializable payload) { + private Message setPayload(ReActedMessage payload) { return SerializationUtils.setObjectField(this, PAYLOAD_OFFSET, payload); } } diff --git a/core/src/main/java/io/reacted/core/messages/SerializationUtils.java b/core/src/main/java/io/reacted/core/messages/SerializationUtils.java index 7e791283..b91b12a0 100644 --- a/core/src/main/java/io/reacted/core/messages/SerializationUtils.java +++ b/core/src/main/java/io/reacted/core/messages/SerializationUtils.java @@ -8,16 +8,28 @@ package io.reacted.core.messages; +import io.reacted.core.serialization.Deserializer; +import io.reacted.core.serialization.ReActedMessage; +import io.reacted.core.serialization.Serializer; import io.reacted.patterns.NonNullByDefault; import io.reacted.patterns.Try; import sun.misc.Unsafe; -import java.io.Serializable; import java.lang.reflect.Field; @NonNullByDefault public final class SerializationUtils { - public static final Serializable NO_PAYLOAD = new Serializable() {}; + public static final ReActedMessage NO_PAYLOAD = new ReActedMessage() { + @Override + public void encode(Serializer serializer) { + + } + + @Override + public void decode(Deserializer deserializer) { + + } + }; private static final Unsafe UNSAFE = Try.of(SerializationUtils::getUnsafeRef) .orElseSneakyThrow(); diff --git a/core/src/main/java/io/reacted/core/messages/reactors/DeadMessage.java b/core/src/main/java/io/reacted/core/messages/reactors/DeadMessage.java index f55cd3a3..9823fc20 100644 --- a/core/src/main/java/io/reacted/core/messages/reactors/DeadMessage.java +++ b/core/src/main/java/io/reacted/core/messages/reactors/DeadMessage.java @@ -9,34 +9,36 @@ package io.reacted.core.messages.reactors; import io.reacted.core.messages.SerializationUtils; +import io.reacted.core.serialization.Deserializer; +import io.reacted.core.serialization.ReActedMessage; +import io.reacted.core.serialization.Serializer; import io.reacted.patterns.NonNullByDefault; -import java.io.Serial; import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; -import java.io.Serializable; +import java.io.Serial; import java.util.Objects; @Immutable @NonNullByDefault -public class DeadMessage implements Externalizable { +public class DeadMessage implements Externalizable, ReActedMessage { @Serial private static final long serialVersionUID = 1; private static final long PAYLOAD_OFFSET = SerializationUtils.getFieldOffset(DeadMessage.class, "payload") .orElseSneakyThrow(); - private final Serializable payload; + private final ReActedMessage payload; public DeadMessage() { this.payload = SerializationUtils.NO_PAYLOAD; /* required for Externalizable */ } - public DeadMessage(Serializable payload) { this.payload = payload; } + public DeadMessage(ReActedMessage payload) { this.payload = payload; } @SuppressWarnings("unchecked") - public PayloadT getPayload() { return (PayloadT)payload; } + public PayloadT getPayload() { return (PayloadT)payload; } @Override public boolean equals(@Nullable Object o) { @@ -65,4 +67,14 @@ public void writeExternal(ObjectOutput out) throws IOException { public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { SerializationUtils.setObjectField(this, PAYLOAD_OFFSET, in.readObject()); } + + @Override + public void encode(Serializer serializer) { + + } + + @Override + public void decode(Deserializer deserializer) { + + } } diff --git a/core/src/main/java/io/reacted/core/messages/reactors/DeliveryStatusUpdate.java b/core/src/main/java/io/reacted/core/messages/reactors/DeliveryStatusUpdate.java index 72426abd..50d69292 100644 --- a/core/src/main/java/io/reacted/core/messages/reactors/DeliveryStatusUpdate.java +++ b/core/src/main/java/io/reacted/core/messages/reactors/DeliveryStatusUpdate.java @@ -11,13 +11,14 @@ import com.google.common.base.Objects; import io.reacted.core.config.ChannelId; import io.reacted.core.reactorsystem.ReActorSystemId; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; -import java.io.Serializable; + import javax.annotation.concurrent.Immutable; @Immutable @NonNullByDefault -public class DeliveryStatusUpdate implements Serializable { +public class DeliveryStatusUpdate implements ReActedMessage { private final long msgSeqNum; private final DeliveryStatus deliveryStatus; diff --git a/core/src/main/java/io/reacted/core/messages/reactors/EventExecutionAttempt.java b/core/src/main/java/io/reacted/core/messages/reactors/EventExecutionAttempt.java index b099a2fc..f343b11d 100644 --- a/core/src/main/java/io/reacted/core/messages/reactors/EventExecutionAttempt.java +++ b/core/src/main/java/io/reacted/core/messages/reactors/EventExecutionAttempt.java @@ -10,19 +10,18 @@ import io.reacted.core.messages.Recyclable; import io.reacted.core.reactors.ReActorId; +import io.reacted.core.serialization.Deserializer; +import io.reacted.core.serialization.ReActedMessage; +import io.reacted.core.serialization.Serializer; import io.reacted.patterns.NonNullByDefault; import javax.annotation.concurrent.Immutable; -import java.io.Externalizable; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; import java.io.Serial; import java.util.Objects; @Immutable @NonNullByDefault -public class EventExecutionAttempt implements Externalizable, Recyclable { +public class EventExecutionAttempt implements ReActedMessage, Recyclable { @Serial private static final long serialVersionUID = 1; @@ -68,20 +67,20 @@ public String toString() { } @Override - public void writeExternal(ObjectOutput out) throws IOException { - getReActorId().writeExternal(out); - out.writeLong(getExecutionSeqNum()); - out.writeLong(getMsgSeqNum()); + public void encode(Serializer serializer) { + getReActorId().encode(serializer); + serializer.put(getExecutionSeqNum()); + serializer.put(getMsgSeqNum()); revalidate(); } @Override - public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + public void decode(Deserializer deserializer) { var receivedReActorId = new ReActorId(); - receivedReActorId.readExternal(in); + receivedReActorId.decode(deserializer); setReActorId(receivedReActorId); - setExecutionSeqNum(in.readLong()); - setMessageSeqNum(in.readLong()); + setExecutionSeqNum(deserializer.getLong()); + setMessageSeqNum(deserializer.getLong()); revalidate(); } diff --git a/core/src/main/java/io/reacted/core/messages/reactors/LogMessage.java b/core/src/main/java/io/reacted/core/messages/reactors/LogMessage.java index a8640a2c..cfba047f 100644 --- a/core/src/main/java/io/reacted/core/messages/reactors/LogMessage.java +++ b/core/src/main/java/io/reacted/core/messages/reactors/LogMessage.java @@ -8,25 +8,25 @@ package io.reacted.core.messages.reactors; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; import org.apache.commons.lang3.exception.ExceptionUtils; import org.slf4j.helpers.MessageFormatter; import java.io.Serializable; + @NonNullByDefault -public abstract class LogMessage implements Serializable { - private final String message; - protected LogMessage(String format, Serializable ...arguments) { +public abstract class LogMessage extends ReActedMessage.StringMessage { + protected LogMessage(String format, Serializable...arguments) { var formattingTuple = MessageFormatter.arrayFormat(format, arguments); - this.message = formattingTuple.getMessage() + (formattingTuple.getThrowable() != null + super.payload = formattingTuple.getMessage() + (formattingTuple.getThrowable() != null ? ExceptionUtils.getStackTrace(formattingTuple.getThrowable()) : ""); } - - public String getMessage() { return message; } + public String getMessage() { return payload; } @Override public String toString() { - return "LogMessage{" + "message='" + message + '\'' + '}'; + return "LogMessage{" + "message='" + payload + '\'' + '}'; } } diff --git a/core/src/main/java/io/reacted/core/messages/reactors/ReActedError.java b/core/src/main/java/io/reacted/core/messages/reactors/ReActedError.java index 0241b8cb..229ba886 100644 --- a/core/src/main/java/io/reacted/core/messages/reactors/ReActedError.java +++ b/core/src/main/java/io/reacted/core/messages/reactors/ReActedError.java @@ -16,7 +16,7 @@ @Immutable @NonNullByDefault public class ReActedError extends LogMessage { - public ReActedError(String format, Serializable... arguments) { + public ReActedError(String format, Serializable ...arguments) { super(format, arguments); } } diff --git a/core/src/main/java/io/reacted/core/messages/reactors/ReActedInfo.java b/core/src/main/java/io/reacted/core/messages/reactors/ReActedInfo.java index 453d0098..acdb4321 100644 --- a/core/src/main/java/io/reacted/core/messages/reactors/ReActedInfo.java +++ b/core/src/main/java/io/reacted/core/messages/reactors/ReActedInfo.java @@ -16,7 +16,7 @@ @Immutable @NonNullByDefault public class ReActedInfo extends LogMessage { - public ReActedInfo(String format, Serializable... arguments) { + public ReActedInfo(String format, Serializable ...arguments) { super(format, arguments); } } diff --git a/core/src/main/java/io/reacted/core/messages/reactors/ReActorInit.java b/core/src/main/java/io/reacted/core/messages/reactors/ReActorInit.java index 71e58793..4693ec83 100644 --- a/core/src/main/java/io/reacted/core/messages/reactors/ReActorInit.java +++ b/core/src/main/java/io/reacted/core/messages/reactors/ReActorInit.java @@ -8,27 +8,15 @@ package io.reacted.core.messages.reactors; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; -import java.io.Serial; import javax.annotation.concurrent.Immutable; -import java.io.Externalizable; -import java.io.ObjectInput; -import java.io.ObjectOutput; + @Immutable @NonNullByDefault -public final class ReActorInit implements Externalizable { - - @Serial - private static final long serialVersionUID = 1; - - @Override - public void writeExternal(ObjectOutput out) { /* No fields */ } - - @Override - public void readExternal(ObjectInput in) { /* No fields */ } - +public final class ReActorInit implements ReActedMessage { @Override public String toString() { return "ReActorInit{}"; diff --git a/core/src/main/java/io/reacted/core/messages/reactors/ReActorStop.java b/core/src/main/java/io/reacted/core/messages/reactors/ReActorStop.java index 0ea48913..2f242fd9 100644 --- a/core/src/main/java/io/reacted/core/messages/reactors/ReActorStop.java +++ b/core/src/main/java/io/reacted/core/messages/reactors/ReActorStop.java @@ -8,26 +8,15 @@ package io.reacted.core.messages.reactors; -import java.io.Serial; +import io.reacted.core.serialization.ReActedMessage; + import javax.annotation.concurrent.Immutable; -import java.io.Externalizable; -import java.io.ObjectInput; -import java.io.ObjectOutput; @Immutable -public final class ReActorStop implements Externalizable { +public final class ReActorStop implements ReActedMessage { public static final ReActorStop STOP = new ReActorStop(); - @Serial - private static final long serialVersionUID = 1; - - @Override - public void writeExternal(ObjectOutput out) { /* No fields */ } - @Override public String toString() { return "ReActorStop{}"; } - - @Override - public void readExternal(ObjectInput in) { /* No fields */ } } diff --git a/core/src/main/java/io/reacted/core/messages/reactors/SystemMonitorReport.java b/core/src/main/java/io/reacted/core/messages/reactors/SystemMonitorReport.java index 42899c70..484a3d66 100644 --- a/core/src/main/java/io/reacted/core/messages/reactors/SystemMonitorReport.java +++ b/core/src/main/java/io/reacted/core/messages/reactors/SystemMonitorReport.java @@ -8,10 +8,10 @@ package io.reacted.core.messages.reactors; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.ObjectUtils; -import java.io.Serializable; -public class SystemMonitorReport implements Serializable { +public class SystemMonitorReport implements ReActedMessage { private final double cpuLoad; private final long freeMemorySize; diff --git a/core/src/main/java/io/reacted/core/messages/serviceregistry/DuplicatedPublicationError.java b/core/src/main/java/io/reacted/core/messages/serviceregistry/DuplicatedPublicationError.java index cda4bd72..6631b647 100644 --- a/core/src/main/java/io/reacted/core/messages/serviceregistry/DuplicatedPublicationError.java +++ b/core/src/main/java/io/reacted/core/messages/serviceregistry/DuplicatedPublicationError.java @@ -8,6 +8,6 @@ package io.reacted.core.messages.serviceregistry; -import java.io.Serializable; +import io.reacted.core.serialization.ReActedMessage; -public class DuplicatedPublicationError implements Serializable {} +public class DuplicatedPublicationError implements ReActedMessage {} diff --git a/core/src/main/java/io/reacted/core/messages/serviceregistry/FilterServiceDiscoveryRequest.java b/core/src/main/java/io/reacted/core/messages/serviceregistry/FilterServiceDiscoveryRequest.java index d8a643ac..bcf50bf4 100644 --- a/core/src/main/java/io/reacted/core/messages/serviceregistry/FilterServiceDiscoveryRequest.java +++ b/core/src/main/java/io/reacted/core/messages/serviceregistry/FilterServiceDiscoveryRequest.java @@ -11,15 +11,15 @@ import com.google.common.base.Objects; import io.reacted.core.messages.services.FilterItem; import io.reacted.core.messages.services.ServiceDiscoverySearchFilter; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; import javax.annotation.concurrent.Immutable; -import java.io.Serializable; import java.util.Collection; @NonNullByDefault @Immutable -public class FilterServiceDiscoveryRequest implements Serializable { +public class FilterServiceDiscoveryRequest implements ReActedMessage { private final ServiceDiscoverySearchFilter filteringRuleToApply; private final Collection serviceDiscoveryResult; diff --git a/core/src/main/java/io/reacted/core/messages/serviceregistry/ReActorSystemChannelIdCancellationRequest.java b/core/src/main/java/io/reacted/core/messages/serviceregistry/ReActorSystemChannelIdCancellationRequest.java index de629176..580c5f67 100644 --- a/core/src/main/java/io/reacted/core/messages/serviceregistry/ReActorSystemChannelIdCancellationRequest.java +++ b/core/src/main/java/io/reacted/core/messages/serviceregistry/ReActorSystemChannelIdCancellationRequest.java @@ -10,14 +10,14 @@ import io.reacted.core.config.ChannelId; import io.reacted.core.reactorsystem.ReActorSystemId; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; import javax.annotation.concurrent.Immutable; -import java.io.Serializable; @Immutable @NonNullByDefault -public class ReActorSystemChannelIdCancellationRequest implements Serializable { +public class ReActorSystemChannelIdCancellationRequest implements ReActedMessage { private final ReActorSystemId reActorSystemId; private final ChannelId channelId; diff --git a/core/src/main/java/io/reacted/core/messages/serviceregistry/ReActorSystemChannelIdPublicationError.java b/core/src/main/java/io/reacted/core/messages/serviceregistry/ReActorSystemChannelIdPublicationError.java index d08d01e6..7c443bf9 100644 --- a/core/src/main/java/io/reacted/core/messages/serviceregistry/ReActorSystemChannelIdPublicationError.java +++ b/core/src/main/java/io/reacted/core/messages/serviceregistry/ReActorSystemChannelIdPublicationError.java @@ -8,6 +8,6 @@ package io.reacted.core.messages.serviceregistry; -import java.io.Serializable; +import io.reacted.core.serialization.ReActedMessage; -public class ReActorSystemChannelIdPublicationError implements Serializable {} +public class ReActorSystemChannelIdPublicationError implements ReActedMessage {} diff --git a/core/src/main/java/io/reacted/core/messages/serviceregistry/ReActorSystemChannelIdPublicationRequest.java b/core/src/main/java/io/reacted/core/messages/serviceregistry/ReActorSystemChannelIdPublicationRequest.java index d0416a7d..e0ed4353 100644 --- a/core/src/main/java/io/reacted/core/messages/serviceregistry/ReActorSystemChannelIdPublicationRequest.java +++ b/core/src/main/java/io/reacted/core/messages/serviceregistry/ReActorSystemChannelIdPublicationRequest.java @@ -10,14 +10,15 @@ import io.reacted.core.config.ChannelId; import io.reacted.core.reactorsystem.ReActorSystemId; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; -import java.io.Serializable; -import java.util.Properties; + import javax.annotation.concurrent.Immutable; +import java.util.Properties; @Immutable @NonNullByDefault -public class ReActorSystemChannelIdPublicationRequest implements Serializable { +public class ReActorSystemChannelIdPublicationRequest implements ReActedMessage { private final ReActorSystemId reActorSystemId; private final ChannelId channelId; private final Properties channelIdData; diff --git a/core/src/main/java/io/reacted/core/messages/serviceregistry/RegistryConnectionLost.java b/core/src/main/java/io/reacted/core/messages/serviceregistry/RegistryConnectionLost.java index 673b038f..dbe32b2a 100644 --- a/core/src/main/java/io/reacted/core/messages/serviceregistry/RegistryConnectionLost.java +++ b/core/src/main/java/io/reacted/core/messages/serviceregistry/RegistryConnectionLost.java @@ -8,6 +8,6 @@ package io.reacted.core.messages.serviceregistry; -import java.io.Serializable; +import io.reacted.core.serialization.ReActedMessage; -public class RegistryConnectionLost implements Serializable {} +public class RegistryConnectionLost implements ReActedMessage {} diff --git a/core/src/main/java/io/reacted/core/messages/serviceregistry/RegistryDriverInitComplete.java b/core/src/main/java/io/reacted/core/messages/serviceregistry/RegistryDriverInitComplete.java index b5594dd5..b6d9e345 100644 --- a/core/src/main/java/io/reacted/core/messages/serviceregistry/RegistryDriverInitComplete.java +++ b/core/src/main/java/io/reacted/core/messages/serviceregistry/RegistryDriverInitComplete.java @@ -8,9 +8,10 @@ package io.reacted.core.messages.serviceregistry; +import io.reacted.core.serialization.ReActedMessage; + import javax.annotation.concurrent.Immutable; -import java.io.Serializable; @Immutable -public class RegistryDriverInitComplete implements Serializable { +public class RegistryDriverInitComplete implements ReActedMessage { } diff --git a/core/src/main/java/io/reacted/core/messages/serviceregistry/RegistryGateRemoved.java b/core/src/main/java/io/reacted/core/messages/serviceregistry/RegistryGateRemoved.java index 4a5709dd..d3c741a7 100644 --- a/core/src/main/java/io/reacted/core/messages/serviceregistry/RegistryGateRemoved.java +++ b/core/src/main/java/io/reacted/core/messages/serviceregistry/RegistryGateRemoved.java @@ -10,15 +10,15 @@ import io.reacted.core.config.ChannelId; import io.reacted.core.reactorsystem.ReActorSystemId; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; import javax.annotation.concurrent.Immutable; -import java.io.Serializable; import java.util.Objects; @Immutable @NonNullByDefault -public class RegistryGateRemoved implements Serializable { +public class RegistryGateRemoved implements ReActedMessage { private final ReActorSystemId removedReActorSystem; private final ChannelId channelId; public RegistryGateRemoved(String reActorSystemName, ChannelId channelId) { diff --git a/core/src/main/java/io/reacted/core/messages/serviceregistry/RegistryGateUpserted.java b/core/src/main/java/io/reacted/core/messages/serviceregistry/RegistryGateUpserted.java index a27abdd4..83c4f4af 100644 --- a/core/src/main/java/io/reacted/core/messages/serviceregistry/RegistryGateUpserted.java +++ b/core/src/main/java/io/reacted/core/messages/serviceregistry/RegistryGateUpserted.java @@ -10,16 +10,16 @@ import io.reacted.core.config.ChannelId; import io.reacted.core.reactorsystem.ReActorSystemId; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; import javax.annotation.concurrent.Immutable; -import java.io.Serializable; import java.util.Objects; import java.util.Properties; @Immutable @NonNullByDefault -public class RegistryGateUpserted implements Serializable { +public class RegistryGateUpserted implements ReActedMessage { private final ReActorSystemId reActorSystemId; private final ChannelId channelId; private final Properties channelData; diff --git a/core/src/main/java/io/reacted/core/messages/serviceregistry/RegistryServicePublicationFailed.java b/core/src/main/java/io/reacted/core/messages/serviceregistry/RegistryServicePublicationFailed.java index 5dfd5371..65f52167 100644 --- a/core/src/main/java/io/reacted/core/messages/serviceregistry/RegistryServicePublicationFailed.java +++ b/core/src/main/java/io/reacted/core/messages/serviceregistry/RegistryServicePublicationFailed.java @@ -8,15 +8,15 @@ package io.reacted.core.messages.serviceregistry; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; import javax.annotation.concurrent.Immutable; -import java.io.Serializable; import java.util.Objects; @Immutable @NonNullByDefault -public class RegistryServicePublicationFailed implements Serializable { +public class RegistryServicePublicationFailed implements ReActedMessage { private final Throwable publicationError; private final String serviceName; diff --git a/core/src/main/java/io/reacted/core/messages/serviceregistry/ServiceCancellationRequest.java b/core/src/main/java/io/reacted/core/messages/serviceregistry/ServiceCancellationRequest.java index bd970dff..ab5c5b17 100644 --- a/core/src/main/java/io/reacted/core/messages/serviceregistry/ServiceCancellationRequest.java +++ b/core/src/main/java/io/reacted/core/messages/serviceregistry/ServiceCancellationRequest.java @@ -9,14 +9,14 @@ package io.reacted.core.messages.serviceregistry; import io.reacted.core.reactorsystem.ReActorSystemId; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; import javax.annotation.concurrent.Immutable; -import java.io.Serializable; @Immutable @NonNullByDefault -public class ServiceCancellationRequest implements Serializable { +public class ServiceCancellationRequest implements ReActedMessage { private final ReActorSystemId reActorSystemId; private final String serviceName; diff --git a/core/src/main/java/io/reacted/core/messages/serviceregistry/ServicePublicationRequest.java b/core/src/main/java/io/reacted/core/messages/serviceregistry/ServicePublicationRequest.java index 5783205a..09d16bb7 100644 --- a/core/src/main/java/io/reacted/core/messages/serviceregistry/ServicePublicationRequest.java +++ b/core/src/main/java/io/reacted/core/messages/serviceregistry/ServicePublicationRequest.java @@ -10,16 +10,16 @@ import io.reacted.core.messages.SerializationUtils; import io.reacted.core.reactorsystem.ReActorRef; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; import java.io.Serial; -import java.io.Serializable; import java.util.Objects; import java.util.Properties; @NonNullByDefault -public class ServicePublicationRequest implements Serializable { +public class ServicePublicationRequest implements ReActedMessage { @Serial private static final long serialVersionUID = 1; diff --git a/core/src/main/java/io/reacted/core/messages/serviceregistry/ServicePublicationRequestError.java b/core/src/main/java/io/reacted/core/messages/serviceregistry/ServicePublicationRequestError.java index 839f7987..18bb71c4 100644 --- a/core/src/main/java/io/reacted/core/messages/serviceregistry/ServicePublicationRequestError.java +++ b/core/src/main/java/io/reacted/core/messages/serviceregistry/ServicePublicationRequestError.java @@ -8,6 +8,6 @@ package io.reacted.core.messages.serviceregistry; -import java.io.Serializable; +import io.reacted.core.serialization.ReActedMessage; -public class ServicePublicationRequestError implements Serializable {} +public class ServicePublicationRequestError implements ReActedMessage {} diff --git a/core/src/main/java/io/reacted/core/messages/serviceregistry/ServiceRegistryNotAvailable.java b/core/src/main/java/io/reacted/core/messages/serviceregistry/ServiceRegistryNotAvailable.java index 691b3f16..a27c9eaa 100644 --- a/core/src/main/java/io/reacted/core/messages/serviceregistry/ServiceRegistryNotAvailable.java +++ b/core/src/main/java/io/reacted/core/messages/serviceregistry/ServiceRegistryNotAvailable.java @@ -8,6 +8,6 @@ package io.reacted.core.messages.serviceregistry; -import java.io.Serializable; +import io.reacted.core.serialization.ReActedMessage; -public class ServiceRegistryNotAvailable implements Serializable {} +public class ServiceRegistryNotAvailable implements ReActedMessage {} diff --git a/core/src/main/java/io/reacted/core/messages/serviceregistry/SynchronizationWithServiceRegistryComplete.java b/core/src/main/java/io/reacted/core/messages/serviceregistry/SynchronizationWithServiceRegistryComplete.java index 3b8a034f..9927a9e2 100644 --- a/core/src/main/java/io/reacted/core/messages/serviceregistry/SynchronizationWithServiceRegistryComplete.java +++ b/core/src/main/java/io/reacted/core/messages/serviceregistry/SynchronizationWithServiceRegistryComplete.java @@ -8,7 +8,8 @@ package io.reacted.core.messages.serviceregistry; +import io.reacted.core.serialization.ReActedMessage; + import javax.annotation.concurrent.Immutable; -import java.io.Serializable; @Immutable -public class SynchronizationWithServiceRegistryComplete implements Serializable { } +public class SynchronizationWithServiceRegistryComplete implements ReActedMessage { } diff --git a/core/src/main/java/io/reacted/core/messages/serviceregistry/SynchronizationWithServiceRegistryFailed.java b/core/src/main/java/io/reacted/core/messages/serviceregistry/SynchronizationWithServiceRegistryFailed.java index 25a538fc..ec84ffe8 100644 --- a/core/src/main/java/io/reacted/core/messages/serviceregistry/SynchronizationWithServiceRegistryFailed.java +++ b/core/src/main/java/io/reacted/core/messages/serviceregistry/SynchronizationWithServiceRegistryFailed.java @@ -8,6 +8,6 @@ package io.reacted.core.messages.serviceregistry; -import java.io.Serializable; +import io.reacted.core.serialization.ReActedMessage; -public class SynchronizationWithServiceRegistryFailed implements Serializable {} +public class SynchronizationWithServiceRegistryFailed implements ReActedMessage {} diff --git a/core/src/main/java/io/reacted/core/messages/serviceregistry/SynchronizationWithServiceRegistryRequest.java b/core/src/main/java/io/reacted/core/messages/serviceregistry/SynchronizationWithServiceRegistryRequest.java index e6945040..444c9d52 100644 --- a/core/src/main/java/io/reacted/core/messages/serviceregistry/SynchronizationWithServiceRegistryRequest.java +++ b/core/src/main/java/io/reacted/core/messages/serviceregistry/SynchronizationWithServiceRegistryRequest.java @@ -8,8 +8,9 @@ package io.reacted.core.messages.serviceregistry; +import io.reacted.core.serialization.ReActedMessage; + import javax.annotation.concurrent.Immutable; -import java.io.Serializable; @Immutable -public class SynchronizationWithServiceRegistryRequest implements Serializable { } +public class SynchronizationWithServiceRegistryRequest implements ReActedMessage { } diff --git a/core/src/main/java/io/reacted/core/messages/services/FilterItem.java b/core/src/main/java/io/reacted/core/messages/services/FilterItem.java index 04a0a293..13d96bc9 100644 --- a/core/src/main/java/io/reacted/core/messages/services/FilterItem.java +++ b/core/src/main/java/io/reacted/core/messages/services/FilterItem.java @@ -10,13 +10,13 @@ import com.google.common.base.Objects; import io.reacted.core.reactorsystem.ReActorRef; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; -import java.io.Serializable; import java.util.Properties; @NonNullByDefault -public record FilterItem(ReActorRef serviceGate, Properties serviceProperties) implements Serializable { +public record FilterItem(ReActorRef serviceGate, Properties serviceProperties) implements ReActedMessage { @Override public boolean equals(Object o) { diff --git a/core/src/main/java/io/reacted/core/messages/services/ServiceDiscoveryReply.java b/core/src/main/java/io/reacted/core/messages/services/ServiceDiscoveryReply.java index 4f01748d..342585f1 100644 --- a/core/src/main/java/io/reacted/core/messages/services/ServiceDiscoveryReply.java +++ b/core/src/main/java/io/reacted/core/messages/services/ServiceDiscoveryReply.java @@ -9,12 +9,12 @@ package io.reacted.core.messages.services; import io.reacted.core.reactorsystem.ReActorRef; +import io.reacted.core.serialization.ReActedMessage; -import java.io.Serializable; import java.util.Collections; import java.util.Set; -public class ServiceDiscoveryReply implements Serializable { +public class ServiceDiscoveryReply implements ReActedMessage { private final Set serviceRefs; public ServiceDiscoveryReply(ReActorRef serviceRef) { this.serviceRefs = Set.of(serviceRef); diff --git a/core/src/main/java/io/reacted/core/messages/services/ServiceDiscoveryRequest.java b/core/src/main/java/io/reacted/core/messages/services/ServiceDiscoveryRequest.java index bee9e5e8..40c2da01 100644 --- a/core/src/main/java/io/reacted/core/messages/services/ServiceDiscoveryRequest.java +++ b/core/src/main/java/io/reacted/core/messages/services/ServiceDiscoveryRequest.java @@ -8,13 +8,14 @@ package io.reacted.core.messages.services; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; + import javax.annotation.concurrent.Immutable; -import java.io.Serializable; @Immutable @NonNullByDefault -public class ServiceDiscoveryRequest implements Serializable { +public class ServiceDiscoveryRequest implements ReActedMessage { private final ServiceDiscoverySearchFilter searchFilter; public ServiceDiscoveryRequest(ServiceDiscoverySearchFilter searchFilter) { this.searchFilter = searchFilter; diff --git a/core/src/main/java/io/reacted/core/messages/services/ServiceDiscoverySearchFilter.java b/core/src/main/java/io/reacted/core/messages/services/ServiceDiscoverySearchFilter.java index 5098b47f..a3c714e6 100644 --- a/core/src/main/java/io/reacted/core/messages/services/ServiceDiscoverySearchFilter.java +++ b/core/src/main/java/io/reacted/core/messages/services/ServiceDiscoverySearchFilter.java @@ -9,13 +9,13 @@ package io.reacted.core.messages.services; import io.reacted.core.reactorsystem.ReActorRef; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.core.services.SelectionType; import io.reacted.core.services.Service; -import java.io.Serializable; import java.util.Properties; -public interface ServiceDiscoverySearchFilter extends Serializable { +public interface ServiceDiscoverySearchFilter extends ReActedMessage { String FIELD_NAME_SERVICE_NAME = "serviceName"; String FIELD_NAME_CPU_LOAD = "cpuLoad"; diff --git a/core/src/main/java/io/reacted/core/reactors/ReActions.java b/core/src/main/java/io/reacted/core/reactors/ReActions.java index 586b7ba7..aa99d29b 100644 --- a/core/src/main/java/io/reacted/core/reactors/ReActions.java +++ b/core/src/main/java/io/reacted/core/reactors/ReActions.java @@ -10,9 +10,9 @@ import com.google.common.collect.ImmutableMap; import io.reacted.core.reactorsystem.ReActorContext; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; -import java.io.Serializable; import java.util.Map; import java.util.Objects; import java.util.function.BiConsumer; @@ -21,9 +21,9 @@ public class ReActions { public static final ReActions NO_REACTIONS = ReActions.newBuilder().build(); - private final Map, - BiConsumer> behaviors; - private final BiConsumer defaultReaction; + private final Map, + BiConsumer> behaviors; + private final BiConsumer defaultReaction; private ReActions(Builder builder) { this.behaviors = builder.callbacks.build(); @@ -32,31 +32,31 @@ private ReActions(Builder builder) { } @SuppressWarnings("unchecked") - public + public BiConsumer getReAction(PayloadT payload) { return (BiConsumer) behaviors.getOrDefault(payload.getClass(), defaultReaction); } public static Builder newBuilder() { return new Builder(); } - private Map, BiConsumer> + private Map, BiConsumer> getBehaviors() { return behaviors; } public static class Builder { - private final ImmutableMap.Builder, - BiConsumer> callbacks; - private BiConsumer anyType = ReActions::noReAction; + private final ImmutableMap.Builder, + BiConsumer> callbacks; + private BiConsumer anyType = ReActions::noReAction; private Builder() { this.callbacks = ImmutableMap.builder(); } - public final Builder reAct(BiConsumer defaultReaction) { + public final Builder reAct(BiConsumer defaultReaction) { this.anyType = defaultReaction; return this; } - public final + public final Builder reAct(Class payloadType, BiConsumer behavior) { callbacks.put(Objects.requireNonNull(payloadType, "Message type cannot be null"), Objects.requireNonNull(behavior, "Message callback cannot be null")); @@ -76,6 +76,6 @@ public ReActions build() { } @SuppressWarnings("EmptyMethod") - public static + public static void noReAction(ReActorContext ctx, PayloadT payload) { /* No Reactions */ } } diff --git a/core/src/main/java/io/reacted/core/reactors/ReActorId.java b/core/src/main/java/io/reacted/core/reactors/ReActorId.java index 45a1b41a..3df51219 100644 --- a/core/src/main/java/io/reacted/core/reactors/ReActorId.java +++ b/core/src/main/java/io/reacted/core/reactors/ReActorId.java @@ -9,19 +9,19 @@ package io.reacted.core.reactors; import io.reacted.core.messages.SerializationUtils; -import java.io.Externalizable; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; +import io.reacted.core.serialization.Deserializer; +import io.reacted.core.serialization.ReActedMessage; +import io.reacted.core.serialization.Serializer; + +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; import java.io.Serial; import java.nio.charset.StandardCharsets; import java.util.Objects; import java.util.UUID; -import javax.annotation.Nullable; -import javax.annotation.concurrent.Immutable; @Immutable -public final class ReActorId implements Externalizable { +public final class ReActorId implements ReActedMessage { public static final UUID NO_REACTOR_ID_UUID = new UUID(0, 0); public static final int NO_REACTOR_ID_MARKER = 1; public static final int COMMON_REACTOR_ID_MARKER = 0; @@ -86,21 +86,22 @@ public String getReActorName() { } @Override - public void writeExternal(ObjectOutput out) throws IOException { + public void encode(Serializer serializer) { if (this == NO_REACTOR_ID) { - out.writeInt(NO_REACTOR_ID_MARKER); + serializer.put(NO_REACTOR_ID_MARKER); } else { - out.writeInt(COMMON_REACTOR_ID_MARKER); - out.writeObject(getReActorUUID()); - out.writeObject(reActorName); + serializer.put(COMMON_REACTOR_ID_MARKER); + serializer.put(getReActorUUID().getMostSignificantBits()); + serializer.put(getReActorUUID().getLeastSignificantBits()); + serializer.put(reActorName); } } @Override - public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { - if (in.readInt() != NO_REACTOR_ID_MARKER) { - setReActorUUID((UUID) in.readObject()); - setReActorName((String) in.readObject()); + public void decode(Deserializer deserializer) { + if (deserializer.getInt() != NO_REACTOR_ID_MARKER) { + setReActorUUID(new UUID(deserializer.getLong(), deserializer.getLong())); + setReActorName(deserializer.getString()); setHashCode(Objects.hash(getReActorUUID(), getReActorName())); } } diff --git a/core/src/main/java/io/reacted/core/reactors/systemreactors/Ask.java b/core/src/main/java/io/reacted/core/reactors/systemreactors/Ask.java index 9747daeb..e5a2739a 100644 --- a/core/src/main/java/io/reacted/core/reactors/systemreactors/Ask.java +++ b/core/src/main/java/io/reacted/core/reactors/systemreactors/Ask.java @@ -16,11 +16,11 @@ import io.reacted.core.reactors.ReActor; import io.reacted.core.reactorsystem.ReActorContext; import io.reacted.core.reactorsystem.ReActorRef; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; import io.reacted.patterns.ObjectUtils; import javax.annotation.Nonnull; -import java.io.Serializable; import java.time.Duration; import java.util.Objects; import java.util.concurrent.CompletableFuture; @@ -28,16 +28,16 @@ import java.util.concurrent.TimeoutException; @NonNullByDefault -public class Ask implements ReActor { +public class Ask implements ReActor { private final Duration askTimeout; private final Class expectedReplyType; private final CompletableFuture completionTrigger; private final String requestName; private final ReActorRef target; - private final Serializable request; + private final ReActedMessage request; public Ask(Duration askTimeout, Class expectedReplyType, CompletableFuture completionTrigger, - String requestName, ReActorRef target, Serializable request) { + String requestName, ReActorRef target, ReActedMessage request) { this.askTimeout = ObjectUtils.checkNonNullPositiveTimeInterval(askTimeout); this.expectedReplyType = Objects.requireNonNull(expectedReplyType); this.completionTrigger = Objects.requireNonNull(completionTrigger); @@ -85,7 +85,7 @@ private void onExpectedReply(ReActorContext ctx, ReplyT reply) { ctx.stop() .thenAccept(noVal -> completionTrigger.complete(reply)); } - private void onUnexpected(ReActorContext ctx, Serializable anyType) { + private void onUnexpected(ReActorContext ctx, ReActedMessage anyType) { var failure = new IllegalArgumentException(String.format("Received %s instead of %s", anyType.getClass().getName(), expectedReplyType.getName())); diff --git a/core/src/main/java/io/reacted/core/reactors/systemreactors/DeadLetter.java b/core/src/main/java/io/reacted/core/reactors/systemreactors/DeadLetter.java index 424eb0a5..b573a1a9 100644 --- a/core/src/main/java/io/reacted/core/reactors/systemreactors/DeadLetter.java +++ b/core/src/main/java/io/reacted/core/reactors/systemreactors/DeadLetter.java @@ -13,12 +13,13 @@ import io.reacted.core.messages.reactors.ReActorStop; import io.reacted.core.reactors.ReActions; import io.reacted.core.reactorsystem.ReActorContext; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.core.services.Service; -import java.io.Serializable; -import java.util.concurrent.atomic.AtomicLong; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.concurrent.atomic.AtomicLong; + public class DeadLetter { private static final Logger LOGGER = LoggerFactory.getLogger(DeadLetter.class); public static final ReActions DEADLETTERS = ReActions.newBuilder() @@ -37,7 +38,7 @@ public class DeadLetter { private DeadLetter() { } - private static + private static void onMessage(ReActorContext ctx, PayloadT message) { LOGGER.info("{} of {}: {} of type {} from {}", DeadLetter.class.getSimpleName(), ctx.getReActorSystem().getLocalReActorSystemId().getReActorSystemName(), message, message.getClass(), diff --git a/core/src/main/java/io/reacted/core/reactors/systemreactors/RemotingRoot.java b/core/src/main/java/io/reacted/core/reactors/systemreactors/RemotingRoot.java index 15a7e9ba..da725558 100644 --- a/core/src/main/java/io/reacted/core/reactors/systemreactors/RemotingRoot.java +++ b/core/src/main/java/io/reacted/core/reactors/systemreactors/RemotingRoot.java @@ -32,9 +32,9 @@ import io.reacted.core.reactorsystem.ReActorContext; import io.reacted.core.reactorsystem.ReActorSystem; import io.reacted.core.reactorsystem.ReActorSystemId; +import io.reacted.core.serialization.ReActedMessage; import javax.annotation.concurrent.Immutable; -import java.io.Serializable; import java.util.Collection; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -105,7 +105,7 @@ private static void onInitComplete(ReActorContext ctx, ctx.reply(new SynchronizationWithServiceRegistryRequest()); } - private static void onSpuriousMessage(ReActorContext ctx, Serializable payload) { + private static void onSpuriousMessage(ReActorContext ctx, ReActedMessage payload) { ctx.logError("Spurious message received", new IllegalStateException(payload.toString())); } diff --git a/core/src/main/java/io/reacted/core/reactorsystem/NullReActorSystemRef.java b/core/src/main/java/io/reacted/core/reactorsystem/NullReActorSystemRef.java index 90916c92..788b3e22 100644 --- a/core/src/main/java/io/reacted/core/reactorsystem/NullReActorSystemRef.java +++ b/core/src/main/java/io/reacted/core/reactorsystem/NullReActorSystemRef.java @@ -14,9 +14,9 @@ import io.reacted.core.drivers.system.ReActorSystemDriver; import io.reacted.core.messages.AckingPolicy; import io.reacted.core.messages.reactors.DeliveryStatus; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; -import java.io.Serializable; import java.util.Properties; import java.util.concurrent.CompletionStage; @@ -34,13 +34,13 @@ private NullReActorSystemRef(ReActorSystemId reActorSystemId, Properties channel } @Override - public DeliveryStatus publish(ReActorRef src, ReActorRef dst, + public DeliveryStatus publish(ReActorRef src, ReActorRef dst, PayloadT message) { return NullDriver.NULL_DRIVER.publish(src, dst, message); } @Override - public CompletionStage apublish(ReActorRef src, ReActorRef dst, + public CompletionStage apublish(ReActorRef src, ReActorRef dst, AckingPolicy ackingPolicy, PayloadT message) { return NullDriver.NULL_DRIVER.apublish(src, dst, ackingPolicy, message); diff --git a/core/src/main/java/io/reacted/core/reactorsystem/ReActorContext.java b/core/src/main/java/io/reacted/core/reactorsystem/ReActorContext.java index f8b7c829..521f15da 100644 --- a/core/src/main/java/io/reacted/core/reactorsystem/ReActorContext.java +++ b/core/src/main/java/io/reacted/core/reactorsystem/ReActorContext.java @@ -17,6 +17,7 @@ import io.reacted.core.reactors.ReActiveEntity; import io.reacted.core.reactors.ReActor; import io.reacted.core.runtime.Dispatcher; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.core.typedsubscriptions.TypedSubscription; import io.reacted.core.typedsubscriptions.TypedSubscriptionsManager; import io.reacted.patterns.NonNullByDefault; @@ -145,14 +146,14 @@ public TypedSubscription[] getTypedSubscriptions() { public boolean reschedule() { return getDispatcher().dispatch(this); } - public DeliveryStatus reply(Serializable anyPayload) { return reply(getSelf(), anyPayload); } + public DeliveryStatus reply(ReActedMessage anyPayload) { return reply(getSelf(), anyPayload); } - public DeliveryStatus reply(ReActorRef sender, Serializable anyPayload) { + public DeliveryStatus reply(ReActorRef sender, ReActedMessage anyPayload) { return getSender().publish(sender, anyPayload); } public Try> - rescheduleMessage(Serializable messageToBeRescheduled, Duration inHowLong) { + rescheduleMessage(ReActedMessage messageToBeRescheduled, Duration inHowLong) { ReActorRef sender = getSender(); return Try.of(() -> getReActorSystem().getSystemSchedulingService() .schedule(() -> getSelf().tell(sender, messageToBeRescheduled), @@ -160,31 +161,31 @@ public DeliveryStatus reply(ReActorRef sender, Serializable anyPayload) { } /** - * Reply sending a message to the sender of the last message processed by this reactor using {@link ReActorRef#apublish(Serializable)} + * Reply sending a message to the sender of the last message processed by this reactor using {@link ReActorRef#apublish(ReActedMessage)} * @param anyPayload payload to be sent - * @return a {@link CompletionStage}<{@link Try}<{@link DeliveryStatus}>> returned by {@link ReActorRef#apublish(ReActorRef, Serializable)} + * @return a {@link CompletionStage}<{@link Try}<{@link DeliveryStatus}>> returned by {@link ReActorRef#apublish(ReActorRef, ReActedMessage)} */ - public CompletionStage areply(Serializable anyPayload) { + public CompletionStage areply(ReActedMessage anyPayload) { return getSender().apublish(anyPayload); } /** - * {@link ReActorRef#publish(Serializable)} to the current reactor the specified message setting itself as sender for the message + * {@link ReActorRef#publish(ReActedMessage)} to the current reactor the specified message setting itself as sender for the message * @param anyPayload message that should be self-sent * @return A {@link DeliveryStatus} * complete */ - public DeliveryStatus selfPublish(Serializable anyPayload) { + public DeliveryStatus selfPublish(ReActedMessage anyPayload) { return getSelf().publish(getSelf(), anyPayload); } /** - * {@link ReActorRef#tell(Serializable)} to the current reactor the specified message setting itself as sender for the message + * {@link ReActorRef#tell(ReActedMessage)} to the current reactor the specified message setting itself as sender for the message * @param anyPayload message that should be self-sent * @return A {@link DeliveryStatus} * complete */ - public DeliveryStatus selfTell(Serializable anyPayload) { + public DeliveryStatus selfTell(ReActedMessage anyPayload) { return getSelf().tell(getSelf(), anyPayload); } @@ -282,7 +283,7 @@ public void logDebug(String descriptionFormat, Serializable ...args) { public void reAct(Message msg) { this.lastMsgSender = msg.getSender(); - BiConsumer reAction = reActions.getReAction(msg.getPayload()); + BiConsumer reAction = reActions.getReAction(msg.getPayload()); reAction.accept(this, msg.getPayload()); } diff --git a/core/src/main/java/io/reacted/core/reactorsystem/ReActorCtxConfig.java b/core/src/main/java/io/reacted/core/reactorsystem/ReActorCtxConfig.java index d132eedf..77343476 100644 --- a/core/src/main/java/io/reacted/core/reactorsystem/ReActorCtxConfig.java +++ b/core/src/main/java/io/reacted/core/reactorsystem/ReActorCtxConfig.java @@ -10,15 +10,15 @@ import io.reacted.core.mailboxes.MailBox; import io.reacted.core.runtime.Dispatcher; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; -import java.io.Serializable; import java.util.Objects; import java.util.Set; @NonNullByDefault public class ReActorCtxConfig { - private final Set> subscribedTypes; + private final Set> subscribedTypes; private final Dispatcher dispatcher; private final MailBox mailBox; @@ -28,7 +28,7 @@ private ReActorCtxConfig(Builder actorCtxConfigBuilder) { this.dispatcher = Objects.requireNonNull(actorCtxConfigBuilder.dispatcher); } - Set> getSubscribedTypes() { return subscribedTypes; } + Set> getSubscribedTypes() { return subscribedTypes; } Dispatcher getDispatcher() { return dispatcher; } @@ -36,11 +36,11 @@ private ReActorCtxConfig(Builder actorCtxConfigBuilder) { @SuppressWarnings("NotNullFieldNotInitialized") public static class Builder { - private Set> subscribedTypes; + private Set> subscribedTypes; private MailBox reactorMailbox; private Dispatcher dispatcher; - public final Builder setSubscribedTypes(Set> subscribedTypes) { + public final Builder setSubscribedTypes(Set> subscribedTypes) { this.subscribedTypes = subscribedTypes; return this; } diff --git a/core/src/main/java/io/reacted/core/reactorsystem/ReActorRef.java b/core/src/main/java/io/reacted/core/reactorsystem/ReActorRef.java index fcce4aa9..72c5f8e0 100644 --- a/core/src/main/java/io/reacted/core/reactorsystem/ReActorRef.java +++ b/core/src/main/java/io/reacted/core/reactorsystem/ReActorRef.java @@ -13,20 +13,19 @@ import io.reacted.core.messages.reactors.DeliveryStatus; import io.reacted.core.reactors.ReActorId; import io.reacted.core.reactors.systemreactors.Ask; +import io.reacted.core.serialization.Deserializer; +import io.reacted.core.serialization.ReActedMessage; +import io.reacted.core.serialization.Serializer; import io.reacted.patterns.NonNullByDefault; -import java.io.Externalizable; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; + import java.io.Serial; -import java.io.Serializable; import java.time.Duration; import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; @NonNullByDefault -public final class ReActorRef implements Externalizable { +public final class ReActorRef implements ReActedMessage { public static final ReActorRef NO_REACTOR_REF = new ReActorRef(ReActorId.NO_REACTOR_ID, NullReActorSystemRef.NULL_REACTOR_SYSTEM_REF); public static final int NO_REACTOR_REF_MARKER = 1; @@ -82,12 +81,12 @@ public String toString() { * Sends a message to this ReActor using {@link ReActorSystem#getSystemSink()} as source * * @param messagePayload payload - * @param Any {@link Serializable} object + * @param Any {@link ReActedMessage} object * @return A {@link DeliveryStatus} representing the outcome of the operation. Different drivers * may offer different guarantees regarding the returned {@link DeliveryStatus}. The common * baseline for this method is providing delivery guarantee to the local driver bus */ - public DeliveryStatus publish(PayloadT messagePayload) { + public DeliveryStatus publish(PayloadT messagePayload) { return reActorSystemRef.publish(ReActorRef.NO_REACTOR_REF, this, Objects.requireNonNull(messagePayload)); } @@ -97,12 +96,12 @@ public DeliveryStatus publish(PayloadT messagePa * * @param msgSender source of the message * @param messagePayload payload - * @param Any {@link Serializable} object + * @param Any {@link ReActedMessage} object * @return A {@link DeliveryStatus} representing the outcome of the operation. Different drivers * may offer different guarantees regarding the returned {@link DeliveryStatus}. The common * baseline for this method is providing delivery guarantee to the local driver bus */ - public DeliveryStatus publish(ReActorRef msgSender, + public DeliveryStatus publish(ReActorRef msgSender, PayloadT messagePayload) { return reActorSystemRef.publish(Objects.requireNonNull(msgSender), this, Objects.requireNonNull(messagePayload)); @@ -114,12 +113,12 @@ public DeliveryStatus publish(ReActorRef msgSend * * @param msgSender source of the message * @param messagePayload payload - * @param Any {@link Serializable} object + * @param Any {@link ReActedMessage} object * @return A {@link DeliveryStatus} representing the outcome of the operation. Different drivers * may offer different guarantees regarding the returned {@link DeliveryStatus}. The common * baseline for this method is providing delivery guarantee to the local driver bus */ - public DeliveryStatus tell(ReActorRef msgSender, PayloadT messagePayload) { + public DeliveryStatus tell(ReActorRef msgSender, PayloadT messagePayload) { return reActorSystemRef.tell(Objects.requireNonNull(msgSender), this, Objects.requireNonNull(messagePayload)); } @@ -130,12 +129,12 @@ public DeliveryStatus tell(ReActorRef msgSender, * @see io.reacted.core.typedsubscriptions.TypedSubscription * * @param messagePayload payload - * @param Any {@link Serializable} object + * @param Any {@link ReActedMessage} object * @return A {@link DeliveryStatus} representing the outcome of the operation. Different drivers * may offer different guarantees regarding the returned {@link DeliveryStatus}. The common * baseline for this method is providing delivery guarantee to the local driver bus */ - public DeliveryStatus tell(PayloadT messagePayload) { + public DeliveryStatus tell(PayloadT messagePayload) { return reActorSystemRef.tell(ReActorRef.NO_REACTOR_REF, this, Objects.requireNonNull(messagePayload)); } @@ -147,11 +146,11 @@ public DeliveryStatus tell(PayloadT messagePayl * * @param msgSender message source * @param messagePayload message payload - * @param Any {@link Serializable} object + * @param Any {@link ReActedMessage} object * @return A {@link CompletionStage} that is going to be completed when an ack from the destination reactor system * is received containing the outcome of the delivery of the message into the target actor mailbox */ - public CompletionStage atell(ReActorRef msgSender, PayloadT messagePayload) { + public CompletionStage atell(ReActorRef msgSender, PayloadT messagePayload) { return reActorSystemRef.atell(Objects.requireNonNull(msgSender), this, AckingPolicy.ONE_TO_ONE, Objects.requireNonNull(messagePayload)); } @@ -161,11 +160,11 @@ public CompletionStage atell(ReA * mailbox. The sender of the message is going to be the system sink * * @param messagePayload message payload - * @param Any {@link Serializable} object + * @param Any {@link ReActedMessage} object * @return A completable future that is going to be completed when an ack from the destination reactor system * is received containing the outcome of the delivery of the message into the target actor mailbox */ - public CompletionStage apublish(PayloadT messagePayload) { + public CompletionStage apublish(PayloadT messagePayload) { return reActorSystemRef.apublish(ReActorRef.NO_REACTOR_REF, this, AckingPolicy.ONE_TO_ONE, Objects.requireNonNull(messagePayload)); } @@ -176,11 +175,11 @@ public CompletionStage apublish( * * @param msgSender message source * @param messagePayload message payload - * @param Any {@link Serializable} object + * @param Any {@link ReActedMessage} object * @return A completable future that is going to be completed when an ack from the destination reactor system * is received containing the outcome of the delivery of the message into the target actor mailbox */ - public CompletionStage apublish(ReActorRef msgSender, + public CompletionStage apublish(ReActorRef msgSender, PayloadT messagePayload) { return reActorSystemRef.apublish(Objects.requireNonNull(msgSender), this, AckingPolicy.ONE_TO_ONE, Objects.requireNonNull(messagePayload)); @@ -193,12 +192,12 @@ public CompletionStage apublish( * @param expectedReply expected message type as reply to this request * @param requestName name of the request. It must be unique reactor name in the reactor system as long as this * ask is alive - * @param Any {@link Serializable} object - * @param Any {@link Serializable} object + * @param Any {@link ReActedMessage} object + * @param Any {@link ReActedMessage} object * @return A {@link CompletionStage} that is going to be completed once an answer for the request has been received. * On failure, the {@link CompletionStage} will be a failed {@link CompletionStage} contain the cause of the failure */ - public + public CompletionStage ask(RequestT request, Class expectedReply, String requestName) { return ask(getReActorSystemRef().getBackingDriver().getLocalReActorSystem(), this, @@ -214,12 +213,12 @@ CompletionStage ask(RequestT request, Class expectedReply, * @param expireTimeout mark this request as completed and failed after this timeout * @param requestName name of the request. It must be unique reactor name in the reactor system as long as this * ask is alive - * @param Any {@link Serializable} object - * @param Any {@link Serializable} object + * @param Any {@link ReActedMessage} object + * @param Any {@link ReActedMessage} object * @return A {@link CompletionStage} that is going to be completed once an answer for the request has been received. * On failure, the {@link CompletionStage} will be a failed {@link CompletionStage} contain the cause of the failure */ - public + public CompletionStage ask(RequestT request, Class expectedReply, Duration expireTimeout, String requestName) { return ask(Objects.requireNonNull(getReActorSystemRef().getBackingDriver().getLocalReActorSystem()), @@ -230,30 +229,30 @@ CompletionStage ask(RequestT request, Class expectedReply, Durat public ReActorId getReActorId() { return reActorId; } @Override - public void writeExternal(ObjectOutput out) throws IOException { + public void encode(Serializer serializer) { if (this == NO_REACTOR_REF) { - out.writeInt(NO_REACTOR_REF_MARKER); + serializer.put(NO_REACTOR_REF_MARKER); } else { - out.writeInt(COMMON_REACTOR_REF_MARKER); - getReActorId().writeExternal(out); - getReActorSystemRef().writeExternal(out); + serializer.put(COMMON_REACTOR_REF_MARKER); + getReActorId().encode(serializer); + getReActorSystemRef().encode(serializer); } } @Override - public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { - if (in.readInt() == COMMON_REACTOR_REF_MARKER) { + public void decode(Deserializer deserializer) { + if (deserializer.getInt() == COMMON_REACTOR_REF_MARKER) { ReActorId receivedReActorId = new ReActorId(); - receivedReActorId.readExternal(in); + receivedReActorId.decode(deserializer); setReActorId(receivedReActorId); ReActorSystemRef receivedReActorSystemRef = new ReActorSystemRef(); - receivedReActorSystemRef.readExternal(in); + receivedReActorSystemRef.decode(deserializer); setReActorSystemRef(receivedReActorSystemRef); setHashCode(Objects.hash(getReActorId(), getReActorSystemRef())); } } - private static + private static CompletionStage ask(ReActorSystem localReActorSystem, ReActorRef target, RequestT request, Class expectedReplyType, Duration askTimeout, String requestName) { CompletableFuture returnValue = new CompletableFuture<>(); diff --git a/core/src/main/java/io/reacted/core/reactorsystem/ReActorSystem.java b/core/src/main/java/io/reacted/core/reactorsystem/ReActorSystem.java index aa9702bb..a1ac6b7d 100644 --- a/core/src/main/java/io/reacted/core/reactorsystem/ReActorSystem.java +++ b/core/src/main/java/io/reacted/core/reactorsystem/ReActorSystem.java @@ -50,12 +50,17 @@ import io.reacted.core.reactors.systemreactors.SystemLogger; import io.reacted.core.reactors.systemreactors.SystemMonitor; import io.reacted.core.runtime.Dispatcher; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.core.services.Service; import io.reacted.core.typedsubscriptions.SubscriptionsManager; import io.reacted.core.typedsubscriptions.TypedSubscription; import io.reacted.core.typedsubscriptions.TypedSubscriptionsManager; import io.reacted.patterns.NonNullByDefault; import io.reacted.patterns.Try; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.Nullable; import java.io.Serializable; import java.time.Duration; import java.util.Arrays; @@ -80,9 +85,6 @@ import java.util.function.Predicate; import java.util.stream.Collectors; import java.util.stream.Stream; -import javax.annotation.Nullable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; @NonNullByDefault @@ -93,7 +95,7 @@ public class ReActorSystem { // to wait indefinitely for an answer from local resources private static final Duration SERVICE_DISCOVERY_TIMEOUT = Duration.ofSeconds(10); private static final Logger LOGGER = LoggerFactory.getLogger(ReActorSystem.class); - private static final Serializable REACTOR_INIT = new ReActorInit(); + private static final ReActedMessage REACTOR_INIT = new ReActorInit(); private static final DispatcherConfig SYSTEM_DISPATCHER_CONFIG = DispatcherConfig.newBuilder() .setDispatcherName( Dispatcher.DEFAULT_DISPATCHER_NAME) @@ -262,7 +264,7 @@ public void logError(String errorDescription, Serializable ...args) { public void logDebug(String format, Serializable ...args) { if (getSystemLogger().publish(getSystemSink(), new ReActedDebug(Objects.requireNonNull(format), - Objects.requireNonNull(args))).isNotSent()) { + Objects.requireNonNull(args))).isNotSent()) { LOGGER.error("Unable to log {}", format); LOGGER.debug(format, (Object) args); } @@ -283,11 +285,11 @@ public void logInfo(String format, Serializable ...args) { } } - public DeliveryStatus toDeadLetters(Serializable payload) { + public DeliveryStatus toDeadLetters(ReActedMessage payload) { return toDeadLetters(ReActorRef.NO_REACTOR_REF, payload); } - public DeliveryStatus toDeadLetters(ReActorRef sender, Serializable payload) { + public DeliveryStatus toDeadLetters(ReActorRef sender, ReActedMessage payload) { DeliveryStatus deliveryStatus = Objects.requireNonNull(systemDeadLetters) .tell(sender, new DeadMessage(payload)); if (deliveryStatus.isNotSent()) { @@ -580,10 +582,10 @@ Try spawnService(ServiceCfgT serviceConfig, ReActorRef father) { * Sends a message to all the local subscribers for the message type * @param msgSender A {@link ReActorRef} defining the sender of this message * @param payload The payload that should be broadcasted - * @param Any {@link Serializable} object + * @param Any {@link ReActedMessage} object * @return A {@link CompletionStage} that is going to be completed when the message is sent */ - public DeliveryStatus + public DeliveryStatus broadcastToLocalSubscribers(ReActorRef msgSender, PayLoadT payload) { return getSystemSink().publish(Objects.requireNonNull(msgSender), Objects.requireNonNull(payload)); } @@ -591,9 +593,9 @@ Try spawnService(ServiceCfgT serviceConfig, ReActorRef father) { /** * Sends a message to all the remote subscribers for the message type * @param payload The payload that should be broadcasted - * @param Any {@link Serializable} object + * @param Any {@link ReActedMessage} object */ - public void broadcastToRemoteSubscribers(PayLoadT payload) { + public void broadcastToRemoteSubscribers(PayLoadT payload) { broadcastToRemoteSubscribers(ReActorRef.NO_REACTOR_REF, payload); } @@ -601,9 +603,9 @@ public void broadcastToRemoteSubscribers(PayLoad * Sends a message to all the remote subscribers for the message type * @param msgSender A {@link ReActorRef} defining the sender of this message * @param payload The payload that should be broadcasted - * @param Any {@link Serializable} object + * @param Any {@link ReActedMessage} object */ - public void broadcastToRemoteSubscribers(ReActorRef msgSender, PayLoadT payload) { + public void broadcastToRemoteSubscribers(ReActorRef msgSender, PayLoadT payload) { gatesCentralizedManager.findAllGates().stream() .filter(Predicate.not(getLoopback()::equals)) .map(remoteGate -> new ReActorRef(ReActorId.NO_REACTOR_ID, remoteGate)) @@ -615,9 +617,9 @@ public void broadcastToRemoteSubscribers(ReActor * Sends a message to all the remote subscribers for the message type * @param channelId {@link ChannelId} towards the message should be broadcasted to * @param payload The payload that should be broadcasted - * @param Any {@link Serializable} object + * @param Any {@link ReActedMessage} object */ - public void broadcastToAllSubscribers(ChannelId channelId, PayLoadT payload) { + public void broadcastToAllSubscribers(ChannelId channelId, PayLoadT payload) { broadcastToAllSubscribers(channelId, getSystemSink(), payload); } @@ -626,9 +628,9 @@ public void broadcastToAllSubscribers(ChannelId * @param channelId {@link ChannelId} towards the message should be broadcasted to * @param msgSender A {@link ReActorRef} defining the sender of this message * @param payload The payload that should be broadcasted - * @param Any {@link Serializable} object + * @param Any {@link ReActedMessage} object */ - public void broadcastToAllSubscribers(ChannelId channelId, ReActorRef msgSender, + public void broadcastToAllSubscribers(ChannelId channelId, ReActorRef msgSender, PayLoadT payload) { gatesCentralizedManager.findAllGates(channelId).stream() .map(remoteGate -> new ReActorRef(ReActorId.NO_REACTOR_ID, remoteGate)) diff --git a/core/src/main/java/io/reacted/core/reactorsystem/ReActorSystemId.java b/core/src/main/java/io/reacted/core/reactorsystem/ReActorSystemId.java index 3101f1bc..7a4eba6e 100644 --- a/core/src/main/java/io/reacted/core/reactorsystem/ReActorSystemId.java +++ b/core/src/main/java/io/reacted/core/reactorsystem/ReActorSystemId.java @@ -10,19 +10,18 @@ import io.reacted.core.messages.SerializationUtils; import io.reacted.core.reactors.ReActorId; +import io.reacted.core.serialization.Deserializer; +import io.reacted.core.serialization.ReActedMessage; +import io.reacted.core.serialization.Serializer; -import java.io.Externalizable; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; +import javax.annotation.concurrent.Immutable; import java.io.Serial; import java.nio.charset.StandardCharsets; import java.util.Objects; import java.util.UUID; -import javax.annotation.concurrent.Immutable; @Immutable -public class ReActorSystemId implements Externalizable { +public class ReActorSystemId implements ReActedMessage { public static final String NO_REACTORSYSTEM_ID_NAME = "NO_REACTORSYSTEM_ID"; public static final int NO_REACTORSYSTEM_ID_MARKER = 1; public static final int COMMON_REACTORSYSTEM_ID_MARKER = 0; @@ -60,21 +59,24 @@ public ReActorSystemId(String reActorSystemName) { public int getHashCode() { return hashCode(); } public UUID getReActorSystemUUID() { return reActorSystemUUID; } + @Override - public void writeExternal(ObjectOutput out) throws IOException { + public void encode(Serializer serializer) { if (this == NO_REACTORSYSTEM_ID) { - out.writeInt(NO_REACTORSYSTEM_ID_MARKER); + serializer.put(NO_REACTORSYSTEM_ID_MARKER); } else { - out.writeInt(COMMON_REACTORSYSTEM_ID_MARKER); - out.writeObject(reActorSystemUUID); - out.writeObject(reActorSystemName); + serializer.put(COMMON_REACTORSYSTEM_ID_MARKER); + serializer.put(reActorSystemUUID.getMostSignificantBits()); + serializer.put(reActorSystemUUID.getLeastSignificantBits()); + serializer.put(reActorSystemName); } } + @Override - public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { - if (in.readInt() == COMMON_REACTORSYSTEM_ID_MARKER) { - setReActorSystemUUID((UUID) in.readObject()) - .setReActorSystemName((String) (in.readObject())); + public void decode(Deserializer deserializer) { + if (deserializer.getInt() == COMMON_REACTORSYSTEM_ID_MARKER) { + setReActorSystemUUID(new UUID(deserializer.getLong(), deserializer.getLong())) + .setReActorSystemName(deserializer.getString()); setHashCode(Objects.hash(reActorSystemUUID, reActorSystemName)); } } diff --git a/core/src/main/java/io/reacted/core/reactorsystem/ReActorSystemRef.java b/core/src/main/java/io/reacted/core/reactorsystem/ReActorSystemRef.java index 4f70b6a1..675b0992 100644 --- a/core/src/main/java/io/reacted/core/reactorsystem/ReActorSystemRef.java +++ b/core/src/main/java/io/reacted/core/reactorsystem/ReActorSystemRef.java @@ -17,22 +17,21 @@ import io.reacted.core.messages.AckingPolicy; import io.reacted.core.messages.SerializationUtils; import io.reacted.core.messages.reactors.DeliveryStatus; -import java.io.Externalizable; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; +import io.reacted.core.serialization.Deserializer; +import io.reacted.core.serialization.ReActedMessage; +import io.reacted.core.serialization.Serializer; + +import javax.annotation.Nullable; import java.io.Serial; -import java.io.Serializable; import java.util.Objects; import java.util.Properties; import java.util.concurrent.CompletionStage; -import javax.annotation.Nullable; /** * ReActorSystem abstraction. Through this interface we can perform operations on the contained reactors, * regardless if they are local or remote */ -public class ReActorSystemRef implements Externalizable { +public class ReActorSystemRef implements ReActedMessage { @Serial private static final long serialVersionUID = 1; private static final long REACTORSYSTEM_ID_OFFSET = SerializationUtils.getFieldOffset(ReActorSystemRef.class, @@ -73,23 +72,23 @@ public ReActorSystemRef(ReActorSystemDriver> this.gateProperties = gateProperties; } - + DeliveryStatus publish(ReActorRef src, ReActorRef dst, PayloadT message) { return backingDriver.publish(src, dst, message); } - + DeliveryStatus tell(ReActorRef src, ReActorRef dst, PayloadT message) { return backingDriver.tell(src, dst, message); } - + CompletionStage apublish(ReActorRef src, ReActorRef dst, AckingPolicy ackingPolicy, PayloadT message) { return backingDriver.apublish(src, dst, ackingPolicy, message); } - + CompletionStage atell(ReActorRef src, ReActorRef dst, AckingPolicy ackingPolicy, PayloadT message) { return backingDriver.atell(src, dst, ackingPolicy, message); @@ -122,9 +121,19 @@ public int hashCode() { } @Override - public void writeExternal(ObjectOutput out) throws IOException { - Objects.requireNonNull(reActorSystemId).writeExternal(out); - channelId.writeExternal(out); + public void encode(Serializer serializer) { + reActorSystemId.encode(serializer); + channelId.encode(serializer); + } + + @Override + public void decode(Deserializer deserializer) { + ReActorSystemId reActorSystemId = new ReActorSystemId(); + ReActorSystemRef currentRef = this; + reActorSystemId.decode(deserializer); + ChannelId sourceChannelId = new ChannelId(); + sourceChannelId.decode(deserializer); + setGateForReActorSystem(currentRef, reActorSystemId, sourceChannelId, ReActorSystemDriver.getDriverCtx()); } @Override @@ -137,16 +146,6 @@ public String toString() { '}'; } - @Override - public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { - ReActorSystemId reActorSystemId = new ReActorSystemId(); - ReActorSystemRef currentRef = this; - reActorSystemId.readExternal(in); - ChannelId sourceChannelId = new ChannelId(); - sourceChannelId.readExternal(in); - setGateForReActorSystem(currentRef, reActorSystemId, sourceChannelId, ReActorSystemDriver.getDriverCtx()); - } - public void setReActorSystemId(ReActorSystemId reActorSystemId) { SerializationUtils.setObjectField(this, REACTORSYSTEM_ID_OFFSET, reActorSystemId); } diff --git a/core/src/main/java/io/reacted/core/serialization/Deserializer.java b/core/src/main/java/io/reacted/core/serialization/Deserializer.java new file mode 100644 index 00000000..2047f3f0 --- /dev/null +++ b/core/src/main/java/io/reacted/core/serialization/Deserializer.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2022 , [ pierre@reacted.io ] + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + +package io.reacted.core.serialization; + +import java.io.Serializable; + +public interface Deserializer { + long getLong(); + long[] getLongs(); + int getInt(); + + int[] getInts(); + String getString(); + byte getByte(); + byte[] getBytes(); + Serializable getObject(); +} diff --git a/core/src/main/java/io/reacted/core/serialization/ReActedMessage.java b/core/src/main/java/io/reacted/core/serialization/ReActedMessage.java new file mode 100644 index 00000000..2e734367 --- /dev/null +++ b/core/src/main/java/io/reacted/core/serialization/ReActedMessage.java @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2022 , [ pierre@reacted.io ] + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + +package io.reacted.core.serialization; + +import java.io.Serializable; + +public interface ReActedMessage extends Serializable { + default Class getMessageType() { + return this.getClass(); + } + default void encode(Serializer serializer) { } + default void decode(Deserializer deserializer) { } + static ReActedMessage of(String payload) { + var msg = new StringMessage(); + msg.payload = payload; + return msg; + } + + static ReActedMessage of(int payload) { + var msg = new IntMessage(); + msg.payload = payload; + return msg; + } + + static ReActedMessage of(long payload) { + var msg = new LongMessage(); + msg.payload = payload; + return msg; + } + + static ReActedMessage of(byte[] payload) { + var msg = new ByteArrayMessage(); + msg.payload = payload; + return msg; + } + + private static ReActedMessage of(Throwable payload) { + var msg = new ThrowableMessage(); + msg.value = payload; + return msg; + } + + class ByteArrayMessage implements ReActedMessage { + byte[] payload = null; + @Override + public void encode(Serializer serializer) { + serializer.put(payload); + } + + @Override + public void decode(Deserializer deserializer) { + this.payload = deserializer.getBytes(); + } + } + class LongMessage implements ReActedMessage { + private Long payload = null; + public Long getPayload() { return payload; } + + public void setPayload(long payload) { this.payload = payload; } + @Override + public void encode(Serializer serializer) { + serializer.put(payload); + } + @Override + public void decode(Deserializer deserializer) { + this.payload = deserializer.getLong(); + } + } + + class LongsMessage implements ReActedMessage { + private long[] payload = null; + + public long[] getPayload() { return payload; } + @Override + public void encode(Serializer serializer) { + serializer.put(payload); + } + @Override + public void decode(Deserializer deserializer) { + this.payload = deserializer.getLongs(); + } + } + + class IntMessage implements ReActedMessage { + private Integer payload = null; + @Override + public void encode(Serializer serializer) { + serializer.put(payload); + } + @Override + public void decode(Deserializer deserializer) { + this.payload = deserializer.getInt(); + } + } + + class IntsMessage implements ReActedMessage { + private int[] payload = null; + @Override + public void encode(Serializer serializer) { + serializer.put(payload); + } + @Override + public void decode(Deserializer deserializer) { + this.payload = deserializer.getInts(); + } + } + + class StringMessage implements ReActedMessage { + protected String payload = null; + @Override + public void encode(Serializer serializer) { + serializer.put(payload); + } + @Override + public void decode(Deserializer deserializer) { + this.payload = deserializer.getString(); + } + } + + class ThrowableMessage extends SerializableMessage { } + class SerializableMessage implements ReActedMessage { + Serializable value = null; + @Override + public void encode(Serializer serializer) { + serializer.putObject(value); + } + @Override + public void decode(Deserializer deserializer) { + this.value = deserializer.getObject(); + } + } +} diff --git a/core/src/main/java/io/reacted/core/serialization/Serializer.java b/core/src/main/java/io/reacted/core/serialization/Serializer.java new file mode 100644 index 00000000..0a1b7df7 --- /dev/null +++ b/core/src/main/java/io/reacted/core/serialization/Serializer.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022 , [ pierre@reacted.io ] + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + +package io.reacted.core.serialization; + +import java.io.Serializable; + +public interface Serializer { + void putLong(long value); + void putLongs(long[] value); + void putInt(int value); + + void putInts(int[] value); + void putString(String value); + void putByte(byte value); + void putBytes(byte[] value); + + void putObject(Serializable value); + default void put(String value) { putString(value);} + default void put(long value) { putLong(value); } + default void put(int value) { putInt(value); } + default void put(byte value) { putByte(value); } + default void put(byte[] value) { putBytes(value); } + + default void put(int[] value) { putInts(value);} + default void put(long[] value) { putLongs(value); } +} diff --git a/core/src/main/java/io/reacted/core/services/LoadBalancingPolicies.java b/core/src/main/java/io/reacted/core/services/LoadBalancingPolicies.java index f99dfe36..ac761654 100644 --- a/core/src/main/java/io/reacted/core/services/LoadBalancingPolicies.java +++ b/core/src/main/java/io/reacted/core/services/LoadBalancingPolicies.java @@ -12,12 +12,12 @@ import io.reacted.core.config.reactors.ReActorServiceConfig.Builder; import io.reacted.core.reactorsystem.ReActorContext; import io.reacted.core.reactorsystem.ReActorRef; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; -import java.io.Serializable; import java.util.List; import java.util.function.ToIntFunction; @@ -31,7 +31,7 @@ public final class LoadBalancingPolicies { ServiceConfigT extends ReActorServiceConfig> ReActorRef selectRoutee(@Nonnull ReActorContext routerCtx, @Nonnull Service thisService, - long msgNum, @Nonnull Serializable message) { + long msgNum, @Nonnull ReActedMessage message) { List routees = thisService.getRouteesMap(); if (routees.size() == 0) { return null; @@ -51,7 +51,7 @@ ReActorRef selectRoutee(@Nonnull ReActorContext routerCtx, ServiceConfigT extends ReActorServiceConfig> ReActorRef selectRoutee(@Nonnull ReActorContext routerCtx, @Nonnull Service thisService, - long msgNum, @Nonnull Serializable message) { + long msgNum, @Nonnull ReActedMessage message) { ReActorRef minLoadRoutee = null; long minLoad = Long.MAX_VALUE; for (ReActorRef routee : routerCtx.getChildren()) { @@ -66,7 +66,7 @@ ReActorRef selectRoutee(@Nonnull ReActorContext routerCtx, }; private LoadBalancingPolicies() { /* No implementation required */ } - public static LoadBalancingPolicy partitionBy(ToIntFunction partitioner) { + public static LoadBalancingPolicy partitionBy(ToIntFunction partitioner) { return new LoadBalancingPolicy() { @Nullable @Override @@ -74,7 +74,7 @@ public static LoadBalancingPolicy partitionBy(ToIntFunction partit ServiceConfigT extends ReActorServiceConfig> ReActorRef selectRoutee(@Nonnull ReActorContext routerCtx, @Nonnull Service thisService, - long msgNum, @Nonnull Serializable message) { + long msgNum, @Nonnull ReActedMessage message) { ReActorRef routee = null; try { int partitionKey = Math.abs(partitioner.applyAsInt(message)); diff --git a/core/src/main/java/io/reacted/core/services/LoadBalancingPolicy.java b/core/src/main/java/io/reacted/core/services/LoadBalancingPolicy.java index c98cdb15..2cbef3d9 100644 --- a/core/src/main/java/io/reacted/core/services/LoadBalancingPolicy.java +++ b/core/src/main/java/io/reacted/core/services/LoadBalancingPolicy.java @@ -11,7 +11,8 @@ import io.reacted.core.config.reactors.ReActorServiceConfig; import io.reacted.core.reactorsystem.ReActorContext; import io.reacted.core.reactorsystem.ReActorRef; -import java.io.Serializable; +import io.reacted.core.serialization.ReActedMessage; + import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -21,5 +22,5 @@ public interface LoadBalancingPolicy { ServiceConfigT extends ReActorServiceConfig> ReActorRef selectRoutee(@Nonnull ReActorContext routerCtx, @Nonnull Service thisService, - long msgNum, @Nonnull Serializable message); + long msgNum, @Nonnull ReActedMessage message); } diff --git a/core/src/main/java/io/reacted/core/services/Service.java b/core/src/main/java/io/reacted/core/services/Service.java index 2b7642a0..1a51cc33 100644 --- a/core/src/main/java/io/reacted/core/services/Service.java +++ b/core/src/main/java/io/reacted/core/services/Service.java @@ -27,6 +27,7 @@ import io.reacted.core.reactors.ReActor; import io.reacted.core.reactorsystem.ReActorContext; import io.reacted.core.reactorsystem.ReActorRef; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.core.typedsubscriptions.TypedSubscription; import io.reacted.patterns.NonNullByDefault; import io.reacted.patterns.Try; @@ -35,7 +36,6 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; -import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -164,7 +164,7 @@ private void serviceDiscovery(ReActorContext ctx, ServiceDiscoveryRequest reques } private DeliveryStatus routeMessage(ReActorContext ctx, - Serializable newMessage) { + ReActedMessage newMessage) { ReActorRef routee = selectRoutee(ctx, ++msgReceived, newMessage); return routee != null ? routee.tell(ctx.getSender(), newMessage) @@ -173,7 +173,7 @@ private DeliveryStatus routeMessage(ReActorContext ctx, @Nullable private ReActorRef selectRoutee(ReActorContext routerCtx, long msgReceived, - Serializable message) { + ReActedMessage message) { return serviceConfig.getLoadBalancingPolicy() .selectRoutee(routerCtx, this, msgReceived, message); } @@ -227,7 +227,7 @@ private static DeliveryStatus sendPublicationRequest(ReActorContext ctx, .publish(ctx.getSelf(), new ServicePublicationRequest(ctx.getSelf(), serviceInfo)); } - private static + private static void requestNextMessage(ReActorContext ctx, PayloadT payload, BiFunction realCall) { if (realCall.apply(ctx, payload).isNotSent()) { @@ -238,13 +238,13 @@ void requestNextMessage(ReActorContext ctx, PayloadT payload, } //Messages required for the Service management logic cannot be backpressured - private static Set> getNonDelayedMessageTypes() { + private static Set> getNonDelayedMessageTypes() { return Set.of(ServiceRegistryNotAvailable.class, ServiceDiscoveryRequest.class, RouteeReSpawnRequest.class, ServicePublicationRequestError.class, SystemMonitorReport.class); } - public static class RouteeReSpawnRequest implements Serializable { + public static class RouteeReSpawnRequest implements ReActedMessage { private final ReActorRef deadRoutee; private final String routeeName; public RouteeReSpawnRequest(ReActorRef deadRoutee, String routeeName) { diff --git a/core/src/main/java/io/reacted/core/typedsubscriptions/SubscriptionsManager.java b/core/src/main/java/io/reacted/core/typedsubscriptions/SubscriptionsManager.java index 65db6905..2103e8a0 100644 --- a/core/src/main/java/io/reacted/core/typedsubscriptions/SubscriptionsManager.java +++ b/core/src/main/java/io/reacted/core/typedsubscriptions/SubscriptionsManager.java @@ -9,27 +9,28 @@ package io.reacted.core.typedsubscriptions; import io.reacted.core.reactorsystem.ReActorContext; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.core.typedsubscriptions.TypedSubscription.TypedSubscriptionPolicy; -import java.io.Serializable; -import java.util.List; + import javax.annotation.Nonnull; import javax.annotation.ParametersAreNonnullByDefault; +import java.util.List; @ParametersAreNonnullByDefault public interface SubscriptionsManager { - default void addSubscription(Class payloadType, + default void addSubscription(Class payloadType, TypedSubscriptionPolicy subscriptionPolicy, ReActorContext subscriber) { } - default void removeSubscription(Class payloadType, + default void removeSubscription(Class payloadType, TypedSubscriptionPolicy subscriptionPolicy, ReActorContext subscriber) { } - default boolean hasFullSubscribers(Class payloadType) { return false; } + default boolean hasFullSubscribers(Class payloadType) { return false; } @Nonnull - default List getLocalSubscribers(Class payloadType) { + default List getLocalSubscribers(Class payloadType) { return List.of(); } } diff --git a/core/src/main/java/io/reacted/core/typedsubscriptions/TypedSubscription.java b/core/src/main/java/io/reacted/core/typedsubscriptions/TypedSubscription.java index b28b3202..2b547d76 100644 --- a/core/src/main/java/io/reacted/core/typedsubscriptions/TypedSubscription.java +++ b/core/src/main/java/io/reacted/core/typedsubscriptions/TypedSubscription.java @@ -9,10 +9,9 @@ package io.reacted.core.typedsubscriptions; import com.google.common.base.Objects; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; -import java.io.Serializable; - @NonNullByDefault public class TypedSubscription { public static final TypedSubscription[] NO_SUBSCRIPTIONS = new TypedSubscription[]{}; @@ -20,17 +19,17 @@ public class TypedSubscription { public static final TypedSubscriptionPolicy FULL = TypedSubscriptionPolicy.FULL; private final TypedSubscriptionPolicy typedSubscriptionPolicy; - private final Class payloadType; + private final Class payloadType; public TypedSubscription(TypedSubscriptionPolicy typedSubscriptionPolicy, - Class sniffedPayloadType) { + Class sniffedPayloadType) { this.typedSubscriptionPolicy = typedSubscriptionPolicy; this.payloadType = sniffedPayloadType; } public TypedSubscriptionPolicy getSubscriptionPolicy() { return typedSubscriptionPolicy; } - public Class getPayloadType() { return payloadType; } + public Class getPayloadType() { return payloadType; } @Override public boolean equals(Object o) { @@ -52,7 +51,7 @@ public enum TypedSubscriptionPolicy { public boolean isLocal() { return this != FULL; } public boolean isFull() { return this != LOCAL; } - public TypedSubscription forType(Class payloadType) { + public TypedSubscription forType(Class payloadType) { return new TypedSubscription(this, payloadType); } } diff --git a/core/src/main/java/io/reacted/core/typedsubscriptions/TypedSubscriptionsManager.java b/core/src/main/java/io/reacted/core/typedsubscriptions/TypedSubscriptionsManager.java index 3ca51f1f..2572b6f4 100644 --- a/core/src/main/java/io/reacted/core/typedsubscriptions/TypedSubscriptionsManager.java +++ b/core/src/main/java/io/reacted/core/typedsubscriptions/TypedSubscriptionsManager.java @@ -9,9 +9,10 @@ package io.reacted.core.typedsubscriptions; import io.reacted.core.reactorsystem.ReActorContext; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; -import java.io.Serializable; +import javax.annotation.Nonnull; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -22,17 +23,16 @@ import java.util.concurrent.atomic.AtomicLong; import java.util.stream.Collectors; import java.util.stream.Stream; -import javax.annotation.Nonnull; @NonNullByDefault public class TypedSubscriptionsManager implements SubscriptionsManager { - private final Map, SubscriptionBucket> typeToSubscriber; + private final Map, SubscriptionBucket> typeToSubscriber; public TypedSubscriptionsManager() { this.typeToSubscriber = new ConcurrentHashMap<>(5000, 0.5f); } @Override - public void addSubscription(@Nonnull Class payloadType, + public void addSubscription(@Nonnull Class payloadType, @Nonnull TypedSubscription.TypedSubscriptionPolicy subscriptionPolicy, @Nonnull ReActorContext subscriber) { var bucket = typeToSubscriber.computeIfAbsent(Objects.requireNonNull(payloadType), @@ -40,7 +40,7 @@ public void addSubscription(@Nonnull Class payloadType, bucket.addSubscriber(Objects.requireNonNull(subscriptionPolicy), Objects.requireNonNull(subscriber)); } @Override - public void removeSubscription(@Nonnull Class payloadType, + public void removeSubscription(@Nonnull Class payloadType, @Nonnull TypedSubscription.TypedSubscriptionPolicy subscriptionPolicy, @Nonnull ReActorContext subscriber) { var bucket = typeToSubscriber.get(Objects.requireNonNull(payloadType)); @@ -50,14 +50,14 @@ public void removeSubscription(@Nonnull Class payloadTyp } } @Override - public boolean hasFullSubscribers(@Nonnull Class payloadType) { + public boolean hasFullSubscribers(@Nonnull Class payloadType) { var bucket = typeToSubscriber.get(payloadType); return bucket != null && bucket.hasFullSubscriptions(); } @Nonnull @Override public List getLocalSubscribers( - @Nonnull Class payloadType) { + @Nonnull Class payloadType) { var localBucket = typeToSubscriber.get(payloadType); return localBucket != null ? localBucket.subscribers diff --git a/core/src/main/java/io/reacted/core/utils/ReActedUtils.java b/core/src/main/java/io/reacted/core/utils/ReActedUtils.java index ea32a163..5bf1288d 100644 --- a/core/src/main/java/io/reacted/core/utils/ReActedUtils.java +++ b/core/src/main/java/io/reacted/core/utils/ReActedUtils.java @@ -14,9 +14,9 @@ import io.reacted.core.reactorsystem.ReActorContext; import io.reacted.core.reactorsystem.ReActorRef; import io.reacted.core.reactorsystem.ReActorSystem; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; -import java.io.Serializable; import java.time.Duration; import java.util.Collection; import java.util.List; @@ -70,7 +70,7 @@ private ReActedUtils() { /* No Implementation required */ } return deliveryAttempt; } - public static + public static void rescheduleIf(BiConsumer realCall, BooleanSupplier shouldReschedule, Duration rescheduleInterval, ReActorContext ctx, PayloadT message) { diff --git a/core/src/test/java/io/reacted/core/CoreConstants.java b/core/src/test/java/io/reacted/core/CoreConstants.java index 942d70d5..fb07e548 100644 --- a/core/src/test/java/io/reacted/core/CoreConstants.java +++ b/core/src/test/java/io/reacted/core/CoreConstants.java @@ -8,11 +8,13 @@ package io.reacted.core; +import io.reacted.core.serialization.ReActedMessage; + public final class CoreConstants { public static final String DESTINATION = "DESTINATION"; public static final String DISPATCHER = "Dispatcher"; - public static final String DE_SERIALIZATION_SUCCESSFUL = "De/Serialization Successful!"; + public static final ReActedMessage DE_SERIALIZATION_SUCCESSFUL = ReActedMessage.of("De/Serialization Successful!"); public static final String HIGH_PRIORITY = "high priority"; diff --git a/core/src/test/java/io/reacted/core/drivers/system/LocalDriverTest.java b/core/src/test/java/io/reacted/core/drivers/system/LocalDriverTest.java index 799b9098..d474a153 100644 --- a/core/src/test/java/io/reacted/core/drivers/system/LocalDriverTest.java +++ b/core/src/test/java/io/reacted/core/drivers/system/LocalDriverTest.java @@ -8,8 +8,6 @@ package io.reacted.core.drivers.system; -import static org.mockito.Mockito.mock; - import io.reacted.core.CoreConstants; import io.reacted.core.ReactorHelper; import io.reacted.core.config.dispatchers.DispatcherConfig; @@ -25,11 +23,14 @@ import io.reacted.core.reactorsystem.ReActorRef; import io.reacted.core.reactorsystem.ReActorSystem; import io.reacted.core.runtime.Dispatcher; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.core.typedsubscriptions.TypedSubscription; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import static org.mockito.Mockito.mock; + class LocalDriverTest { static ReActorSystem reActorSystem; static UnboundedMbox unboundedMbox; @@ -57,7 +58,7 @@ static void prepareLocalDriver() throws Exception { localDriver = SystemLocalDrivers.DIRECT_COMMUNICATION; localDriver.initDriverLoop(reActorSystem); - TypedSubscription subscribedTypes = TypedSubscription.LOCAL.forType(String.class); + TypedSubscription subscribedTypes = TypedSubscription.LOCAL.forType(ReActedMessage.StringMessage.class); ReActorConfig reActorConfig = ReActorConfig.newBuilder() .setReActorName(CoreConstants.REACTOR_NAME) .setDispatcherName("Dispatcher") diff --git a/core/src/test/java/io/reacted/core/drivers/system/LoopbackDriverTest.java b/core/src/test/java/io/reacted/core/drivers/system/LoopbackDriverTest.java index 2f9a7be6..8e6de4ec 100644 --- a/core/src/test/java/io/reacted/core/drivers/system/LoopbackDriverTest.java +++ b/core/src/test/java/io/reacted/core/drivers/system/LoopbackDriverTest.java @@ -12,7 +12,6 @@ import io.reacted.core.config.dispatchers.DispatcherConfig; import io.reacted.core.config.drivers.ChannelDriverConfig; import io.reacted.core.config.reactors.ReActorConfig; -import io.reacted.core.typedsubscriptions.TypedSubscription; import io.reacted.core.config.reactorsystem.ReActorSystemConfig; import io.reacted.core.drivers.local.SystemLocalDrivers; import io.reacted.core.messages.AckingPolicy; @@ -20,6 +19,8 @@ import io.reacted.core.reactors.systemreactors.MagicTestReActor; import io.reacted.core.reactorsystem.ReActorRef; import io.reacted.core.reactorsystem.ReActorSystem; +import io.reacted.core.serialization.ReActedMessage; +import io.reacted.core.typedsubscriptions.TypedSubscription; import org.awaitility.Awaitility; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; @@ -57,13 +58,13 @@ void prepareEnvironment() throws Exception { ReActorConfig reActorConfig = ReActorConfig.newBuilder() .setReActorName("ReActorName") .setDispatcherName(testDispatcher) - .setTypedSubscriptions(TypedSubscription.LOCAL.forType(String.class)) + .setTypedSubscriptions(TypedSubscription.LOCAL.forType(ReActedMessage.StringMessage.class)) .build(); destReActorRef = reActorSystem.spawn(new MagicTestReActor(1, true, reActorConfig)) .orElseSneakyThrow(); message = Message.of(ReActorRef.NO_REACTOR_REF, destReActorRef, 0, reActorSystem.getLocalReActorSystemId(), - AckingPolicy.NONE, "payload"); + AckingPolicy.NONE, ReActedMessage.of("payload")); } @AfterEach diff --git a/core/src/test/java/io/reacted/core/mailboxes/PriorityMailboxTest.java b/core/src/test/java/io/reacted/core/mailboxes/PriorityMailboxTest.java index ed52ed02..5395accf 100644 --- a/core/src/test/java/io/reacted/core/mailboxes/PriorityMailboxTest.java +++ b/core/src/test/java/io/reacted/core/mailboxes/PriorityMailboxTest.java @@ -8,21 +8,21 @@ package io.reacted.core.mailboxes; -import static io.reacted.core.CoreConstants.PRIORITY_2; - import io.reacted.core.CoreConstants; import io.reacted.core.ReactorHelper; import io.reacted.core.messages.AckingPolicy; import io.reacted.core.messages.Message; import io.reacted.core.reactorsystem.ReActorRef; - -import java.util.Comparator; - +import io.reacted.core.serialization.ReActedMessage; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import java.util.Comparator; + +import static io.reacted.core.CoreConstants.PRIORITY_2; + class PriorityMailboxTest { PriorityMailbox priorityMailbox; @@ -36,7 +36,7 @@ static void prepareMessages() { testMsgDst = ReactorHelper.generateReactor(CoreConstants.DESTINATION); originalMsg = Message.of(testMsgSrc, testMsgDst, 0x31337, ReactorHelper.TEST_REACTOR_SYSTEM_ID, - AckingPolicy.NONE, "De/Serialization Successful!"); + AckingPolicy.NONE, ReActedMessage.of("De/Serialization Successful!")); } @BeforeEach @@ -91,7 +91,7 @@ void messageWithHigherPriorityProvidedFirstThenNormalPriorityApplied() { Message message4 = Message.of(highPrioMsgSrc2, highPrioMsgDest2, 0x31337, ReactorHelper.TEST_REACTOR_SYSTEM_ID, - AckingPolicy.NONE, CoreConstants.HIGH_PRIORITY); + AckingPolicy.NONE, ReActedMessage.of(CoreConstants.HIGH_PRIORITY)); priorityMailbox1.deliver(message1); priorityMailbox1.deliver(message2); @@ -106,7 +106,7 @@ void messageWithHigherPriorityProvidedFirstThenNormalPriorityApplied() { private Message createMessage(String payload) { return Message.of(testMsgSrc, testMsgDst, 0x31337, ReactorHelper.TEST_REACTOR_SYSTEM_ID, - AckingPolicy.NONE, payload); + AckingPolicy.NONE, ReActedMessage.of(payload)); } private final static Comparator PAYLOAD_COMPARATOR = diff --git a/core/src/test/java/io/reacted/core/mailboxes/UnboundedMboxTest.java b/core/src/test/java/io/reacted/core/mailboxes/UnboundedMboxTest.java index 556dc666..438b48b6 100644 --- a/core/src/test/java/io/reacted/core/mailboxes/UnboundedMboxTest.java +++ b/core/src/test/java/io/reacted/core/mailboxes/UnboundedMboxTest.java @@ -13,6 +13,7 @@ import io.reacted.core.messages.AckingPolicy; import io.reacted.core.messages.Message; import io.reacted.core.reactorsystem.ReActorRef; +import io.reacted.core.serialization.ReActedMessage; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; @@ -82,7 +83,8 @@ void getNextMessageReturnsMessagesInTheOrderTheyWereSent() { ReActorRef testMsgDst2 = ReactorHelper.generateReactor("destination2"); Message originalMsg2 = Message.of(testMsgSrc2, testMsgDst2, 0x31337, - ReactorHelper.TEST_REACTOR_SYSTEM_ID, AckingPolicy.NONE, "De/Serialization Successful!"); + ReactorHelper.TEST_REACTOR_SYSTEM_ID, AckingPolicy.NONE, + ReActedMessage.of("De/Serialization Successful!")); unboundedMbox.deliver(originalMsg2); Assertions.assertEquals(2, unboundedMbox.getMsgNum()); diff --git a/core/src/test/java/io/reacted/core/reactors/systemreactors/DeadLetterTest.java b/core/src/test/java/io/reacted/core/reactors/systemreactors/DeadLetterTest.java index b66a3908..ff866928 100644 --- a/core/src/test/java/io/reacted/core/reactors/systemreactors/DeadLetterTest.java +++ b/core/src/test/java/io/reacted/core/reactors/systemreactors/DeadLetterTest.java @@ -11,7 +11,6 @@ import io.reacted.core.CoreConstants; import io.reacted.core.config.dispatchers.DispatcherConfig; import io.reacted.core.config.reactors.ReActorConfig; -import io.reacted.core.typedsubscriptions.TypedSubscription; import io.reacted.core.config.reactorsystem.ReActorSystemConfig; import io.reacted.core.drivers.local.SystemLocalDrivers; import io.reacted.core.mailboxes.UnboundedMbox; @@ -19,10 +18,13 @@ import io.reacted.core.reactors.ReActorId; import io.reacted.core.reactorsystem.ReActorRef; import io.reacted.core.reactorsystem.ReActorSystem; -import java.util.concurrent.TimeUnit; +import io.reacted.core.serialization.ReActedMessage; +import io.reacted.core.typedsubscriptions.TypedSubscription; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import java.util.concurrent.TimeUnit; + class DeadLetterTest { @Test @@ -51,7 +53,8 @@ void messagesWithUnknownDestinationAreSentToDeadLetter() throws InterruptedExcep reActorSystem.spawn(new MagicTestReActor(2, true, reActorConfig)) .orElseSneakyThrow(); new ReActorRef(new ReActorId(ReActorId.NO_REACTOR_ID, CoreConstants.REACTOR_NAME), - reActorSystem.getLoopback()).publish(ReActorRef.NO_REACTOR_REF, "message"); + reActorSystem.getLoopback()).publish(ReActorRef.NO_REACTOR_REF, + ReActedMessage.of("message")); TimeUnit.SECONDS.sleep(1); Assertions.assertEquals(1, DeadLetter.RECEIVED.get()); } diff --git a/core/src/test/java/io/reacted/core/reactors/systemreactors/MagicTestReActor.java b/core/src/test/java/io/reacted/core/reactors/systemreactors/MagicTestReActor.java index 25d3855a..36805fd5 100644 --- a/core/src/test/java/io/reacted/core/reactors/systemreactors/MagicTestReActor.java +++ b/core/src/test/java/io/reacted/core/reactors/systemreactors/MagicTestReActor.java @@ -9,14 +9,14 @@ package io.reacted.core.reactors.systemreactors; import io.reacted.core.config.reactors.ReActorConfig; -import io.reacted.core.runtime.Dispatcher; -import io.reacted.core.typedsubscriptions.TypedSubscription; import io.reacted.core.mailboxes.UnboundedMbox; -import io.reacted.core.messages.Message; import io.reacted.core.messages.reactors.DeadMessage; import io.reacted.core.reactors.ReActions; import io.reacted.core.reactors.ReActor; import io.reacted.core.reactorsystem.ReActorContext; +import io.reacted.core.runtime.Dispatcher; +import io.reacted.core.serialization.ReActedMessage; +import io.reacted.core.typedsubscriptions.TypedSubscription; import javax.annotation.Nonnull; import java.util.concurrent.atomic.LongAdder; @@ -48,7 +48,7 @@ public MagicTestReActor(int maxMsgValue, boolean checkMsgOrdering, ReActorConfig this.reActorConfig = reActorConfig; this.reActions = ReActions.newBuilder() .reAct(DeadMessage.class, this::onDeadMessage) - .reAct(String.class, this::onMessage) + .reAct(ReActedMessage.StringMessage.class, this::onMessage) .build(); } @@ -58,7 +58,7 @@ public void onDeadMessage(ReActorContext ctx, DeadMessage deadMessage) { DEADMSG.increment(); } - public void onMessage(ReActorContext ctx, String message) { + public void onMessage(ReActorContext ctx, ReActedMessage.StringMessage message) { System.err.printf("Dispatcher used [%s] Payload: %s%n", ctx.getDispatcher().getName(), message); RECEIVED.increment(); diff --git a/core/src/test/java/io/reacted/core/reactorsystem/ReActorSystemTest.java b/core/src/test/java/io/reacted/core/reactorsystem/ReActorSystemTest.java index f8f35d69..9cb3f2c7 100644 --- a/core/src/test/java/io/reacted/core/reactorsystem/ReActorSystemTest.java +++ b/core/src/test/java/io/reacted/core/reactorsystem/ReActorSystemTest.java @@ -21,6 +21,7 @@ import io.reacted.core.reactors.ReActions; import io.reacted.core.reactors.ReActorId; import io.reacted.core.reactors.systemreactors.MagicTestReActor; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.core.typedsubscriptions.TypedSubscription; import io.reacted.patterns.Try; import org.awaitility.Awaitility; @@ -38,9 +39,6 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; - class ReActorSystemTest { private final Logger LOGGER = LoggerFactory.getLogger(ReActorSystemTest.class); private static final String DISPATCHER_NAME = "TestDispatcher"; @@ -180,7 +178,7 @@ void reActorSystemCanBroadcastToListeners() { ReActorConfig reActorConfig = ReActorConfig.newBuilder() .setReActorName("TR") .setDispatcherName("TestDispatcher") - .setTypedSubscriptions(TypedSubscription.LOCAL.forType(String.class)) + .setTypedSubscriptions(TypedSubscription.LOCAL.forType(ReActedMessage.StringMessage.class)) .build(); reActorSystem.spawn(new MagicTestReActor(1, true, reActorConfig)); diff --git a/drivers/src/main/java/io/reacted/drivers/channels/chroniclequeue/CQLocalDriver.java b/drivers/src/main/java/io/reacted/drivers/channels/chroniclequeue/CQLocalDriver.java index 2a6fc615..5002ed61 100644 --- a/drivers/src/main/java/io/reacted/drivers/channels/chroniclequeue/CQLocalDriver.java +++ b/drivers/src/main/java/io/reacted/drivers/channels/chroniclequeue/CQLocalDriver.java @@ -20,17 +20,10 @@ import io.reacted.core.reactorsystem.ReActorSystem; import io.reacted.core.reactorsystem.ReActorSystemId; import io.reacted.core.reactorsystem.ReActorSystemRef; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; import io.reacted.patterns.Try; import io.reacted.patterns.UnChecked; - -import java.io.Serializable; -import java.util.Objects; -import java.util.Properties; -import java.util.UUID; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import javax.annotation.Nullable; import net.openhft.chronicle.queue.ChronicleQueue; import net.openhft.chronicle.queue.ExcerptTailer; import net.openhft.chronicle.queue.RollCycles; @@ -40,6 +33,13 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.annotation.Nullable; +import java.util.Objects; +import java.util.Properties; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; + @NonNullByDefault public class CQLocalDriver extends LocalDriver { private static final Logger LOGGER = LoggerFactory.getLogger(CQLocalDriver.class); @@ -74,7 +74,7 @@ public ChannelId getChannelId() { public Properties getChannelProperties() { return getDriverConfig().getChannelProperties(); } @Override - public + public CompletionStage sendAsyncMessage(ReActorRef source, ReActorContext destinationCtx, ReActorRef destination, long seqNum, ReActorSystemId reActorSystemId, @@ -95,7 +95,7 @@ CompletionStage sendAsyncMessage(ReActorRef source, ReActorConte } @Override - public DeliveryStatus + public DeliveryStatus sendMessage(ReActorRef source, ReActorContext destinationCtx, ReActorRef destination, long seqNum, ReActorSystemId reActorSystemId, AckingPolicy ackingPolicy, PayloadT message) { try { @@ -138,7 +138,7 @@ private void readMessage(WireIn in, DriverCtx driverCtx) { readAckingPolicy(in), readPayload(in))); } - public static + public static void writeMessage(WireOut out, ReActorRef source, ReActorRef destination, long seqNum, ReActorSystemId localReActorSystemId, AckingPolicy ackingPolicy, PayloadT payload) { out.write("M") @@ -173,12 +173,12 @@ public static ReActorSystemRef readReActorSystemRef(WireIn in, DriverCtx ctx) { ReActorSystemRef.setGateForReActorSystem(reActorSystemRef, reActorSystemId, channelId, ctx); return reActorSystemRef; } - public static WireOut writePayload(WireOut wireOut, PayloadT payloadT) { + public static WireOut writePayload(WireOut wireOut, PayloadT payloadT) { return wireOut.write().object(payloadT); } @SuppressWarnings("unchecked") - public static PayloadT readPayload(WireIn in) { + public static PayloadT readPayload(WireIn in) { return (PayloadT)in.read().object(); } public static WireOut writeSequenceNumber(WireOut out, long sequenceNumber) { diff --git a/drivers/src/main/java/io/reacted/drivers/channels/chroniclequeue/CQRemoteDriver.java b/drivers/src/main/java/io/reacted/drivers/channels/chroniclequeue/CQRemoteDriver.java index 604ad17a..0b9a46b0 100644 --- a/drivers/src/main/java/io/reacted/drivers/channels/chroniclequeue/CQRemoteDriver.java +++ b/drivers/src/main/java/io/reacted/drivers/channels/chroniclequeue/CQRemoteDriver.java @@ -18,21 +18,21 @@ import io.reacted.core.reactorsystem.ReActorRef; import io.reacted.core.reactorsystem.ReActorSystem; import io.reacted.core.reactorsystem.ReActorSystemId; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; import io.reacted.patterns.Try; import io.reacted.patterns.UnChecked; - -import java.io.Serializable; -import java.util.Objects; -import java.util.Properties; -import java.util.concurrent.CompletableFuture; -import javax.annotation.Nullable; import net.openhft.chronicle.queue.ChronicleQueue; import net.openhft.chronicle.queue.ExcerptAppender; import net.openhft.chronicle.queue.ExcerptTailer; import net.openhft.chronicle.threads.Pauser; import net.openhft.chronicle.wire.WireIn; +import javax.annotation.Nullable; +import java.util.Objects; +import java.util.Properties; +import java.util.concurrent.CompletableFuture; + import static io.reacted.drivers.channels.chroniclequeue.CQLocalDriver.readAckingPolicy; import static io.reacted.drivers.channels.chroniclequeue.CQLocalDriver.readPayload; import static io.reacted.drivers.channels.chroniclequeue.CQLocalDriver.readReActorRef; @@ -89,7 +89,7 @@ public ChannelId getChannelId() { public Properties getChannelProperties() { return getDriverConfig().getChannelProperties(); } @Override - public + public DeliveryStatus sendMessage(ReActorRef source, ReActorContext destinationCtx, ReActorRef destination, long seqNum, ReActorSystemId reActorSystemId, AckingPolicy ackingPolicy, PayloadT message) { @@ -113,7 +113,7 @@ private void cqRemoteDriverMainLoop(ExcerptTailer cqTailer, ChronicleQueue chron } } } - private static + private static DeliveryStatus sendMessage(ReActorSystem localReActorSystem, ExcerptAppender cqAppender, ReActorRef source, ReActorRef destination, long seqNum, AckingPolicy ackingPolicy, PayloadT message) { diff --git a/drivers/src/main/java/io/reacted/drivers/channels/grpc/GrpcDriver.java b/drivers/src/main/java/io/reacted/drivers/channels/grpc/GrpcDriver.java index 641445fc..374bb9cb 100644 --- a/drivers/src/main/java/io/reacted/drivers/channels/grpc/GrpcDriver.java +++ b/drivers/src/main/java/io/reacted/drivers/channels/grpc/GrpcDriver.java @@ -41,15 +41,17 @@ import io.reacted.core.reactorsystem.ReActorSystem; import io.reacted.core.reactorsystem.ReActorSystemId; import io.reacted.core.reactorsystem.ReActorSystemRef; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; import io.reacted.patterns.ObjectUtils; import io.reacted.patterns.Try; import io.reacted.patterns.UnChecked; + +import javax.annotation.Nullable; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; -import java.io.Serializable; import java.net.InetSocketAddress; import java.util.Map; import java.util.Objects; @@ -62,7 +64,6 @@ import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.function.Function; -import javax.annotation.Nullable; @NonNullByDefault public class GrpcDriver extends RemotingDriver { @@ -151,7 +152,7 @@ public UnChecked.CheckedRunnable getDriverLoop() { public ChannelId getChannelId() { return channelId; } @Override - public + public DeliveryStatus sendMessage(ReActorRef source, ReActorContext destinationCtx, ReActorRef destination, long seqNum, ReActorSystemId reActorSystemId, AckingPolicy ackingPolicy, PayloadT payload) { @@ -274,7 +275,7 @@ public void onNext(ReActedLinkProtocol.ReActedDatagram reActedDatagram) { reActedDatagram.getSequenceNumber(), fromReActorSystemId(reActedDatagram.getGeneratorSystem()), AckingPolicy.forOrdinal(reActedDatagram.getAckingPolicyOrdinal()), - (Serializable)msgSource.readObject()); + (ReActedMessage)msgSource.readObject()); } catch (Exception deserializationError) { thisDriver.getLocalReActorSystem() .logError("Error decoding message", deserializationError); diff --git a/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaDriver.java b/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaDriver.java index 75871b40..4b1a7dd4 100644 --- a/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaDriver.java +++ b/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaDriver.java @@ -17,6 +17,7 @@ import io.reacted.core.reactorsystem.ReActorRef; import io.reacted.core.reactorsystem.ReActorSystem; import io.reacted.core.reactorsystem.ReActorSystemId; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; import io.reacted.patterns.Try; import io.reacted.patterns.UnChecked; @@ -40,7 +41,6 @@ import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; -import java.io.Serializable; import java.time.Duration; import java.util.List; import java.util.Objects; @@ -91,7 +91,7 @@ public ChannelId getChannelId() { public Properties getChannelProperties() { return getDriverConfig().getChannelProperties(); } @Override - public + public DeliveryStatus sendMessage(ReActorRef source, ReActorContext destinationCtx, ReActorRef destination, long sequenceNumber, ReActorSystemId reActorSystemId, AckingPolicy ackingPolicy, PayloadT payload) { diff --git a/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaUtils.java b/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaUtils.java index f92a7d1b..f12b925b 100644 --- a/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaUtils.java +++ b/drivers/src/main/java/io/reacted/drivers/channels/kafka/KafkaUtils.java @@ -13,6 +13,7 @@ import io.reacted.core.reactorsystem.ReActorRef; import io.reacted.core.reactorsystem.ReActorSystemId; import io.reacted.core.reactorsystem.ReActorSystemRef; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.drivers.channels.kafka.avro.ChannelId; import io.reacted.drivers.channels.kafka.avro.ChannelType; import io.reacted.drivers.channels.kafka.avro.Message; @@ -25,7 +26,6 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; -import java.io.Serializable; import java.nio.ByteBuffer; import java.util.Objects; @@ -33,7 +33,7 @@ final class KafkaUtils { private KafkaUtils() { throw new AssertionError("We are not supposed to be called"); } @Nullable - static + static Message toAvroMessage(ReActorRef source, ReActorRef destination, long sequenceNumber, ReActorSystemId reActorSystemId, AckingPolicy ackingPolicy, PayloadT payload) throws IOException { @@ -51,7 +51,7 @@ Message toAvroMessage(ReActorRef source, ReActorRef destination, long sequenceNu return avroMessageBuilder.build(); } - static ByteBuffer toSerializedPayload(Serializable payload) throws IOException { + static ByteBuffer toSerializedPayload(ReActedMessage payload) throws IOException { try(ByteArrayOutputStream byteArray = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(byteArray)) { oos.writeObject(payload); @@ -59,10 +59,10 @@ static ByteBuffer toSerializedPayload(Serializable payload) throws IOException { } } - static Serializable fromSerializedPayload(ByteBuffer serializedPayload) throws IOException, ClassNotFoundException { + static ReActedMessage fromSerializedPayload(ByteBuffer serializedPayload) throws IOException, ClassNotFoundException { try (var bais = new ByteArrayInputStream(serializedPayload.array()); var inputStream = new ObjectInputStream(bais)) { - return (Serializable) inputStream.readObject(); + return (ReActedMessage) inputStream.readObject(); } } diff --git a/drivers/src/main/java/io/reacted/drivers/channels/replay/ReplayLocalDriver.java b/drivers/src/main/java/io/reacted/drivers/channels/replay/ReplayLocalDriver.java index 0f3f1697..dd3a2296 100644 --- a/drivers/src/main/java/io/reacted/drivers/channels/replay/ReplayLocalDriver.java +++ b/drivers/src/main/java/io/reacted/drivers/channels/replay/ReplayLocalDriver.java @@ -23,11 +23,19 @@ import io.reacted.core.reactorsystem.ReActorRef; import io.reacted.core.reactorsystem.ReActorSystem; import io.reacted.core.reactorsystem.ReActorSystemId; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.drivers.channels.chroniclequeue.CQLocalDriverConfig; import io.reacted.patterns.NonNullByDefault; import io.reacted.patterns.Try; import io.reacted.patterns.UnChecked; -import java.io.Serializable; +import net.openhft.chronicle.queue.ChronicleQueue; +import net.openhft.chronicle.queue.ExcerptTailer; +import net.openhft.chronicle.threads.Pauser; +import net.openhft.chronicle.wire.WireIn; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.Nullable; import java.util.HashMap; import java.util.Map; import java.util.Objects; @@ -36,13 +44,6 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; import java.util.concurrent.ConcurrentHashMap; -import javax.annotation.Nullable; -import net.openhft.chronicle.queue.ChronicleQueue; -import net.openhft.chronicle.queue.ExcerptTailer; -import net.openhft.chronicle.threads.Pauser; -import net.openhft.chronicle.wire.WireIn; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import static io.reacted.drivers.channels.chroniclequeue.CQLocalDriver.readAckingPolicy; import static io.reacted.drivers.channels.chroniclequeue.CQLocalDriver.readPayload; @@ -84,7 +85,7 @@ public ChannelId getChannelId() { public Properties getChannelProperties() { return new Properties(); } @Override - public DeliveryStatus + public DeliveryStatus sendMessage(ReActorRef source, ReActorContext destinationCtx, ReActorRef destination, long seqNum, ReActorSystemId reActorSystemId, AckingPolicy ackingPolicy, PayloadT message) { if (!(message instanceof DeliveryStatusUpdate)) { @@ -98,7 +99,7 @@ public ChannelId getChannelId() { } @Override - public + public CompletionStage sendAsyncMessage(ReActorRef source, ReActorContext destinationCtx, ReActorRef destination, long seqNum, ReActorSystemId reActorSystemId, @@ -132,7 +133,7 @@ private void replayerMainLoop(ReActorSystem localReActorSystem, ChronicleQueue c } } - private + private void onNewMessage(ReActorSystem localReActorSystem, Map emptyMap, Map> dstToMessageBySeqNum, ReActorRef source, ReActorRef destination, long sequenceNumber, ReActorSystemId fromReActorSystemId, AckingPolicy ackingPolicy, diff --git a/drivers/src/main/java/io/reacted/drivers/serviceregistries/zookeeper/ZooKeeperRootPathsCreated.java b/drivers/src/main/java/io/reacted/drivers/serviceregistries/zookeeper/ZooKeeperRootPathsCreated.java index cfad6aa3..6f0f9795 100644 --- a/drivers/src/main/java/io/reacted/drivers/serviceregistries/zookeeper/ZooKeeperRootPathsCreated.java +++ b/drivers/src/main/java/io/reacted/drivers/serviceregistries/zookeeper/ZooKeeperRootPathsCreated.java @@ -8,6 +8,6 @@ package io.reacted.drivers.serviceregistries.zookeeper; -import java.io.Serializable; +import io.reacted.core.serialization.ReActedMessage; -class ZooKeeperRootPathsCreated implements Serializable {} +class ZooKeeperRootPathsCreated implements ReActedMessage {} diff --git a/examples/src/main/java/io/reacted/examples/benchmarking/BenchmarkingUtils.java b/examples/src/main/java/io/reacted/examples/benchmarking/BenchmarkingUtils.java index 337a02c2..ed0b7167 100644 --- a/examples/src/main/java/io/reacted/examples/benchmarking/BenchmarkingUtils.java +++ b/examples/src/main/java/io/reacted/examples/benchmarking/BenchmarkingUtils.java @@ -4,6 +4,9 @@ import io.reacted.core.reactorsystem.ReActorRef; import io.reacted.core.reactorsystem.ReActorSystem; import io.reacted.core.runtime.Dispatcher; +import io.reacted.core.serialization.Deserializer; +import io.reacted.core.serialization.ReActedMessage; +import io.reacted.core.serialization.Serializer; import io.reacted.core.typedsubscriptions.TypedSubscription; import io.reacted.flow.ReActedGraph; import io.reacted.flow.operators.map.MapOperatorConfig; @@ -13,7 +16,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.Serializable; import java.time.Duration; import java.util.Arrays; import java.util.List; @@ -68,11 +70,11 @@ static Future initAsyncMessageProducer(Runnable messageGenerator, ExecutorSer return executor.submit(messageGenerator); } static Runnable backpressureAwareMessageSender(long messageNum, ReActorRef destination) { - return backpressureAwareMessageSender(messageNum, destination, System::nanoTime); + return backpressureAwareMessageSender(messageNum, destination, () -> ReActedMessage.of(System.nanoTime())); } static Runnable backpressureAwareMessageSender(long messageNum, ReActorRef destination, - Supplier payloadProducer) { + Supplier payloadProducer) { return UnChecked.runnable(() -> { long baseNanosDelay = 100; long delay = baseNanosDelay; @@ -93,10 +95,10 @@ static Runnable backpressureAwareMessageSender(long messageNum, ReActorRef desti } static Runnable nonStopMessageSender(long messageNum, ReActorRef destination) { - return nonStopMessageSender(messageNum, destination, System::nanoTime); + return nonStopMessageSender(messageNum, destination, () -> ReActedMessage.of(System.nanoTime())); } static Runnable nonStopMessageSender(long messageNum, ReActorRef destination, - Supplier payloadProducer) { + Supplier payloadProducer) { return UnChecked.runnable(() -> { for (int msg = 0; msg < messageNum; msg++) { destination.tell(payloadProducer.get()); @@ -105,11 +107,11 @@ static Runnable nonStopMessageSender(long messageNum, ReActorRef destination, } static Runnable constantWindowMessageSender(long messageNum, ReActorRef destination, Duration window) { - return constantWindowMessageSender(messageNum, destination, window, System::nanoTime); + return constantWindowMessageSender(messageNum, destination, window, () -> ReActedMessage.of(System.nanoTime())); } static Runnable constantWindowMessageSender(long messageNum, ReActorRef destination, Duration window, - Supplier payloadProducer) { + Supplier payloadProducer) { Runnable sender = UnChecked.runnable(() -> { long pauseWindowDuration = window.toNanos(); long start = System.nanoTime(); @@ -184,8 +186,8 @@ static Map initStatisticsCollectorProcessor(ReActedGraph sta } @SuppressWarnings("unchecked") - static List - fromRequestsPerIntervalSnapshotsToPrintableOutput(Map, List> payloadByType) { + static List + fromRequestsPerIntervalSnapshotsToPrintableOutput(Map, List> payloadByType) { List requestsPerInterval = (List)payloadByType.get(RPISnapshot.class); long totalRequests = requestsPerInterval.stream() .mapToLong(RPISnapshot::requestsPerInterval) @@ -195,22 +197,23 @@ static Map initStatisticsCollectorProcessor(ReActedGraph sta output.append(String.format("%d ", rpi.requestsPerInterval())); } output.append(String.format("-> %d%n", totalRequests)); - return List.of(output.toString()); + return List.of(ReActedMessage.of(output.toString())); } - static List - fromLatenciesSnapshotsToPrintableOutput(Map, List> payloadByType) { + static List + fromLatenciesSnapshotsToPrintableOutput(Map, List> payloadByType) { List snapshots = (List)payloadByType.get(LatenciesSnapshot.class); long[] latencies = snapshots.stream() - .map(LatenciesSnapshot::latencies) + .map(LatenciesSnapshot::getLatencies) .flatMapToLong(Arrays::stream) .toArray(); return computeLatenciesOutput(latencies); } - static List computeLatenciesOutput(long[] latencies) { + static List computeLatenciesOutput(long[] latencies) { return computeLatencies(latencies).stream() .map(percentile -> String.format("Msgs: %d Percentile %f Latency: %s", latencies.length, percentile.percentile, percentile.latency)) + .map(ReActedMessage::of) .collect(Collectors.toUnmodifiableList()); } @@ -238,13 +241,30 @@ static void nanoSleep(long nanos) { } } - record LatencyForPercentile(double percentile, Duration latency) implements Serializable { } + record LatencyForPercentile(double percentile, Duration latency) implements ReActedMessage { } - record DiagnosticRequest() implements Serializable { } + record DiagnosticRequest() implements ReActedMessage { } - record RPISnapshot(int requestsPerInterval) implements Serializable { } + record RPISnapshot(int requestsPerInterval) implements ReActedMessage { } - record LatenciesSnapshot(long[] latencies) implements Serializable { } + static class LatenciesSnapshot implements ReActedMessage { - record StopCrunching() implements Serializable { } + private long[] latencies; + public LatenciesSnapshot(long[] latencies) { + this.latencies = latencies; + } + + public long[] getLatencies() { return latencies; } + @Override + public void encode(Serializer serializer) { + serializer.put(latencies); + } + + @Override + public void decode(Deserializer deserializer) { + this.latencies = deserializer.getLongs(); + } + } + + record StopCrunching() implements ReActedMessage { } } diff --git a/examples/src/main/java/io/reacted/examples/benchmarking/MessageTsunami.java b/examples/src/main/java/io/reacted/examples/benchmarking/MessageTsunami.java index 4bdbb8d9..aa8116f5 100644 --- a/examples/src/main/java/io/reacted/examples/benchmarking/MessageTsunami.java +++ b/examples/src/main/java/io/reacted/examples/benchmarking/MessageTsunami.java @@ -18,10 +18,10 @@ import io.reacted.core.reactorsystem.ReActorContext; import io.reacted.core.reactorsystem.ReActorRef; import io.reacted.core.reactorsystem.ReActorSystem; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.core.typedsubscriptions.TypedSubscription; import javax.annotation.Nonnull; -import java.io.Serializable; import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.Arrays; @@ -97,8 +97,8 @@ private static class CrunchingWorker implements ReActor { private CrunchingWorker(String dispatcher, String name, int iterations) { this.cfg = ReActorConfig.newBuilder() .setMailBoxProvider(ctx -> new PriorityMailbox((o1, o2) -> { - Class p1 = o1.getPayload().getClass(); - Class p2 = o2.getPayload().getClass(); + Class p1 = o1.getPayload().getClass(); + Class p2 = o2.getPayload().getClass(); if (p1 == p2) { return 0; } if (p1 == BenchmarkingUtils.DiagnosticRequest.class) { return -1; @@ -114,7 +114,7 @@ private CrunchingWorker(String dispatcher, String name, int iterations) { TypedSubscription.TypedSubscriptionPolicy.LOCAL.forType(BenchmarkingUtils.StopCrunching.class)) .build(); this.reActions = ReActions.newBuilder() - .reAct(Long.class, this::onPayload) + .reAct(ReActedMessage.LongMessage.class, this::onPayload) .reAct(BenchmarkingUtils.StopCrunching.class, this::onCrunchStop) .reAct(BenchmarkingUtils.DiagnosticRequest.class, this::onDiagnosticRequest) .build(); @@ -142,13 +142,13 @@ private void onCrunchStop(ReActorContext reActorContext, BenchmarkingUtils.StopC reActorContext.getMbox().request(1); reActorContext.stop(); } - private void onPayload(ReActorContext ctx, Long payLoad) { + private void onPayload(ReActorContext ctx, ReActedMessage.LongMessage payLoad) { if (marker != 0) { System.err.println("CRITIC!"); } marker = 1; int pos = counter.getPlain(); - latencies[pos] = System.nanoTime() - payLoad; + latencies[pos] = System.nanoTime() - payLoad.getPayload(); counter.setPlain(pos + 1); ctx.getMbox().request(1); if (marker != 1) { diff --git a/examples/src/main/java/io/reacted/examples/benchmarking/ReactionTime.java b/examples/src/main/java/io/reacted/examples/benchmarking/ReactionTime.java index b312038c..53248ebf 100644 --- a/examples/src/main/java/io/reacted/examples/benchmarking/ReactionTime.java +++ b/examples/src/main/java/io/reacted/examples/benchmarking/ReactionTime.java @@ -18,9 +18,9 @@ import io.reacted.core.reactorsystem.ReActorContext; import io.reacted.core.reactorsystem.ReActorRef; import io.reacted.core.reactorsystem.ReActorSystem; +import io.reacted.core.serialization.ReActedMessage; import javax.annotation.Nonnull; -import java.io.Serializable; import java.time.Duration; import java.util.Arrays; import java.util.List; @@ -68,6 +68,7 @@ public static void main(String[] args) throws InterruptedException { long start = System.nanoTime(); long end; long elapsed = 0; + ReActedMessage.LongMessage recycle = new ReActedMessage.LongMessage(); for(long cycle = 0; cycle < iterations; cycle++) { while (elapsed < pauseWindowDuration) { @@ -77,7 +78,8 @@ public static void main(String[] args) throws InterruptedException { elapsed = 0; start = System.nanoTime(); - latencyGrabber.tell(start); + recycle.setPayload(start); + latencyGrabber.tell(recycle); //benchmarkSystem.getSystemSink().publish(start); } TimeUnit.SECONDS.sleep(5); @@ -97,8 +99,8 @@ private static Duration getLatencyForPercentile(long[] latencies, double percent return Duration.ofNanos(latencies[index]); } - private record LatenciesRequest() implements Serializable {} - private record LatenciesReply(long[] latencies) implements Serializable {} + private record LatenciesRequest() implements ReActedMessage {} + private record LatenciesReply(long[] latencies) implements ReActedMessage {} private static class MessageGrabber implements ReActiveEntity { private ReActorContext ctx; private final long[] latencies; @@ -111,7 +113,7 @@ private MessageGrabber(int iterations) { @Override public ReActions getReActions() { return ReActions.newBuilder() - .reAct(Long.class, this::onNanoTime) + .reAct(ReActedMessage.LongMessage.class, this::onNanoTime) .reAct(LatenciesRequest.class, (ctx, request) -> ctx.reply(new LatenciesReply(getLatencies()))) .reAct(ReActorInit.class, (ctx, init) -> this.ctx = ctx) @@ -123,8 +125,8 @@ public long[] getLatencies() { } public synchronized CompletionStage stop() { return ctx.stop(); } - private void onNanoTime(ReActorContext reActorContext, long nanotime) { - latencies[cycles++] = System.nanoTime() - nanotime; + private void onNanoTime(ReActorContext reActorContext, ReActedMessage.LongMessage nanotime) { + latencies[cycles++] = System.nanoTime() - nanotime.getPayload(); } } } diff --git a/examples/src/main/java/io/reacted/examples/benchmarking/SingleChannel.java b/examples/src/main/java/io/reacted/examples/benchmarking/SingleChannel.java index 3a7d6ab2..17626ff9 100644 --- a/examples/src/main/java/io/reacted/examples/benchmarking/SingleChannel.java +++ b/examples/src/main/java/io/reacted/examples/benchmarking/SingleChannel.java @@ -17,6 +17,7 @@ import io.reacted.core.reactors.ReActiveEntity; import io.reacted.core.reactorsystem.ReActorContext; import io.reacted.core.reactorsystem.ReActorSystem; +import io.reacted.core.serialization.ReActedMessage; import javax.annotation.Nonnull; @@ -58,16 +59,17 @@ private final static class Cycler implements ReActiveEntity { private Cycler(int cycles) { this.latencies = new long[cycles]; this.reActions = ReActions.newBuilder() - .reAct(Long.class, this::onLong) - .reAct(ReActorInit.class, (ctx, init) -> ctx.selfTell(System.nanoTime())) + .reAct(ReActedMessage.LongMessage.class, this::onLong) + .reAct(ReActorInit.class, + (ctx, init) -> ctx.selfTell(ReActedMessage.of(System.nanoTime()))) .build(); } private synchronized long[] getLatencies() { return latencies; } - private void onLong(ReActorContext ctx, Long latency) { - latencies[idx++] = System.nanoTime() - latency; + private void onLong(ReActorContext ctx, ReActedMessage.LongMessage latency) { + latencies[idx++] = System.nanoTime() - latency.getPayload(); if (idx < latencies.length) { - ctx.selfTell(System.nanoTime()); + ctx.selfTell(ReActedMessage.of(System.nanoTime())); } else { ctx.stop(); } diff --git a/examples/src/main/java/io/reacted/examples/communication/ask/TimeRequest.java b/examples/src/main/java/io/reacted/examples/communication/ask/TimeRequest.java index 5a44f068..40c0c421 100644 --- a/examples/src/main/java/io/reacted/examples/communication/ask/TimeRequest.java +++ b/examples/src/main/java/io/reacted/examples/communication/ask/TimeRequest.java @@ -8,6 +8,6 @@ package io.reacted.examples.communication.ask; -import java.io.Serializable; +import io.reacted.core.serialization.ReActedMessage; -record TimeRequest() implements Serializable { } +record TimeRequest() implements ReActedMessage { } diff --git a/examples/src/main/java/io/reacted/examples/communication/tell/ping/PreparationRequest.java b/examples/src/main/java/io/reacted/examples/communication/tell/ping/PreparationRequest.java index 833a330c..e0b322e0 100644 --- a/examples/src/main/java/io/reacted/examples/communication/tell/ping/PreparationRequest.java +++ b/examples/src/main/java/io/reacted/examples/communication/tell/ping/PreparationRequest.java @@ -8,6 +8,6 @@ package io.reacted.examples.communication.tell.ping; -import java.io.Serializable; +import io.reacted.core.serialization.ReActedMessage; -record PreparationRequest() implements Serializable {} +record PreparationRequest() implements ReActedMessage {} diff --git a/examples/src/main/java/io/reacted/examples/communication/tell/pingpong/Ping.java b/examples/src/main/java/io/reacted/examples/communication/tell/pingpong/Ping.java index 0752b7df..ee00e7e1 100644 --- a/examples/src/main/java/io/reacted/examples/communication/tell/pingpong/Ping.java +++ b/examples/src/main/java/io/reacted/examples/communication/tell/pingpong/Ping.java @@ -8,7 +8,7 @@ package io.reacted.examples.communication.tell.pingpong; -import java.io.Serializable; +import io.reacted.core.serialization.ReActedMessage; -record Ping(int pingValue) implements Serializable { +record Ping(int pingValue) implements ReActedMessage { } diff --git a/examples/src/main/java/io/reacted/examples/communication/tell/pingpong/Pong.java b/examples/src/main/java/io/reacted/examples/communication/tell/pingpong/Pong.java index d0b3f03e..c16bacb0 100644 --- a/examples/src/main/java/io/reacted/examples/communication/tell/pingpong/Pong.java +++ b/examples/src/main/java/io/reacted/examples/communication/tell/pingpong/Pong.java @@ -8,9 +8,9 @@ package io.reacted.examples.communication.tell.pingpong; -import java.io.Serializable; +import io.reacted.core.serialization.ReActedMessage; -class Pong implements Serializable { +class Pong implements ReActedMessage { private final int pongValue; Pong(int pongValue) { diff --git a/examples/src/main/java/io/reacted/examples/httpserver/ReactiveServer.java b/examples/src/main/java/io/reacted/examples/httpserver/ReactiveServer.java index 469f0bce..269a057a 100644 --- a/examples/src/main/java/io/reacted/examples/httpserver/ReactiveServer.java +++ b/examples/src/main/java/io/reacted/examples/httpserver/ReactiveServer.java @@ -16,15 +16,20 @@ import io.reacted.core.reactorsystem.ReActorContext; import io.reacted.core.reactorsystem.ReActorRef; import io.reacted.core.reactorsystem.ReActorSystem; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; import io.reacted.patterns.Try; import io.reacted.streams.ReactedSubmissionPublisher; import io.reacted.streams.ReactedSubmissionPublisher.ReActedSubscriptionConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; -import java.io.Serializable; import java.net.InetSocketAddress; import java.nio.charset.StandardCharsets; import java.time.Duration; @@ -38,10 +43,6 @@ import java.util.concurrent.atomic.AtomicLong; import java.util.stream.Collectors; import java.util.stream.IntStream; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; @NonNullByDefault public class ReactiveServer { @@ -300,6 +301,6 @@ private static void logOnStop(ReActorContext ctx) { ctx.logInfo("Stopping {}", ctx.getSelf().getReActorId().getReActorName()); } - private record PublishRequest(Duration backpressureDelay) implements Serializable { } - private record InternalError(Throwable anyError) implements Serializable { } + private record PublishRequest(Duration backpressureDelay) implements ReActedMessage { } + private record InternalError(Throwable anyError) implements ReActedMessage { } } diff --git a/examples/src/main/java/io/reacted/examples/quickstart/GreeterService.java b/examples/src/main/java/io/reacted/examples/quickstart/GreeterService.java index 064a770f..4b9f980e 100644 --- a/examples/src/main/java/io/reacted/examples/quickstart/GreeterService.java +++ b/examples/src/main/java/io/reacted/examples/quickstart/GreeterService.java @@ -12,10 +12,10 @@ import io.reacted.core.messages.reactors.ReActorInit; import io.reacted.core.reactors.ReActions; import io.reacted.core.reactors.ReActor; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; import javax.annotation.Nonnull; -import java.io.Serializable; @NonNullByDefault final class GreeterService implements ReActor { @@ -40,5 +40,5 @@ public ReActions getReActions() { ctx.reply("Hello from " + GreeterService.class.getSimpleName())) .build(); } - static final class GreetingsRequest implements Serializable { } + static final class GreetingsRequest implements ReActedMessage { } } diff --git a/examples/src/main/java/io/reacted/examples/remoting/services/TimeRequest.java b/examples/src/main/java/io/reacted/examples/remoting/services/TimeRequest.java index 504b1386..839ac8b7 100644 --- a/examples/src/main/java/io/reacted/examples/remoting/services/TimeRequest.java +++ b/examples/src/main/java/io/reacted/examples/remoting/services/TimeRequest.java @@ -8,6 +8,6 @@ package io.reacted.examples.remoting.services; -import java.io.Serializable; +import io.reacted.core.serialization.ReActedMessage; -public class TimeRequest implements Serializable {} +public class TimeRequest implements ReActedMessage {} diff --git a/examples/src/main/java/io/reacted/examples/services/TimeRequest.java b/examples/src/main/java/io/reacted/examples/services/TimeRequest.java index 801905f7..f2e8c1fb 100644 --- a/examples/src/main/java/io/reacted/examples/services/TimeRequest.java +++ b/examples/src/main/java/io/reacted/examples/services/TimeRequest.java @@ -8,6 +8,6 @@ package io.reacted.examples.services; -import java.io.Serializable; +import io.reacted.core.serialization.ReActedMessage; -public class TimeRequest implements Serializable {} +public class TimeRequest implements ReActedMessage {} diff --git a/examples/src/main/java/io/reacted/examples/spawning/ReActorRelationsApp.java b/examples/src/main/java/io/reacted/examples/spawning/ReActorRelationsApp.java index 45174c96..34d5eab3 100644 --- a/examples/src/main/java/io/reacted/examples/spawning/ReActorRelationsApp.java +++ b/examples/src/main/java/io/reacted/examples/spawning/ReActorRelationsApp.java @@ -10,12 +10,12 @@ import io.reacted.core.reactorsystem.ReActorContext; import io.reacted.core.reactorsystem.ReActorRef; import io.reacted.core.reactorsystem.ReActorSystem; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; import io.reacted.patterns.ObjectUtils; import javax.annotation.Nonnull; import javax.annotation.concurrent.Immutable; -import java.io.Serializable; import java.util.concurrent.TimeUnit; import java.util.stream.LongStream; @@ -138,7 +138,7 @@ private void onInit(ReActorContext ctx, ReActorInit init) { } @Immutable - private record BreedRequest(long requestedChildren) implements Serializable { + private record BreedRequest(long requestedChildren) implements ReActedMessage { private BreedRequest(long requestedChildren) { this.requestedChildren = ObjectUtils.requiredInRange(requestedChildren, 1L, Long.MAX_VALUE, IllegalArgumentException::new); @@ -147,12 +147,12 @@ private BreedRequest(long requestedChildren) { @NonNullByDefault @Immutable - private record Greetings(String greetingsMessage) implements Serializable { + private record Greetings(String greetingsMessage) implements ReActedMessage { } @Immutable - private static final class ThankYouFather implements Serializable { private ThankYouFather() { } } + private static final class ThankYouFather implements ReActedMessage { private ThankYouFather() { } } @Immutable - private static final class ByeByeUncle implements Serializable { private ByeByeUncle() { } } + private static final class ByeByeUncle implements ReActedMessage { private ByeByeUncle() { } } } diff --git a/examples/src/main/java/io/reacted/examples/typedsubscription/RemoteBroadcastingApp.java b/examples/src/main/java/io/reacted/examples/typedsubscription/RemoteBroadcastingApp.java index ed2563a5..19b0a961 100644 --- a/examples/src/main/java/io/reacted/examples/typedsubscription/RemoteBroadcastingApp.java +++ b/examples/src/main/java/io/reacted/examples/typedsubscription/RemoteBroadcastingApp.java @@ -12,13 +12,13 @@ import io.reacted.core.config.reactorsystem.ReActorSystemConfig; import io.reacted.core.reactors.ReActions; import io.reacted.core.reactorsystem.ReActorSystem; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.core.typedsubscriptions.TypedSubscription; import io.reacted.drivers.channels.grpc.GrpcDriver; import io.reacted.drivers.channels.grpc.GrpcDriverConfig; import io.reacted.drivers.serviceregistries.zookeeper.ZooKeeperDriver; import io.reacted.drivers.serviceregistries.zookeeper.ZooKeeperDriverConfig; -import java.io.Serializable; import java.util.concurrent.TimeUnit; public class RemoteBroadcastingApp { @@ -68,5 +68,5 @@ public static void main(String[] args) throws InterruptedException { subscriberSystem.shutDown(); } - private static final class Update implements Serializable { } + private static final class Update implements ReActedMessage { } } diff --git a/examples/src/main/java/io/reacted/examples/typedsubscription/Update.java b/examples/src/main/java/io/reacted/examples/typedsubscription/Update.java index d81effa5..35f02841 100644 --- a/examples/src/main/java/io/reacted/examples/typedsubscription/Update.java +++ b/examples/src/main/java/io/reacted/examples/typedsubscription/Update.java @@ -8,7 +8,7 @@ package io.reacted.examples.typedsubscription; -import java.io.Serializable; +import io.reacted.core.serialization.ReActedMessage; -record Update(int updateId) implements Serializable { +record Update(int updateId) implements ReActedMessage { } diff --git a/examples/src/main/java/io/reacted/examples/webappbackend/ServerGate.java b/examples/src/main/java/io/reacted/examples/webappbackend/ServerGate.java index faf838fb..ec870cb0 100644 --- a/examples/src/main/java/io/reacted/examples/webappbackend/ServerGate.java +++ b/examples/src/main/java/io/reacted/examples/webappbackend/ServerGate.java @@ -17,12 +17,12 @@ import io.reacted.core.reactors.ReActions; import io.reacted.core.reactors.ReActor; import io.reacted.core.reactorsystem.ReActorContext; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.examples.webappbackend.handlers.Get; import io.reacted.examples.webappbackend.handlers.Post; import io.reacted.patterns.NonNullByDefault; import javax.annotation.Nonnull; -import java.io.Serializable; import java.time.Instant; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; @@ -104,7 +104,7 @@ private static void spawnUnknownHandler(ReActorContext ctx, SpawnUnknownHandler ctx.logError("Unknown request type received: ", spawnUnknownRequest.getRequestId()); } - private static class SpawnPostHandler implements Serializable { + private static class SpawnPostHandler implements ReActedMessage { private final String requestId; private SpawnPostHandler(String requestId) { this.requestId = requestId; } diff --git a/examples/src/main/java/io/reacted/examples/webappbackend/db/DatabaseService.java b/examples/src/main/java/io/reacted/examples/webappbackend/db/DatabaseService.java index 70e98998..ba6c8dbc 100644 --- a/examples/src/main/java/io/reacted/examples/webappbackend/db/DatabaseService.java +++ b/examples/src/main/java/io/reacted/examples/webappbackend/db/DatabaseService.java @@ -16,12 +16,12 @@ import io.reacted.core.reactors.ReActions; import io.reacted.core.reactors.ReActor; import io.reacted.core.reactorsystem.ReActorContext; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; import org.bson.Document; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import java.io.Serializable; import java.util.Map; import java.util.Objects; import java.util.function.BiConsumer; @@ -73,7 +73,7 @@ private void onQueryRequest(ReActorContext ctx, StorageMessages.QueryRequest req .first().subscribe(new MongoSubscribers.MongoQuerySubscriber(ctx.getSelf(), ctx.getSender())); } - private + private void ifNotReplaying(BiConsumer realCall, ReActorContext ctx, PayloadT anyPayload) { if (mongoClient != null) { realCall.accept(ctx, anyPayload); diff --git a/examples/src/main/java/io/reacted/examples/webappbackend/db/StorageMessages.java b/examples/src/main/java/io/reacted/examples/webappbackend/db/StorageMessages.java index 15a0a3f0..220c9b60 100644 --- a/examples/src/main/java/io/reacted/examples/webappbackend/db/StorageMessages.java +++ b/examples/src/main/java/io/reacted/examples/webappbackend/db/StorageMessages.java @@ -8,21 +8,23 @@ package io.reacted.examples.webappbackend.db; +import io.reacted.core.serialization.Deserializer; +import io.reacted.core.serialization.ReActedMessage; +import io.reacted.core.serialization.Serializer; import io.reacted.patterns.NonNullByDefault; -import java.io.Serializable; import java.util.Objects; @NonNullByDefault public final class StorageMessages { private StorageMessages() { /* No implementation required*/ } - public record QueryReply(String payload) implements Serializable { + public record QueryReply(String payload) implements ReActedMessage { public QueryReply(String payload) { this.payload = Objects.requireNonNull(payload); } } - public record QueryRequest(String key) implements Serializable { + public record QueryRequest(String key) implements ReActedMessage { public QueryRequest(String key) { this.key = Objects.requireNonNull(key); } @@ -32,15 +34,28 @@ public static class StoreError extends Throwable { public StoreError(Throwable anyError) { super(anyError); } } - public static class StoreReply implements Serializable { } - public static class StoreRequest implements Serializable { - private final String payload; - private final String key; + public static class StoreReply implements ReActedMessage { } + + public static class StoreRequest implements ReActedMessage { + private String key; + private String payload; public StoreRequest(String key, String payload) { this.payload = Objects.requireNonNull(payload); this.key = Objects.requireNonNull(key); } - public Serializable getPayload() { return payload; } + + public String getPayload() { return payload; } public String getKey() { return key; } + @Override + public void encode(Serializer serializer) { + serializer.put(payload); + serializer.put(key); + } + + @Override + public void decode(Deserializer deserializer) { + this.payload = deserializer.getString(); + this.key = deserializer.getString(); + } } } diff --git a/examples/src/main/java/io/reacted/examples/webappbackend/handlers/Get.java b/examples/src/main/java/io/reacted/examples/webappbackend/handlers/Get.java index a2527895..2f4185b7 100644 --- a/examples/src/main/java/io/reacted/examples/webappbackend/handlers/Get.java +++ b/examples/src/main/java/io/reacted/examples/webappbackend/handlers/Get.java @@ -17,6 +17,7 @@ import io.reacted.core.reactors.ReActor; import io.reacted.core.reactorsystem.ReActorContext; import io.reacted.core.reactorsystem.ReActorRef; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.examples.webappbackend.Backend; import io.reacted.examples.webappbackend.db.StorageMessages; import io.reacted.patterns.ObjectUtils; @@ -28,7 +29,6 @@ import javax.annotation.Nullable; import java.io.IOException; import java.io.OutputStream; -import java.io.Serializable; import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; @@ -131,6 +131,6 @@ private static Void sendData(OutputStream outputStream, String data) throws IOEx return ObjectUtils.VOID; } - private record ProcessGet(String getRequest) implements Serializable { + private record ProcessGet(String getRequest) implements ReActedMessage { } } diff --git a/examples/src/main/java/io/reacted/examples/webappbackend/handlers/Post.java b/examples/src/main/java/io/reacted/examples/webappbackend/handlers/Post.java index 2c87592b..e8ea4444 100644 --- a/examples/src/main/java/io/reacted/examples/webappbackend/handlers/Post.java +++ b/examples/src/main/java/io/reacted/examples/webappbackend/handlers/Post.java @@ -19,6 +19,7 @@ import io.reacted.core.reactors.ReActions; import io.reacted.core.reactors.ReActor; import io.reacted.core.reactorsystem.ReActorContext; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.examples.webappbackend.Backend; import io.reacted.examples.webappbackend.db.StorageMessages; import io.reacted.patterns.Try; @@ -27,7 +28,6 @@ import javax.annotation.Nullable; import java.io.BufferedReader; import java.io.InputStreamReader; -import java.io.Serializable; import java.time.Instant; import java.util.Objects; import java.util.concurrent.CompletionStage; @@ -146,15 +146,15 @@ private static DeliveryStatus sendTillAvailable(ReActorContext ctx, ? nextSend : DeliveryStatus.BACKPRESSURE_REQUIRED; } - private static Serializable getNextDataChunk(BufferedReader requestStream) { + private static ReActedMessage getNextDataChunk(BufferedReader requestStream) { return Try.of(requestStream::readLine) .filter(Objects::nonNull) - .map(string -> (Serializable)new DataChunkPush(string)) + .map(string -> (ReActedMessage)new DataChunkPush(string)) .orElse(new DataChunksCompleted()); } - private record DataChunkPush(String lineRead) implements Serializable { + private record DataChunkPush(String lineRead) implements ReActedMessage { } - private static final class DataChunksCompleted implements Serializable {} + private static final class DataChunksCompleted implements ReActedMessage {} } diff --git a/flow/src/main/java/io/reacted/flow/GraphController.java b/flow/src/main/java/io/reacted/flow/GraphController.java index 4bdf5704..13f49dc5 100644 --- a/flow/src/main/java/io/reacted/flow/GraphController.java +++ b/flow/src/main/java/io/reacted/flow/GraphController.java @@ -18,6 +18,7 @@ import io.reacted.core.reactorsystem.ReActorContext; import io.reacted.core.reactorsystem.ReActorRef; import io.reacted.core.reactorsystem.ReActorSystem; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.flow.operators.FlowOperatorConfig; import io.reacted.flow.operators.FlowOperatorConfig.Builder; import io.reacted.flow.operators.messages.OperatorInitComplete; @@ -26,7 +27,8 @@ import io.reacted.patterns.ObjectUtils; import io.reacted.patterns.Try; import io.reacted.patterns.UnChecked.TriConsumer; -import java.io.Serializable; + +import javax.annotation.Nonnull; import java.util.Collection; import java.util.HashMap; import java.util.LinkedList; @@ -41,7 +43,6 @@ import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; -import javax.annotation.Nonnull; @SuppressWarnings("unchecked") @NonNullByDefault @@ -125,7 +126,7 @@ private void onStop() { inputStreamProcessors.forEach(ExecutorService::shutdownNow); } private void spawnNewStreamConsumer(ReActorRef operator, - Stream inputStream, + Stream inputStream, ReActorSystem localReActorSystem, String flowName, FlowOperatorConfig operatorCfg) { ExecutorService streamConsumerExecutor = spawnNewInputStreamExecutor(localReActorSystem, @@ -159,7 +160,7 @@ private static ExecutorService spawnNewInputStreamExecutor(ReActorSystem localRe return Executors.newSingleThreadExecutor(inputStreamThreadFactory.build()); } - private record InitInputStreams() implements Serializable { + private record InitInputStreams() implements ReActedMessage { @Override public String toString() { return "InitInputStreams{}"; diff --git a/flow/src/main/java/io/reacted/flow/SourceStream.java b/flow/src/main/java/io/reacted/flow/SourceStream.java index a8bf6080..b4e47b82 100644 --- a/flow/src/main/java/io/reacted/flow/SourceStream.java +++ b/flow/src/main/java/io/reacted/flow/SourceStream.java @@ -8,11 +8,13 @@ package io.reacted.flow; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; import io.reacted.patterns.Try; import io.reacted.streams.ReactedSubmissionPublisher; import io.reacted.streams.ReactedSubmissionPublisher.ReActedSubscriptionConfig; -import java.io.Serializable; + +import javax.annotation.Nullable; import java.util.Collection; import java.util.Spliterator; import java.util.concurrent.BlockingQueue; @@ -24,9 +26,8 @@ import java.util.function.Consumer; import java.util.stream.Stream; import java.util.stream.StreamSupport; -import javax.annotation.Nullable; @NonNullByDefault -public class SourceStream extends StreamProxy { +public class SourceStream extends StreamProxy { @Nullable private final SourceSubscriber sourceSubscriber; private SourceStream(Stream inputStream) { @@ -39,19 +40,19 @@ private SourceStream(Stream inputStream, super(inputStream); this.sourceSubscriber = sourceSubscriber; } - public static SourceStream + public static SourceStream of(Collection inputCollection) { return of(inputCollection.stream()); } - public static + public static SourceStream of(Flow.Publisher publisher) { SourceSubscriber subscriber = new SourceSubscriber<>(); publisher.subscribe(subscriber); return of(subscriber); } - public static + public static SourceStream of(ReactedSubmissionPublisher publisher, ReActedSubscriptionConfig subscriptionConfig) { SourceSubscriber subscriber = new SourceSubscriber<>(); @@ -59,7 +60,7 @@ SourceStream of(ReactedSubmissionPublisher publisher, return of(subscriber); } - public static + public static SourceStream of(Stream inputStream) { return new SourceStream<>(inputStream); } @@ -70,7 +71,7 @@ public void close() { sourceSubscriber.stop(); } } - private static SourceStream + private static SourceStream of(SourceSubscriber subscription) { Spliterator spliterator = new Spliterator<>() { @Override @@ -95,7 +96,7 @@ public boolean tryAdvance(Consumer action) { }; return new SourceStream<>(StreamSupport.stream(spliterator, false), subscription); } - private static class SourceSubscriber + private static class SourceSubscriber implements Subscriber { private final BlockingQueue dataOutput = new LinkedBlockingQueue<>(); private volatile boolean isTerminated = false; diff --git a/flow/src/main/java/io/reacted/flow/operators/FlowOperator.java b/flow/src/main/java/io/reacted/flow/operators/FlowOperator.java index 74a1a2f3..e371ae5a 100644 --- a/flow/src/main/java/io/reacted/flow/operators/FlowOperator.java +++ b/flow/src/main/java/io/reacted/flow/operators/FlowOperator.java @@ -19,6 +19,7 @@ import io.reacted.core.reactorsystem.ReActorContext; import io.reacted.core.reactorsystem.ReActorRef; import io.reacted.core.reactorsystem.ReActorSystem; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.core.services.GateSelectorPolicies; import io.reacted.core.utils.ReActedUtils; import io.reacted.flow.operators.messages.OperatorInitComplete; @@ -27,7 +28,6 @@ import io.reacted.patterns.annotations.unstable.Unstable; import javax.annotation.Nonnull; -import java.io.Serializable; import java.util.Collection; import java.util.List; import java.util.Map; @@ -45,7 +45,7 @@ @Unstable public abstract class FlowOperator, CfgT extends FlowOperatorConfig> implements ReActor { - public static final Collection NO_OUTPUT = List.of(); + public static final Collection NO_OUTPUT = List.of(); private final ReActions operatorReactions; private final CfgT operatorCfg; private final ReActorConfig routeeCfg; @@ -84,9 +84,9 @@ protected FlowOperator(CfgT operatorCfg) { protected static Try of(ReActorSystem localReActorSystem, ServiceConfig config) { return localReActorSystem.spawnService(config); } - protected abstract CompletionStage> - onNext(Serializable input, ReActorContext ctx); - protected void onLinkError(Throwable error, ReActorContext ctx, Serializable input) { + protected abstract CompletionStage> + onNext(ReActedMessage input, ReActorContext ctx); + protected void onLinkError(Throwable error, ReActorContext ctx, ReActedMessage input) { ctx.logError("Unable to pass {} to the next stage", input, error); } @SuppressWarnings("EmptyMethod") @@ -152,20 +152,20 @@ protected void onRefreshOperatorRequest(ReActorContext ctx) { }); } - private void onNext(ReActorContext ctx, Serializable message) { + private void onNext(ReActorContext ctx, ReActedMessage message) { backpressuredPropagation(onNext(message, ctx), message, ctx); } - protected CompletionStage backpressuredPropagation(CompletionStage> operatorOutput, - Serializable inputMessage, + protected CompletionStage backpressuredPropagation(CompletionStage> operatorOutput, + ReActedMessage inputMessage, ReActorContext ctx) { return propagate(operatorOutput, inputMessage, ctx) .thenAccept(lastDelivery -> ctx.getMbox().request(1)); } protected CompletionStage - propagate(CompletionStage> operatorOutput, - Serializable inputMessage, ReActorContext ctx) { + propagate(CompletionStage> operatorOutput, + ReActedMessage inputMessage, ReActorContext ctx) { Consumer onDeliveryError = error -> onFailedDelivery(error, ctx, inputMessage); return operatorOutput.thenCompose(messages -> routeOutputMessageAfterFiltering(messages).entrySet().stream() .map(msgToDst -> forwardToOperators(onDeliveryError, @@ -174,8 +174,8 @@ protected CompletionStage backpressuredPropagation(CompletionStage ReActedUtils.composeDeliveries(first, second, onDeliveryError)) .orElse(CompletableFuture.completedStage(DeliveryStatus.DELIVERED))); } - protected Map, ? extends Collection> - routeOutputMessageAfterFiltering(Collection outputMessages) { + protected Map, ? extends Collection> + routeOutputMessageAfterFiltering(Collection outputMessages) { return outputMessages.stream() .collect(Collectors.groupingBy(message -> operatorCfg.getIfPredicate() .test(message) @@ -184,7 +184,7 @@ protected CompletionStage backpressuredPropagation(CompletionStage forwardToOperators(Consumer onDeliveryError, - Collection messages, + Collection messages, ReActorContext ctx, Collection nextStages) { return messages.stream() .flatMap(output -> nextStages.stream() @@ -193,7 +193,7 @@ protected CompletionStage backpressuredPropagation(CompletionStage CompletableFuture.completedFuture(DeliveryStatus.DELIVERED)); } @SuppressWarnings("SameReturnValue") - protected + protected DeliveryStatus onFailedDelivery(Throwable error, ReActorContext ctx, InputT message) { onLinkError(error, ctx, message); return DeliveryStatus.NOT_DELIVERED; @@ -206,7 +206,7 @@ private static boolean isUpdateMatchingRequest(int expectedIfServices, update.thenElseServices.size() == expectedThenElseServices; } - private static class RefreshOperatorRequest implements Serializable { + private static class RefreshOperatorRequest implements ReActedMessage { @Override public String toString() { @@ -215,7 +215,7 @@ public String toString() { } private record OperatorOutputGatesUpdate(Collection ifPredicateServices, - Collection thenElseServices) implements Serializable { + Collection thenElseServices) implements ReActedMessage { @Override public String toString() { return "OperatorOutputGatesUpdate{" + diff --git a/flow/src/main/java/io/reacted/flow/operators/FlowOperatorConfig.java b/flow/src/main/java/io/reacted/flow/operators/FlowOperatorConfig.java index 7b7ee763..c56e85ad 100644 --- a/flow/src/main/java/io/reacted/flow/operators/FlowOperatorConfig.java +++ b/flow/src/main/java/io/reacted/flow/operators/FlowOperatorConfig.java @@ -13,13 +13,13 @@ import io.reacted.core.messages.services.BasicServiceDiscoverySearchFilter; import io.reacted.core.messages.services.ServiceDiscoverySearchFilter; import io.reacted.core.reactorsystem.ReActorSystem; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; import io.reacted.patterns.ObjectUtils; import io.reacted.patterns.UnChecked.TriConsumer; import io.reacted.patterns.annotations.unstable.Unstable; import javax.annotation.concurrent.Immutable; -import java.io.Serializable; import java.time.Duration; import java.util.Arrays; import java.util.Collection; @@ -36,9 +36,9 @@ public abstract class FlowOperatorConfig> extends ReActorServiceConfig { public static final Duration DEFAULT_OUTPUT_OPERATORS_REFRESH = Duration.ofMinutes(1); - public static final Predicate NO_FILTERING = element -> true; + public static final Predicate NO_FILTERING = element -> true; public static final Collection NO_OUTPUT = List.of(); - public static final Collection> NO_INPUT_STREAMS = List.of(); + public static final Collection> NO_INPUT_STREAMS = List.of(); public static final TriConsumer, ? extends ReActorServiceConfig>, @@ -51,10 +51,10 @@ public abstract class FlowOperatorConfig inputStreamErrorHandler; - private final Predicate ifPredicate; + private final Predicate ifPredicate; private final Collection ifPredicateOutputOperators; private final Collection thenElseOutputOperators; - private final Collection> inputStreams; + private final Collection> inputStreams; private final ReActorConfig routeeConfig; private final String flowName; @@ -79,7 +79,7 @@ protected FlowOperatorConfig(Builder builder) { this.outputOperatorsRefreshPeriod = ObjectUtils.checkNonNullPositiveTimeInterval(builder.outputOperatorsRefreshPeriod); } - public Predicate getIfPredicate() { + public Predicate getIfPredicate() { return ifPredicate; } @@ -91,7 +91,7 @@ public Collection getThenElseOutputOperators() { return thenElseOutputOperators; } - public Collection> getInputStreams() { return inputStreams; } + public Collection> getInputStreams() { return inputStreams; } public ReActorConfig getRouteeConfig() { return routeeConfig; } @@ -108,8 +108,8 @@ public abstract static class Builder> extends ReActorServiceConfig.Builder { protected Collection ifPredicateOutputOperators = NO_OUTPUT; protected Collection thenElseOutputOperators = NO_OUTPUT; - protected Predicate ifPredicate = NO_FILTERING; - protected Collection> inputStreams = NO_INPUT_STREAMS; + protected Predicate ifPredicate = NO_FILTERING; + protected Collection> inputStreams = NO_INPUT_STREAMS; protected ReActorConfig operatorRouteeCfg = DEFAULT_OPERATOR_ROUTEE_CONFIG; protected Duration outputOperatorsRefreshPeriod = DEFAULT_OUTPUT_OPERATORS_REFRESH; @SuppressWarnings("unchecked") @@ -119,7 +119,7 @@ public abstract static class Builder ifPredicate) { + public final BuilderT setIfOutputPredicate(Predicate ifPredicate) { this.ifPredicate = ifPredicate; return getThis(); } @@ -148,7 +148,7 @@ public final BuilderT setThenElseOutputFilter(Collection> inputStreams) { + public final BuilderT setInputStreams(Collection> inputStreams) { this.inputStreams = inputStreams; return getThis(); } diff --git a/flow/src/main/java/io/reacted/flow/operators/map/MapOperator.java b/flow/src/main/java/io/reacted/flow/operators/map/MapOperator.java index 4c034c69..8e0329fd 100644 --- a/flow/src/main/java/io/reacted/flow/operators/map/MapOperator.java +++ b/flow/src/main/java/io/reacted/flow/operators/map/MapOperator.java @@ -9,11 +9,11 @@ package io.reacted.flow.operators.map; import io.reacted.core.reactorsystem.ReActorContext; - +import io.reacted.core.serialization.ReActedMessage; import io.reacted.flow.operators.FlowOperator; import io.reacted.flow.operators.map.MapOperatorConfig.Builder; import io.reacted.patterns.NonNullByDefault; -import java.io.Serializable; + import java.util.Collection; import java.util.Objects; import java.util.concurrent.CompletableFuture; @@ -22,7 +22,7 @@ @NonNullByDefault public class MapOperator extends FlowOperator { - private final Function> mappingFunction; + private final Function> mappingFunction; protected MapOperator(MapOperatorConfig config) { super(config); @@ -31,8 +31,8 @@ protected MapOperator(MapOperatorConfig config) { } @Override - protected CompletionStage> - onNext(Serializable input, ReActorContext ctx) { + protected CompletionStage> + onNext(ReActedMessage input, ReActorContext ctx) { return CompletableFuture.completedStage(mappingFunction.apply(input)); } } diff --git a/flow/src/main/java/io/reacted/flow/operators/map/MapOperatorConfig.java b/flow/src/main/java/io/reacted/flow/operators/map/MapOperatorConfig.java index e7148d9f..34e746aa 100644 --- a/flow/src/main/java/io/reacted/flow/operators/map/MapOperatorConfig.java +++ b/flow/src/main/java/io/reacted/flow/operators/map/MapOperatorConfig.java @@ -8,10 +8,11 @@ package io.reacted.flow.operators.map; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.flow.operators.FlowOperatorConfig; import io.reacted.flow.operators.map.MapOperatorConfig.Builder; import io.reacted.patterns.NonNullByDefault; -import java.io.Serializable; + import java.util.Collection; import java.util.List; import java.util.Objects; @@ -21,7 +22,7 @@ @NonNullByDefault public class MapOperatorConfig extends FlowOperatorConfig { - private final Function> mapper; + private final Function> mapper; private final Builder builder; private MapOperatorConfig(Builder builder) { super(builder); @@ -30,7 +31,7 @@ private MapOperatorConfig(Builder builder) { this.builder = builder; } - public Function> getMapper() { + public Function> getMapper() { return mapper; } @@ -39,11 +40,11 @@ public Function> getMapper() { public static Builder newBuilder() { return new Builder(); } public static class Builder extends FlowOperatorConfig.Builder { @SuppressWarnings("NotNullFieldNotInitialized") - private Function> mapper; + private Function> mapper; private Builder() { super.setRouteeProvider(MapOperator::new); } - public final Builder setMapper(Function> mapper) { + public final Builder setMapper(Function> mapper) { this.mapper = mapper; return this; } diff --git a/flow/src/main/java/io/reacted/flow/operators/messages/OperatorInitComplete.java b/flow/src/main/java/io/reacted/flow/operators/messages/OperatorInitComplete.java index f05b14f9..db8ce5c7 100644 --- a/flow/src/main/java/io/reacted/flow/operators/messages/OperatorInitComplete.java +++ b/flow/src/main/java/io/reacted/flow/operators/messages/OperatorInitComplete.java @@ -8,14 +8,15 @@ package io.reacted.flow.operators.messages; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; -import java.io.Serializable; -import java.util.Objects; + import javax.annotation.concurrent.Immutable; +import java.util.Objects; @NonNullByDefault @Immutable -public class OperatorInitComplete implements Serializable { +public class OperatorInitComplete implements ReActedMessage { private final String flowName; private final String operatorName; private final String routeeName; diff --git a/flow/src/main/java/io/reacted/flow/operators/reduce/ReducingOperator.java b/flow/src/main/java/io/reacted/flow/operators/reduce/ReducingOperator.java index 4bb652ef..43fbb34f 100644 --- a/flow/src/main/java/io/reacted/flow/operators/reduce/ReducingOperator.java +++ b/flow/src/main/java/io/reacted/flow/operators/reduce/ReducingOperator.java @@ -10,10 +10,11 @@ import com.google.common.collect.ImmutableMap; import io.reacted.core.reactorsystem.ReActorContext; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.flow.operators.FlowOperator; import io.reacted.patterns.NonNullByDefault; import io.reacted.patterns.annotations.unstable.Unstable; -import java.io.Serializable; + import java.util.Collection; import java.util.LinkedList; import java.util.List; @@ -29,8 +30,8 @@ public abstract class ReducingOperator, ConfigT extends ReducingOperatorConfig> extends FlowOperator { - private static final Queue NO_ELEMENTS = new LinkedList<>(); - private final Map, Queue> storage; + private static final Queue NO_ELEMENTS = new LinkedList<>(); + private final Map, Queue> storage; protected ReducingOperator(ConfigT config) { super(config); this.storage = config.getReductionRules().keySet().stream() @@ -38,10 +39,10 @@ protected ReducingOperator(ConfigT config) { } @Override - protected CompletionStage> - onNext(Serializable input, ReActorContext ctx) { - Collection result = List.of(); - Class inputType = input.getClass(); + protected CompletionStage> + onNext(ReActedMessage input, ReActorContext ctx) { + Collection result = List.of(); + Class inputType = input.getClass(); if (storage.containsKey(inputType)) { storage.computeIfAbsent(inputType, newKey -> new LinkedList<>()) .add(input); @@ -53,12 +54,12 @@ protected ReducingOperator(ConfigT config) { return CompletableFuture.completedStage(result); } - private Map, List> - getReduceData(Map, Long> reductionRules) { - ImmutableMap.Builder, List> output; + private Map, List> + getReduceData(Map, Long> reductionRules) { + ImmutableMap.Builder, List> output; output = ImmutableMap.builder(); for(var entry : storage.entrySet()) { - Class type = entry.getKey(); + Class type = entry.getKey(); var payloads = entry.getValue(); var required = reductionRules.get(type).intValue(); var elements = removeNfromInput(payloads, required); @@ -67,15 +68,15 @@ protected ReducingOperator(ConfigT config) { return output.build(); } - private static List removeNfromInput(Queue input, + private static List removeNfromInput(Queue input, long howManyToRemove) { - List output = new LinkedList<>(); + List output = new LinkedList<>(); for(int iter = 0; iter < howManyToRemove; iter++) { output.add(input.poll()); } return output; } - private boolean canReduce(Class inputType) { + private boolean canReduce(Class inputType) { return getOperatorCfg().getReductionRules().entrySet().stream() .allMatch(typeToNum -> storage.getOrDefault(inputType, NO_ELEMENTS) .size() >= typeToNum.getValue() diff --git a/flow/src/main/java/io/reacted/flow/operators/reduce/ReducingOperatorConfig.java b/flow/src/main/java/io/reacted/flow/operators/reduce/ReducingOperatorConfig.java index db9548dc..7a9d4e20 100644 --- a/flow/src/main/java/io/reacted/flow/operators/reduce/ReducingOperatorConfig.java +++ b/flow/src/main/java/io/reacted/flow/operators/reduce/ReducingOperatorConfig.java @@ -8,10 +8,11 @@ package io.reacted.flow.operators.reduce; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.flow.operators.FlowOperatorConfig; import io.reacted.patterns.NonNullByDefault; import io.reacted.patterns.annotations.unstable.Unstable; -import java.io.Serializable; + import java.util.Arrays; import java.util.Collection; import java.util.List; @@ -26,10 +27,10 @@ public abstract class ReducingOperatorConfig> extends FlowOperatorConfig { - private final Function, - List>, - Collection> reducer; - private final Map, Long> reductionRules; + private final Function, + List>, + Collection> reducer; + private final Map, Long> reductionRules; protected ReducingOperatorConfig(Builder builder) { super(builder); this.reducer = Objects.requireNonNull(builder.reducer, "Reducer function cannot be null"); @@ -41,27 +42,27 @@ protected ReducingOperatorConfig(Builder, List>, - Collection> getReducer() { return reducer; } + public Function, List>, + Collection> getReducer() { return reducer; } - public Map, Long> getReductionRules() { return reductionRules; } + public Map, Long> getReductionRules() { return reductionRules; } @SuppressWarnings("NotNullFieldNotInitialized") protected abstract static class Builder, BuiltT extends FlowOperatorConfig> extends FlowOperatorConfig.Builder { - private Function, List>, - Collection> reducer; - private Map, Long> reductionRules; + private Function, List>, + Collection> reducer; + private Map, Long> reductionRules; protected Builder() { } @SafeVarargs - public final BuilderT setReductionRules(Class ...requiredTypes) { + public final BuilderT setReductionRules(Class ...requiredTypes) { return setReductionRules(Arrays.stream(requiredTypes) .collect(Collectors.toUnmodifiableList())); } - public final BuilderT setReductionRules(List> reductionRules) { + public final BuilderT setReductionRules(List> reductionRules) { var rules = reductionRules.stream() .collect(Collectors.collectingAndThen(Collectors.groupingBy(Function.identity(), Collectors.counting()), @@ -69,12 +70,12 @@ public final BuilderT setReductionRules(List> redu return setReductionRules(rules); } - public final BuilderT setReductionRules(Map, Long> typeToRequiredInstances) { + public final BuilderT setReductionRules(Map, Long> typeToRequiredInstances) { this.reductionRules = typeToRequiredInstances; return getThis(); } - public final BuilderT setReducer(Function, List>, - Collection> reducer) { + public final BuilderT setReducer(Function, List>, + Collection> reducer) { this.reducer = reducer; return getThis(); } diff --git a/flow/src/main/java/io/reacted/flow/operators/service/ServiceOperator.java b/flow/src/main/java/io/reacted/flow/operators/service/ServiceOperator.java index 13764a64..b92525f8 100644 --- a/flow/src/main/java/io/reacted/flow/operators/service/ServiceOperator.java +++ b/flow/src/main/java/io/reacted/flow/operators/service/ServiceOperator.java @@ -14,6 +14,7 @@ import io.reacted.core.reactors.ReActions; import io.reacted.core.reactorsystem.ReActorContext; import io.reacted.core.reactorsystem.ReActorRef; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.core.utils.ReActedUtils; import io.reacted.flow.operators.FlowOperator; import io.reacted.flow.operators.service.ServiceOperatorConfig.Builder; @@ -22,7 +23,6 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; -import java.io.Serializable; import java.util.Collection; import java.util.List; import java.util.Set; @@ -66,8 +66,8 @@ protected ServiceOperator(ServiceOperatorConfig config) { public ReActions getReActions() { return reActions; } @Override - protected final CompletionStage> - onNext(Serializable input, ReActorContext ctx) { + protected final CompletionStage> + onNext(ReActedMessage input, ReActorContext ctx) { return AsyncUtils.asyncForeach(request -> service.apublish(ctx.getSelf(), request), getOperatorCfg().getToServiceRequests().apply(input).iterator(), @@ -130,18 +130,18 @@ private void onRefreshServiceUpdate(ReActorContext reActorContext, } } } - private void onReply(ReActorContext ctx, PayloadT reply) { + private void onReply(ReActorContext ctx, PayloadT reply) { propagate(CompletableFuture.supplyAsync(() -> getOperatorCfg().getFromServiceResponse() .apply(reply), executorService), reply, ctx); } - private static class RefreshServiceRequest implements Serializable { + private static class RefreshServiceRequest implements ReActedMessage { @Override public String toString() { return "RefreshServiceRequest{}"; } } - private record RefreshServiceUpdate(Collection serviceGates) implements Serializable { } + private record RefreshServiceUpdate(Collection serviceGates) implements ReActedMessage { } } diff --git a/flow/src/main/java/io/reacted/flow/operators/service/ServiceOperatorConfig.java b/flow/src/main/java/io/reacted/flow/operators/service/ServiceOperatorConfig.java index 5a613b4c..91f7754a 100644 --- a/flow/src/main/java/io/reacted/flow/operators/service/ServiceOperatorConfig.java +++ b/flow/src/main/java/io/reacted/flow/operators/service/ServiceOperatorConfig.java @@ -10,12 +10,14 @@ import io.reacted.core.messages.services.ServiceDiscoverySearchFilter; import io.reacted.core.reactorsystem.ReActorRef; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.core.services.GateSelectorPolicies; import io.reacted.flow.operators.FlowOperatorConfig; import io.reacted.flow.operators.service.ServiceOperatorConfig.Builder; import io.reacted.patterns.NonNullByDefault; import io.reacted.patterns.ObjectUtils; -import java.io.Serializable; + +import javax.annotation.Nullable; import java.time.Duration; import java.util.Collection; import java.util.List; @@ -23,15 +25,14 @@ import java.util.Optional; import java.util.concurrent.ExecutorService; import java.util.function.Function; -import javax.annotation.Nullable; @NonNullByDefault public class ServiceOperatorConfig extends FlowOperatorConfig { public static final Duration DEFAULT_SERVICE_REFRESH_PERIOD = Duration.ofMinutes(1); - public static final Function> IDENTITY = List::of; - private final Function> toServiceRequests; - private final Function> fromServiceResponse; - private final Class serviceReplyType; + public static final Function> IDENTITY = List::of; + private final Function> toServiceRequests; + private final Function> fromServiceResponse; + private final Class serviceReplyType; private final ServiceDiscoverySearchFilter serviceSearchFilter; private final Function, Optional> gateSelector; private final Builder builder; @@ -56,15 +57,15 @@ private ServiceOperatorConfig(Builder builder) { this.builder = builder; } - public Function> getToServiceRequests() { + public Function> getToServiceRequests() { return toServiceRequests; } - public Function> getFromServiceResponse() { + public Function> getFromServiceResponse() { return fromServiceResponse; } - public Class getServiceReplyType() { + public Class getServiceReplyType() { return serviceReplyType; } @@ -87,10 +88,10 @@ public Optional getExecutorService() { public static Builder newBuilder() { return new Builder(); } public static class Builder extends FlowOperatorConfig.Builder { - private Function> toServiceRequests = IDENTITY; - private Function> fromServiceResponse = IDENTITY; + private Function> toServiceRequests = IDENTITY; + private Function> fromServiceResponse = IDENTITY; @SuppressWarnings("NotNullFieldNotInitialized") - private Class serviceReplyType; + private Class serviceReplyType; @SuppressWarnings("NotNullFieldNotInitialized") private ServiceDiscoverySearchFilter serviceSearchFilter; private Function, Optional> gateSelector = GateSelectorPolicies.RANDOM_GATE; @@ -100,18 +101,18 @@ public static class Builder extends FlowOperatorConfig.Builder serviceReplyType) { + public final Builder setServiceReplyType(Class serviceReplyType) { this.serviceReplyType = serviceReplyType; return this; } - public final Builder setToServiceRequest(Function> + public final Builder setToServiceRequest(Function> toServiceRequests) { this.toServiceRequests = toServiceRequests; return this; } - public final Builder setFromServiceResponse(Function> + public final Builder setFromServiceResponse(Function> fromServiceResponse) { this.fromServiceResponse = fromServiceResponse; return this; diff --git a/flow/src/main/java/io/reacted/flow/operators/zip/ZipOperatorConfig.java b/flow/src/main/java/io/reacted/flow/operators/zip/ZipOperatorConfig.java index 824db554..4b7718f4 100644 --- a/flow/src/main/java/io/reacted/flow/operators/zip/ZipOperatorConfig.java +++ b/flow/src/main/java/io/reacted/flow/operators/zip/ZipOperatorConfig.java @@ -8,11 +8,11 @@ package io.reacted.flow.operators.zip; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.flow.operators.reduce.ReducingOperatorConfig; import io.reacted.flow.operators.zip.ZipOperatorConfig.Builder; import io.reacted.patterns.NonNullByDefault; -import java.io.Serializable; import java.util.Arrays; import java.util.Collection; import java.util.List; @@ -36,10 +36,10 @@ public static class Builder extends ReducingOperatorConfig.Builder... zipTypes) { + public final Builder setZipTypes(Class... zipTypes) { return setZipTypes(Arrays.stream(zipTypes).collect(Collectors.toUnmodifiableList())); } - public final Builder setZipTypes(Collection> zipTypes) { + public final Builder setZipTypes(Collection> zipTypes) { var zipRequiredTypes = zipTypes.stream() .collect(Collectors.collectingAndThen(Collectors.groupingBy(Function.identity(), Collectors.counting()), @@ -48,17 +48,17 @@ public final Builder setZipTypes(Collection> zipTy return this; } - public final Builder setZipTypes(Map, Long> setZipTypes) { + public final Builder setZipTypes(Map, Long> setZipTypes) { setReductionRules(setZipTypes); return this; } - public final Builder setZipper(Function, List>, - Collection> zipper) { + public final Builder setZipper(Function, List>, + Collection> zipper) { return setReducer(zipper); } - public final Builder setZippingConsumer(Consumer, - List>> zippingConsumer) { + public final Builder setZippingConsumer(Consumer, + List>> zippingConsumer) { return setReducer(map -> { zippingConsumer.accept(map); return List.of(); }); } diff --git a/framework/src/test/java/BenchmarkingUtils.java b/framework/src/test/java/BenchmarkingUtils.java index 6f61c29b..8a5d8479 100644 --- a/framework/src/test/java/BenchmarkingUtils.java +++ b/framework/src/test/java/BenchmarkingUtils.java @@ -2,6 +2,7 @@ import io.reacted.core.reactorsystem.ReActorRef; import io.reacted.core.reactorsystem.ReActorSystem; import io.reacted.core.runtime.Dispatcher; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.core.typedsubscriptions.TypedSubscription; import io.reacted.flow.ReActedGraph; import io.reacted.flow.operators.map.MapOperatorConfig; @@ -11,7 +12,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.Serializable; import java.time.Duration; import java.util.Arrays; import java.util.List; @@ -70,7 +70,7 @@ static Runnable backpressureAwareMessageSender(long messageNum, ReActorRef desti } static Runnable backpressureAwareMessageSender(long messageNum, ReActorRef destination, - Supplier payloadProducer) { + Supplier payloadProducer) { Runnable sender = UnChecked.runnable(() -> { long baseNanosDelay = 1_000_000; long delay = baseNanosDelay; @@ -95,7 +95,7 @@ static Runnable nonStopMessageSender(long messageNum, ReActorRef destination) { return nonStopMessageSender(messageNum, destination, System::nanoTime); } static Runnable nonStopMessageSender(long messageNum, ReActorRef destination, - Supplier payloadProducer) { + Supplier payloadProducer) { return UnChecked.runnable(() -> { for (int msg = 0; msg < messageNum; msg++) { destination.tell(payloadProducer.get()); @@ -108,7 +108,7 @@ static Runnable constantWindowMessageSender(long messageNum, ReActorRef destinat } static Runnable constantWindowMessageSender(long messageNum, ReActorRef destination, Duration window, - Supplier payloadProducer) { + Supplier payloadProducer) { Runnable sender = UnChecked.runnable(() -> { long pauseWindowDuration = window.toNanos(); long start = System.nanoTime(); @@ -183,7 +183,7 @@ static Map initStatisticsCollectorProcessor(ReActedGraph sta } static List - fromRequestsPerIntervalSnapshotsToPrintableOutput(Map, List> payloadByType) { + fromRequestsPerIntervalSnapshotsToPrintableOutput(Map, List> payloadByType) { List requestsPerInterval = (List)payloadByType.get(RPISnapshot.class); long totalRequests = requestsPerInterval.stream() .mapToLong(RPISnapshot::requestsPerInterval) @@ -196,7 +196,7 @@ static Map initStatisticsCollectorProcessor(ReActedGraph sta return List.of(output.toString()); } static List - fromLatenciesSnapshotsToPrintableOutput(Map, List> payloadByType) { + fromLatenciesSnapshotsToPrintableOutput(Map, List> payloadByType) { List snapshots = (List)payloadByType.get(LatenciesSnapshot.class); long[] latencies = snapshots.stream() .map(LatenciesSnapshot::latencies) @@ -236,13 +236,13 @@ static void nanoSleep(long nanos) { } } - record LatencyForPercentile(double percentile, Duration latency) implements Serializable { } + record LatencyForPercentile(double percentile, Duration latency) implements ReActedMessage { } - record DiagnosticRequest() implements Serializable { } + record DiagnosticRequest() implements ReActedMessage { } - record RPISnapshot(int requestsPerInterval) implements Serializable { } + record RPISnapshot(int requestsPerInterval) implements ReActedMessage { } - record LatenciesSnapshot(long[] latencies) implements Serializable { } + record LatenciesSnapshot(long[] latencies) implements ReActedMessage { } - record StopCrunching() implements Serializable { } + record StopCrunching() implements ReActedMessage { } } diff --git a/streams/src/main/java/io/reacted/streams/BackpressureManager.java b/streams/src/main/java/io/reacted/streams/BackpressureManager.java index c097d270..7f2b6f80 100644 --- a/streams/src/main/java/io/reacted/streams/BackpressureManager.java +++ b/streams/src/main/java/io/reacted/streams/BackpressureManager.java @@ -18,6 +18,7 @@ import io.reacted.core.reactors.ReActiveEntity; import io.reacted.core.reactorsystem.ReActorContext; import io.reacted.core.reactorsystem.ReActorRef; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; import io.reacted.patterns.Try; import io.reacted.streams.ReactedSubmissionPublisher.ReActedSubscriptionConfig; @@ -30,18 +31,17 @@ import io.reacted.streams.messages.SubscriptionRequest; import io.reacted.streams.messages.UnsubscriptionRequest; -import java.util.concurrent.Flow.Subscriber; -import java.util.function.Consumer; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import java.io.Serializable; import java.util.Objects; import java.util.concurrent.CompletionStage; import java.util.concurrent.Flow; +import java.util.concurrent.Flow.Subscriber; +import java.util.function.Consumer; import java.util.function.Function; @NonNullByDefault -public class BackpressureManager implements Flow.Subscription, +public class BackpressureManager implements Flow.Subscription, AutoCloseable, ReActiveEntity { private final Flow.Subscriber subscriber; diff --git a/streams/src/main/java/io/reacted/streams/ReactedSubmissionPublisher.java b/streams/src/main/java/io/reacted/streams/ReactedSubmissionPublisher.java index 07a5a2b8..bb46de12 100644 --- a/streams/src/main/java/io/reacted/streams/ReactedSubmissionPublisher.java +++ b/streams/src/main/java/io/reacted/streams/ReactedSubmissionPublisher.java @@ -21,6 +21,9 @@ import io.reacted.core.reactorsystem.ReActorRef; import io.reacted.core.reactorsystem.ReActorSystem; import io.reacted.core.runtime.Dispatcher; +import io.reacted.core.serialization.Deserializer; +import io.reacted.core.serialization.ReActedMessage; +import io.reacted.core.serialization.Serializer; import io.reacted.core.typedsubscriptions.TypedSubscription; import io.reacted.patterns.NonNullByDefault; import io.reacted.patterns.ObjectUtils; @@ -31,11 +34,6 @@ import io.reacted.streams.messages.SubscriptionRequest; import io.reacted.streams.messages.UnsubscriptionRequest; -import java.io.Externalizable; -import java.io.IOException; -import java.io.ObjectInput; -import java.io.ObjectOutput; -import java.io.Serializable; import java.time.Duration; import java.util.Iterator; import java.util.Objects; @@ -51,8 +49,8 @@ import static io.reacted.core.utils.ReActedUtils.ifNotDelivered; @NonNullByDefault -public class ReactedSubmissionPublisher implements Flow.Publisher, - AutoCloseable, Externalizable { +public class ReactedSubmissionPublisher implements Flow.Publisher, + AutoCloseable, ReActedMessage { private static final Duration BACKPRESSURE_DELAY_BASE = Duration.ofMillis(1); private static final String SUBSCRIPTION_NAME_FORMAT = "Backpressure Manager [%s] Subscription [%s]"; private static final long FEED_GATE_OFFSET = SerializationUtils.getFieldOffset(ReactedSubmissionPublisher.class, @@ -68,7 +66,7 @@ public class ReactedSubmissionPublisher implement /** * Creates a location oblivious data publisher with automatic backpressure. Subscribers can slow down - * the producer. Publisher is Serializable, so it can be sent to any reactor over any gate + * the producer. Publisher is ReActedMessage, so it can be sent to any reactor over any gate * and subscribers can simply join the stream. * This publisher is reactive-streams compliant * @see https://www.reactive-streams.org/ @@ -116,15 +114,16 @@ public ReactedSubmissionPublisher() { this.localReActorSystem = ReActorSystem.NO_REACTOR_SYSTEM; } + @Override - public void writeExternal(ObjectOutput out) throws IOException { - feedGate.writeExternal(out); + public void encode(Serializer serializer) { + feedGate.encode(serializer); } @Override - public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + public void decode(Deserializer deserializer) { ReActorRef gate = new ReActorRef(); - gate.readExternal(in); + gate.decode(deserializer); DriverCtx driverCtx = ReActorSystemDriver.getDriverCtx(); if (driverCtx == null) { throw new IllegalStateException("No Driver Context For Driver"); @@ -234,7 +233,7 @@ public DeliveryStatus submit(PayloadT message) { return feedGate.publish(message); } - private void forwardToSubscribers(ReActorContext ctx, Serializable payload) { + private void forwardToSubscribers(ReActorContext ctx, ReActedMessage payload) { if (subscribers.isEmpty()) { return; } diff --git a/streams/src/main/java/io/reacted/streams/messages/PublisherComplete.java b/streams/src/main/java/io/reacted/streams/messages/PublisherComplete.java index 79e65386..8e4819ff 100644 --- a/streams/src/main/java/io/reacted/streams/messages/PublisherComplete.java +++ b/streams/src/main/java/io/reacted/streams/messages/PublisherComplete.java @@ -8,11 +8,12 @@ package io.reacted.streams.messages; -import java.io.Serializable; +import io.reacted.core.serialization.ReActedMessage; + import javax.annotation.concurrent.Immutable; @Immutable -public class PublisherComplete implements Serializable { +public class PublisherComplete implements ReActedMessage { @Override public String toString() { diff --git a/streams/src/main/java/io/reacted/streams/messages/PublisherInterrupt.java b/streams/src/main/java/io/reacted/streams/messages/PublisherInterrupt.java index d352d4ff..8baf52cb 100644 --- a/streams/src/main/java/io/reacted/streams/messages/PublisherInterrupt.java +++ b/streams/src/main/java/io/reacted/streams/messages/PublisherInterrupt.java @@ -7,11 +7,12 @@ */ package io.reacted.streams.messages; -import java.io.Serializable; +import io.reacted.core.serialization.ReActedMessage; + import javax.annotation.concurrent.Immutable; @Immutable -public class PublisherInterrupt implements Serializable { +public class PublisherInterrupt implements ReActedMessage { @Override public String toString() { diff --git a/streams/src/main/java/io/reacted/streams/messages/PublisherShutdown.java b/streams/src/main/java/io/reacted/streams/messages/PublisherShutdown.java index 07f87f35..8d65dd79 100644 --- a/streams/src/main/java/io/reacted/streams/messages/PublisherShutdown.java +++ b/streams/src/main/java/io/reacted/streams/messages/PublisherShutdown.java @@ -8,6 +8,6 @@ package io.reacted.streams.messages; -import java.io.Serializable; +import io.reacted.core.serialization.ReActedMessage; -public class PublisherShutdown implements Serializable { } +public class PublisherShutdown implements ReActedMessage { } diff --git a/streams/src/main/java/io/reacted/streams/messages/SubscriberError.java b/streams/src/main/java/io/reacted/streams/messages/SubscriberError.java index 25de7429..12c6bc42 100644 --- a/streams/src/main/java/io/reacted/streams/messages/SubscriberError.java +++ b/streams/src/main/java/io/reacted/streams/messages/SubscriberError.java @@ -8,11 +8,12 @@ package io.reacted.streams.messages; -import java.io.Serializable; +import io.reacted.core.serialization.ReActedMessage; + import javax.annotation.concurrent.Immutable; @Immutable -public class SubscriberError implements Serializable { +public class SubscriberError implements ReActedMessage { private final Throwable error; public SubscriberError(Throwable error) { this.error = error; diff --git a/streams/src/main/java/io/reacted/streams/messages/SubscriptionReply.java b/streams/src/main/java/io/reacted/streams/messages/SubscriptionReply.java index 8ee8a5b4..8a5ecb98 100644 --- a/streams/src/main/java/io/reacted/streams/messages/SubscriptionReply.java +++ b/streams/src/main/java/io/reacted/streams/messages/SubscriptionReply.java @@ -8,11 +8,12 @@ package io.reacted.streams.messages; -import java.io.Serializable; +import io.reacted.core.serialization.ReActedMessage; + import javax.annotation.concurrent.Immutable; @Immutable -public class SubscriptionReply implements Serializable { +public class SubscriptionReply implements ReActedMessage { private final boolean success; public SubscriptionReply(boolean isSuccess) { this.success = isSuccess; diff --git a/streams/src/main/java/io/reacted/streams/messages/SubscriptionRequest.java b/streams/src/main/java/io/reacted/streams/messages/SubscriptionRequest.java index 2e062517..cabb9ac4 100644 --- a/streams/src/main/java/io/reacted/streams/messages/SubscriptionRequest.java +++ b/streams/src/main/java/io/reacted/streams/messages/SubscriptionRequest.java @@ -9,12 +9,11 @@ package io.reacted.streams.messages; import io.reacted.core.reactorsystem.ReActorRef; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.NonNullByDefault; -import java.io.Serializable; - @NonNullByDefault -public record SubscriptionRequest(ReActorRef subscriptionBackpressuringManager) implements Serializable { +public record SubscriptionRequest(ReActorRef subscriptionBackpressuringManager) implements ReActedMessage { @Override public String toString() { diff --git a/streams/src/main/java/io/reacted/streams/messages/UnsubscriptionRequest.java b/streams/src/main/java/io/reacted/streams/messages/UnsubscriptionRequest.java index 4c42d8cb..8591462f 100644 --- a/streams/src/main/java/io/reacted/streams/messages/UnsubscriptionRequest.java +++ b/streams/src/main/java/io/reacted/streams/messages/UnsubscriptionRequest.java @@ -9,10 +9,9 @@ package io.reacted.streams.messages; import io.reacted.core.reactorsystem.ReActorRef; +import io.reacted.core.serialization.ReActedMessage; -import java.io.Serializable; - -public record UnsubscriptionRequest(ReActorRef subscriptionBackpressuringManager) implements Serializable { +public record UnsubscriptionRequest(ReActorRef subscriptionBackpressuringManager) implements ReActedMessage { @Override public String toString() { diff --git a/streams/src/test/java/io/reacted/streams/DistributedPublisherTest.java b/streams/src/test/java/io/reacted/streams/DistributedPublisherTest.java index 30117529..945cd8f8 100644 --- a/streams/src/test/java/io/reacted/streams/DistributedPublisherTest.java +++ b/streams/src/test/java/io/reacted/streams/DistributedPublisherTest.java @@ -1,7 +1,5 @@ package io.reacted.streams; -import static org.junit.jupiter.api.Assertions.fail; - import io.reacted.core.config.reactors.ReActorConfig; import io.reacted.core.config.reactorsystem.ReActorSystemConfig; import io.reacted.core.messages.reactors.ReActorInit; @@ -9,21 +7,23 @@ import io.reacted.core.reactors.ReActor; import io.reacted.core.reactorsystem.ReActorContext; import io.reacted.core.reactorsystem.ReActorSystem; -import io.reacted.drivers.channels.chroniclequeue.CQDriverConfig; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.drivers.channels.chroniclequeue.CQLocalDriver; import io.reacted.drivers.channels.chroniclequeue.CQLocalDriverConfig; import io.reacted.patterns.ObjectUtils; -import java.io.Serializable; -import java.util.concurrent.Flow.Subscriber; -import java.util.concurrent.Flow.Subscription; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.LongAdder; -import javax.annotation.Nonnull; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; +import javax.annotation.Nonnull; +import java.util.concurrent.Flow.Subscriber; +import java.util.concurrent.Flow.Subscription; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.LongAdder; + +import static org.junit.jupiter.api.Assertions.fail; + public class DistributedPublisherTest { private static ReActorSystem system; @@ -55,12 +55,12 @@ public void testRemotePublishing() throws InterruptedException { .orElseSneakyThrow(); remoteSubscriber.publish(publisher); TimeUnit.SECONDS.sleep(2); - publisher.submit("First Message"); + publisher.submit(ReActedMessage.of("First Message")); TimeUnit.SECONDS.sleep(2); Assertions.assertEquals(2L, testSubscriber.getMessagesCount()); } - private static class TestSubscription implements Subscriber { + private static class TestSubscription implements Subscriber { private Subscription subscription; private LongAdder receivedMessages = new LongAdder(); @Override @@ -70,7 +70,7 @@ public void onSubscribe(Subscription subscription) { } @Override - public void onNext(Serializable item) { + public void onNext(ReActedMessage item) { receivedMessages.increment(); } @@ -84,7 +84,7 @@ public void onNext(Serializable item) { } private static class RemoteReactor implements ReActor { private final ReActorConfig cfg; - private ReactedSubmissionPublisher publisher; + private ReactedSubmissionPublisher publisher; private Subscription subscription; public RemoteReactor(String reactorName) { @@ -108,11 +108,11 @@ public ReActions getReActions() { .build(); } - private void onMessage(ReActorContext ctx, Serializable message) { + private void onMessage(ReActorContext ctx, ReActedMessage message) { publisher.submit(message); subscription.request(1); } - private void onPublisher(ReActorContext ctx,ReactedSubmissionPublisher publisher) { + private void onPublisher(ReActorContext ctx,ReactedSubmissionPublisher publisher) { this.publisher = publisher; publisher.subscribe(new Subscriber<>() { @Override @@ -122,7 +122,7 @@ public void onSubscribe(Subscription subscription) { } @Override - public void onNext(Serializable item) { ctx.selfPublish(item); } + public void onNext(ReActedMessage item) { ctx.selfPublish(item); } @Override public void onError(Throwable throwable) { fail(throwable); } diff --git a/streams/src/test/java/io/reacted/streams/PublisherTCKTest.java b/streams/src/test/java/io/reacted/streams/PublisherTCKTest.java index 6fd2dde7..adbcf8ae 100644 --- a/streams/src/test/java/io/reacted/streams/PublisherTCKTest.java +++ b/streams/src/test/java/io/reacted/streams/PublisherTCKTest.java @@ -11,14 +11,8 @@ import io.reacted.core.config.reactorsystem.ReActorSystemConfig; import io.reacted.core.drivers.local.SystemLocalDrivers; import io.reacted.core.reactorsystem.ReActorSystem; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.patterns.Try; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Flow; -import java.util.concurrent.LinkedBlockingDeque; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; import org.reactivestreams.tck.TestEnvironment; import org.reactivestreams.tck.flow.FlowPublisherVerification; import org.slf4j.Logger; @@ -29,12 +23,20 @@ import org.testng.annotations.BeforeSuite; import org.testng.annotations.Test; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Flow; +import java.util.concurrent.LinkedBlockingDeque; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLong; + @Test public class PublisherTCKTest extends FlowPublisherVerification { private static final Logger LOGGER = LoggerFactory.getLogger(PublisherTCKTest.class); private final AtomicLong counter = new AtomicLong(0); private final ReActorSystem localReActorSystem; - private final BlockingQueue> generatedFlows = new LinkedBlockingDeque<>(); + private final BlockingQueue> generatedFlows = new LinkedBlockingDeque<>(); private volatile ExecutorService submitterThread; public PublisherTCKTest() { @@ -50,7 +52,7 @@ public PublisherTCKTest() { @Override public Flow.Publisher createFlowPublisher(long l) { - var publisher = new ReactedSubmissionPublisher(localReActorSystem, 10_000, + var publisher = new ReactedSubmissionPublisher(localReActorSystem, 10_000, "TckFeed-" + counter.getAndIncrement()); generatedFlows.add(publisher); asyncPublishMessages(publisher, l); From 91dd2f98e256dfbd022242d2e98d38a797c5b599 Mon Sep 17 00:00:00 2001 From: wireknight Date: Mon, 27 Mar 2023 21:28:36 +0200 Subject: [PATCH 12/16] Recyclable fix for logging drivers --- .../core/serialization/Deserializer.java | 13 ++- .../core/serialization/ReActedMessage.java | 52 ++++++++++- .../core/serialization/Serializer.java | 40 ++++---- .../chroniclequeue/CQDeserializer.java | 58 ++++++++++++ .../channels/chroniclequeue/CQSerializer.java | 91 +++++++++++++++++++ .../benchmarking/BenchmarkingUtils.java | 4 +- .../apublish/MessageStormApp.java | 9 +- .../remoting/services/ClockReActor.java | 6 +- .../{TimeRequest.java => TimeMessages.java} | 7 +- .../remoting/services/TimeReActor.java | 7 +- .../examples/streams/SlowdownProducerApp.java | 16 ++-- .../src/test/java/BenchmarkingUtils.java | 18 ++-- framework/src/test/java/ConsistencyTest.java | 6 +- .../io/reacted/streams/PublisherTCKTest.java | 14 +-- 14 files changed, 281 insertions(+), 60 deletions(-) create mode 100644 drivers/src/main/java/io/reacted/drivers/channels/chroniclequeue/CQDeserializer.java create mode 100644 drivers/src/main/java/io/reacted/drivers/channels/chroniclequeue/CQSerializer.java rename examples/src/main/java/io/reacted/examples/remoting/services/{TimeRequest.java => TimeMessages.java} (62%) diff --git a/core/src/main/java/io/reacted/core/serialization/Deserializer.java b/core/src/main/java/io/reacted/core/serialization/Deserializer.java index 2047f3f0..3f0f110a 100644 --- a/core/src/main/java/io/reacted/core/serialization/Deserializer.java +++ b/core/src/main/java/io/reacted/core/serialization/Deserializer.java @@ -11,13 +11,20 @@ import java.io.Serializable; public interface Deserializer { + > T getEnum(Class type); + long getLong(); - long[] getLongs(); + int getLongs(long[] target); + int getInt(); - int[] getInts(); + int getInts(int[] target); + String getString(); byte getByte(); byte[] getBytes(); - Serializable getObject(); + + T getObject(); + + Serializable getObject(Serializable target); } diff --git a/core/src/main/java/io/reacted/core/serialization/ReActedMessage.java b/core/src/main/java/io/reacted/core/serialization/ReActedMessage.java index 2e734367..34ffc165 100644 --- a/core/src/main/java/io/reacted/core/serialization/ReActedMessage.java +++ b/core/src/main/java/io/reacted/core/serialization/ReActedMessage.java @@ -40,12 +40,16 @@ static ReActedMessage of(byte[] payload) { return msg; } - private static ReActedMessage of(Throwable payload) { + static ReActedMessage of(Throwable payload) { var msg = new ThrowableMessage(); msg.value = payload; return msg; } + static , R extends ReActedMessage> R of(T payload) { + return (R) new EnumMessage(payload); + } + class ByteArrayMessage implements ReActedMessage { byte[] payload = null; @Override @@ -58,8 +62,37 @@ public void decode(Deserializer deserializer) { this.payload = deserializer.getBytes(); } } + + class EnumMessage> implements ReActedMessage { + + private T payload = null; + + public EnumMessage(T value) { + this.payload = value; + } + + public EnumMessage() { } + + public EnumMessage setPayload(T payload) { + this.payload = payload; + return this; + } + @Override + public void encode(Serializer serializer) { + serializer.put(payload); + } + + @Override + public void decode(Deserializer deserializer) { + ReActedMessage.super.decode(deserializer); + } + } class LongMessage implements ReActedMessage { private Long payload = null; + + public LongMessage() { } + + public LongMessage(long payload) { this.payload = payload; } public Long getPayload() { return payload; } public void setPayload(long payload) { this.payload = payload; } @@ -79,16 +112,23 @@ class LongsMessage implements ReActedMessage { public long[] getPayload() { return payload; } @Override public void encode(Serializer serializer) { + serializer.put(payload.length); serializer.put(payload); } @Override public void decode(Deserializer deserializer) { - this.payload = deserializer.getLongs(); + this.payload = new long[deserializer.getInt()]; + deserializer.getLongs(payload); } } class IntMessage implements ReActedMessage { private Integer payload = null; + + public IntMessage() { } + + public IntMessage(int payload) { this.payload = payload; } + public int getPayload() { return payload; } @Override public void encode(Serializer serializer) { serializer.put(payload); @@ -103,16 +143,22 @@ class IntsMessage implements ReActedMessage { private int[] payload = null; @Override public void encode(Serializer serializer) { + serializer.put(payload.length); serializer.put(payload); } @Override public void decode(Deserializer deserializer) { - this.payload = deserializer.getInts(); + this.payload = new int[deserializer.getInt()]; + deserializer.getInts(payload); } } class StringMessage implements ReActedMessage { protected String payload = null; + + public StringMessage() { } + + public StringMessage(String payload) { this.payload = payload; } @Override public void encode(Serializer serializer) { serializer.put(payload); diff --git a/core/src/main/java/io/reacted/core/serialization/Serializer.java b/core/src/main/java/io/reacted/core/serialization/Serializer.java index 0a1b7df7..51cfc966 100644 --- a/core/src/main/java/io/reacted/core/serialization/Serializer.java +++ b/core/src/main/java/io/reacted/core/serialization/Serializer.java @@ -11,22 +11,26 @@ import java.io.Serializable; public interface Serializer { - void putLong(long value); - void putLongs(long[] value); - void putInt(int value); - - void putInts(int[] value); - void putString(String value); - void putByte(byte value); - void putBytes(byte[] value); - - void putObject(Serializable value); - default void put(String value) { putString(value);} - default void put(long value) { putLong(value); } - default void put(int value) { putInt(value); } - default void put(byte value) { putByte(value); } - default void put(byte[] value) { putBytes(value); } - - default void put(int[] value) { putInts(value);} - default void put(long[] value) { putLongs(value); } + > Serializer putEnum(T value); + + Serializer putLong(long value); + Serializer putLongs(long[] value); + Serializer putInt(int value); + + Serializer putInts(int[] value); + Serializer putString(String value); + Serializer putByte(byte value); + Serializer putBytes(byte[] value); + + Serializer putObject(Serializable value); + default Serializer put(String value) { return putString(value);} + default Serializer put(long value) { return putLong(value); } + default Serializer put(int value) { return putInt(value); } + default Serializer put(byte value) { return putByte(value); } + default Serializer put(byte[] value) { return putBytes(value); } + + default Serializer put(int[] value) { return putInts(value);} + default Serializer put(long[] value) { return putLongs(value); } + + default > Serializer put(T value) { return putEnum(value); } } diff --git a/drivers/src/main/java/io/reacted/drivers/channels/chroniclequeue/CQDeserializer.java b/drivers/src/main/java/io/reacted/drivers/channels/chroniclequeue/CQDeserializer.java new file mode 100644 index 00000000..6e9b648a --- /dev/null +++ b/drivers/src/main/java/io/reacted/drivers/channels/chroniclequeue/CQDeserializer.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2022 , [ pierre@reacted.io ] + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + +package io.reacted.drivers.channels.chroniclequeue; + +import io.reacted.core.serialization.Deserializer; +import io.reacted.patterns.NonNullByDefault; +import net.openhft.chronicle.wire.WireIn; + +import java.io.Serializable; + +@NonNullByDefault +public class CQDeserializer implements Deserializer { + private WireIn input; + + CQDeserializer(WireIn input) { setDeserializerInput(input); } + + CQDeserializer setDeserializerInput(WireIn input) { this.input = input; return this; } + + @Override + public > T getEnum(Class type) { return input.read().asEnum(type); } + @Override + public long getLong() { return input.read().readLong(); } + + @Override + public int getLongs(long[] target) { + return input.read().array(target); + } + + @Override + public int getInt() { return input.read().int32(); } + + + @Override + public int getInts(int[] target) { + return input.read().array(target); + } + + @Override + public String getString() { return input.read().readString(); } + + @Override + public byte getByte() { return input.read().readByte(); } + + @Override + public byte[] getBytes() { return input.read().bytes(); } + + @Override + public T getObject() { return (T)input.read().object(); } + + @Override + public Serializable getObject(Serializable target) { return input.read().object(target, target.getClass()); } +} diff --git a/drivers/src/main/java/io/reacted/drivers/channels/chroniclequeue/CQSerializer.java b/drivers/src/main/java/io/reacted/drivers/channels/chroniclequeue/CQSerializer.java new file mode 100644 index 00000000..a52d37e3 --- /dev/null +++ b/drivers/src/main/java/io/reacted/drivers/channels/chroniclequeue/CQSerializer.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2022 , [ pierre@reacted.io ] + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + +package io.reacted.drivers.channels.chroniclequeue; + +import io.reacted.core.serialization.Serializer; +import io.reacted.patterns.NonNullByDefault; +import net.openhft.chronicle.wire.WireOut; + +import java.io.Serializable; + +@NonNullByDefault +public class CQSerializer implements Serializer { + + private WireOut out; + + CQSerializer(WireOut out) {setSerializerOutput(out);} + + CQSerializer setSerializerOutput(WireOut out) { + this.out = out; + return this; + } + + @Override + public > Serializer putEnum(T value) { + out.write() + .asEnum(value); + return this; + } + + @Override + public Serializer putLong(long value) { + out.write() + .writeLong(value); + return this; + } + + @Override + public Serializer putLongs(long[] value) { + out.write() + .array(value, value.length); + return this; + } + + @Override + public Serializer putInt(int value) { + out.write() + .int32(value); + return this; + } + + @Override + public Serializer putInts(int[] value) { + out.write() + .array(value, value.length); + return this; + } + + @Override + public Serializer putString(String value) { + out.write() + .writeString(value); + return this; + } + + @Override + public Serializer putByte(byte value) { + out.write() + .int8(value); + return this; + } + + @Override + public Serializer putBytes(byte[] value) { + out.write() + .array(value, value.length); + return this; + } + + @Override + public Serializer putObject(Serializable value) { + out.write() + .object(value); + return this; + } +} diff --git a/examples/src/main/java/io/reacted/examples/benchmarking/BenchmarkingUtils.java b/examples/src/main/java/io/reacted/examples/benchmarking/BenchmarkingUtils.java index ed0b7167..8981d52c 100644 --- a/examples/src/main/java/io/reacted/examples/benchmarking/BenchmarkingUtils.java +++ b/examples/src/main/java/io/reacted/examples/benchmarking/BenchmarkingUtils.java @@ -257,12 +257,14 @@ public LatenciesSnapshot(long[] latencies) { public long[] getLatencies() { return latencies; } @Override public void encode(Serializer serializer) { + serializer.put(latencies.length); serializer.put(latencies); } @Override public void decode(Deserializer deserializer) { - this.latencies = deserializer.getLongs(); + this.latencies = new long[deserializer.getInt()]; + deserializer.getLongs(latencies); } } diff --git a/examples/src/main/java/io/reacted/examples/communication/apublish/MessageStormApp.java b/examples/src/main/java/io/reacted/examples/communication/apublish/MessageStormApp.java index 7b2630f3..4fc7d9e3 100644 --- a/examples/src/main/java/io/reacted/examples/communication/apublish/MessageStormApp.java +++ b/examples/src/main/java/io/reacted/examples/communication/apublish/MessageStormApp.java @@ -19,6 +19,7 @@ import io.reacted.core.reactorsystem.ReActorContext; import io.reacted.core.reactorsystem.ReActorRef; import io.reacted.core.reactorsystem.ReActorSystem; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.core.services.LoadBalancingPolicies; import io.reacted.core.typedsubscriptions.TypedSubscription; import io.reacted.drivers.channels.grpc.GrpcDriver; @@ -138,14 +139,14 @@ public ReActorConfig getConfig() { public ReActions getReActions() { return ReActions.newBuilder() .reAct(ReActorInit.class, (ctx, init) -> onInit(ctx)) - .reAct(NextRecord.class, (ctx, nextRecord) -> onNextRecord(ctx)) + .reAct(ReActedMessage.EnumMessage.class, (ctx, nextRecord) -> onNextRecord(ctx)) .reAct(ReActions::noReAction) .build(); } private void onInit(ReActorContext ctx) { this.testStart = System.nanoTime(); - ctx.selfPublish(NextRecord.INSTANCE); + ctx.selfPublish(ReActedMessage.of(NextRecord.INSTANCE)); } private void onNextRecord(ReActorContext ctx) { @@ -154,7 +155,7 @@ private void onNextRecord(ReActorContext ctx) { Duration.ofNanos(System.nanoTime() - testStart)); ctx.stop(); } else { - serverReference.apublish(String.format("Async Message %d", missingCycles--)) + serverReference.apublish(ReActedMessage.of(String.format("Async Message %d", missingCycles--))) .toCompletableFuture() .handle((deliveryStatus, error) -> { if (error != null) { @@ -162,7 +163,7 @@ private void onNextRecord(ReActorContext ctx) { error.printStackTrace(); } else { if (deliveryStatus.isDelivered()) { - ctx.selfPublish(NextRecord.INSTANCE); + ctx.selfPublish(ReActedMessage.of(NextRecord.INSTANCE)); } else { System.err.printf("Unable to deliver loop message: %s%n", deliveryStatus); diff --git a/examples/src/main/java/io/reacted/examples/remoting/services/ClockReActor.java b/examples/src/main/java/io/reacted/examples/remoting/services/ClockReActor.java index 2fac3131..1ec6a374 100644 --- a/examples/src/main/java/io/reacted/examples/remoting/services/ClockReActor.java +++ b/examples/src/main/java/io/reacted/examples/remoting/services/ClockReActor.java @@ -9,10 +9,10 @@ package io.reacted.examples.remoting.services; import io.reacted.core.config.reactors.ReActorConfig; -import io.reacted.core.typedsubscriptions.TypedSubscription; import io.reacted.core.mailboxes.UnboundedMbox; import io.reacted.core.reactors.ReActions; import io.reacted.core.reactors.ReActor; +import io.reacted.core.typedsubscriptions.TypedSubscription; import io.reacted.patterns.NonNullByDefault; import javax.annotation.Nonnull; @@ -32,8 +32,8 @@ public class ClockReActor implements ReActor { @Override public ReActions getReActions() { return ReActions.newBuilder() - .reAct(TimeRequest.class, - (ctx, timeRequest) -> ctx.reply(ctx.getParent(), ZonedDateTime.now())) + .reAct(TimeMessages.TimeRequest.class, + (ctx, timeRequest) -> ctx.reply(ctx.getParent(), new TimeMessages.TimeReply(ZonedDateTime.now()))) .reAct(ReActions::noReAction) .build(); } diff --git a/examples/src/main/java/io/reacted/examples/remoting/services/TimeRequest.java b/examples/src/main/java/io/reacted/examples/remoting/services/TimeMessages.java similarity index 62% rename from examples/src/main/java/io/reacted/examples/remoting/services/TimeRequest.java rename to examples/src/main/java/io/reacted/examples/remoting/services/TimeMessages.java index 839ac8b7..2e53668c 100644 --- a/examples/src/main/java/io/reacted/examples/remoting/services/TimeRequest.java +++ b/examples/src/main/java/io/reacted/examples/remoting/services/TimeMessages.java @@ -10,4 +10,9 @@ import io.reacted.core.serialization.ReActedMessage; -public class TimeRequest implements ReActedMessage {} +import java.time.ZonedDateTime; + +class TimeMessages { + public record TimeRequest() implements ReActedMessage {} + public record TimeReply(ZonedDateTime time) implements ReActedMessage { } +} diff --git a/examples/src/main/java/io/reacted/examples/remoting/services/TimeReActor.java b/examples/src/main/java/io/reacted/examples/remoting/services/TimeReActor.java index fd15f681..ce7ac94f 100644 --- a/examples/src/main/java/io/reacted/examples/remoting/services/TimeReActor.java +++ b/examples/src/main/java/io/reacted/examples/remoting/services/TimeReActor.java @@ -22,7 +22,6 @@ import io.reacted.core.typedsubscriptions.TypedSubscription; import javax.annotation.Nonnull; -import java.time.ZonedDateTime; public class TimeReActor implements ReActor { private final String serviceToQuery; @@ -37,7 +36,7 @@ public ReActions getReActions() { return ReActions.newBuilder() .reAct(ReActorInit.class, this::onInit) .reAct(ServiceDiscoveryReply.class, this:: onServiceDiscoveryReply) - .reAct(ZonedDateTime.class, this::onServiceResponse) + .reAct(TimeMessages.TimeReply.class, this::onServiceResponse) .reAct(ReActorStop.class, this::onStop) .build(); } @@ -55,11 +54,11 @@ private void onInit(ReActorContext ctx, ReActorInit init) { private void onServiceDiscoveryReply(ReActorContext ctx, ServiceDiscoveryReply serviceDiscoveryReply) { var gate = serviceDiscoveryReply.getServiceGates().stream() .findAny(); - gate.ifPresentOrElse(serviceGate -> serviceGate.publish(ctx.getSelf(), new TimeRequest()), + gate.ifPresentOrElse(serviceGate -> serviceGate.publish(ctx.getSelf(), new TimeMessages.TimeRequest()), () -> ctx.logError("No service discovery response received")); } - private void onServiceResponse(ReActorContext ctx, ZonedDateTime time) { + private void onServiceResponse(ReActorContext ctx, TimeMessages.TimeReply time) { ctx.logInfo("Received {} response from service: {}", ++received, time.toString()); } diff --git a/examples/src/main/java/io/reacted/examples/streams/SlowdownProducerApp.java b/examples/src/main/java/io/reacted/examples/streams/SlowdownProducerApp.java index cf132979..def3508b 100644 --- a/examples/src/main/java/io/reacted/examples/streams/SlowdownProducerApp.java +++ b/examples/src/main/java/io/reacted/examples/streams/SlowdownProducerApp.java @@ -8,23 +8,25 @@ package io.reacted.examples.streams; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.examples.ExampleUtils; import io.reacted.patterns.NonNullByDefault; import io.reacted.streams.ReactedSubmissionPublisher; +import org.awaitility.Awaitility; + import java.io.FileNotFoundException; import java.time.Duration; import java.util.List; import java.util.concurrent.Flow; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.LongAdder; -import org.awaitility.Awaitility; @NonNullByDefault class SlowdownProducerApp { public static void main(String[] args) throws InterruptedException, FileNotFoundException { var reactorSystem = ExampleUtils.getDefaultInitedReActorSystem(SlowdownProducerApp.class.getSimpleName()); - try(var streamPublisher = new ReactedSubmissionPublisher(reactorSystem, 1_000, + try(var streamPublisher = new ReactedSubmissionPublisher(reactorSystem, 1_000, SlowdownProducerApp.class.getSimpleName() + "-Publisher")) { var subscribers = List.of(new TestSubscriber(), new TestSubscriber(), new TestSubscriber()); int subId = 0; @@ -39,7 +41,7 @@ public static void main(String[] args) throws InterruptedException, FileNotFound Duration delay = Duration.ofNanos(1); //Produce a stream of updates for(int updateNum = 0; updateNum < msgNum; updateNum++) { - if (streamPublisher.submit(updateNum).isBackpressureRequired()) { + if (streamPublisher.submit(new ReActedMessage.IntMessage(updateNum)).isBackpressureRequired()) { TimeUnit.NANOSECONDS.sleep(delay.toNanos()); delay = delay.multipliedBy(2); bpcnt++; @@ -63,7 +65,7 @@ public static void main(String[] args) throws InterruptedException, FileNotFound reactorSystem.shutDown(); } - private static class TestSubscriber implements Flow.Subscriber { + private static class TestSubscriber implements Flow.Subscriber { private final LongAdder updatesReceived = new LongAdder(); private boolean isTerminated = false; private Flow.Subscription subscription; @@ -76,13 +78,13 @@ public void onSubscribe(Flow.Subscription subscription) { } @Override - public void onNext(Integer item) { + public void onNext(ReActedMessage.IntMessage item) { updatesReceived.increment(); if (!isTerminated) { - if (lastItem >= item) { + if (lastItem >= item.getPayload()) { throw new IllegalStateException("Unordered sequence detected"); } - this.lastItem = item; + this.lastItem = item.getPayload(); subscription.request(1); } } diff --git a/framework/src/test/java/BenchmarkingUtils.java b/framework/src/test/java/BenchmarkingUtils.java index 8a5d8479..9a160f0d 100644 --- a/framework/src/test/java/BenchmarkingUtils.java +++ b/framework/src/test/java/BenchmarkingUtils.java @@ -66,7 +66,8 @@ static Future initAsyncMessageProducer(Runnable messageGenerator, ExecutorSer return executor.submit(messageGenerator); } static Runnable backpressureAwareMessageSender(long messageNum, ReActorRef destination) { - return backpressureAwareMessageSender(messageNum, destination, System::nanoTime); + return backpressureAwareMessageSender(messageNum, destination, + () -> new ReActedMessage.LongMessage(System.nanoTime())); } static Runnable backpressureAwareMessageSender(long messageNum, ReActorRef destination, @@ -92,7 +93,8 @@ static Runnable backpressureAwareMessageSender(long messageNum, ReActorRef desti } static Runnable nonStopMessageSender(long messageNum, ReActorRef destination) { - return nonStopMessageSender(messageNum, destination, System::nanoTime); + return nonStopMessageSender(messageNum, destination, + () -> new ReActedMessage.LongMessage(System.nanoTime())); } static Runnable nonStopMessageSender(long messageNum, ReActorRef destination, Supplier payloadProducer) { @@ -104,7 +106,8 @@ static Runnable nonStopMessageSender(long messageNum, ReActorRef destination, } static Runnable constantWindowMessageSender(long messageNum, ReActorRef destination, Duration window) { - return constantWindowMessageSender(messageNum, destination, window, System::nanoTime); + return constantWindowMessageSender(messageNum, destination, window, + () -> new ReActedMessage.LongMessage(System.nanoTime())); } static Runnable constantWindowMessageSender(long messageNum, ReActorRef destination, Duration window, @@ -182,7 +185,7 @@ static Map initStatisticsCollectorProcessor(ReActedGraph sta .build(); } - static List + static List fromRequestsPerIntervalSnapshotsToPrintableOutput(Map, List> payloadByType) { List requestsPerInterval = (List)payloadByType.get(RPISnapshot.class); long totalRequests = requestsPerInterval.stream() @@ -193,9 +196,9 @@ static Map initStatisticsCollectorProcessor(ReActedGraph sta output.append(String.format("%d ", rpi.requestsPerInterval())); } output.append(String.format("-> %d%n", totalRequests)); - return List.of(output.toString()); + return List.of(new ReActedMessage.StringMessage(output.toString())); } - static List + static List fromLatenciesSnapshotsToPrintableOutput(Map, List> payloadByType) { List snapshots = (List)payloadByType.get(LatenciesSnapshot.class); long[] latencies = snapshots.stream() @@ -204,11 +207,12 @@ static Map initStatisticsCollectorProcessor(ReActedGraph sta .toArray(); return computeLatenciesOutput(latencies); } - static List computeLatenciesOutput(long[] latencies) { + static List computeLatenciesOutput(long[] latencies) { return computeLatencies(latencies).stream() .map(percentile -> String.format("Msgs: %d Percentile %f Latency: %s", latencies.length, percentile.percentile, percentile.latency)) + .map(ReActedMessage.StringMessage::new) .collect(Collectors.toUnmodifiableList()); } diff --git a/framework/src/test/java/ConsistencyTest.java b/framework/src/test/java/ConsistencyTest.java index 637c15e7..35afc7e3 100644 --- a/framework/src/test/java/ConsistencyTest.java +++ b/framework/src/test/java/ConsistencyTest.java @@ -16,9 +16,9 @@ import io.reacted.core.reactorsystem.ReActorContext; import io.reacted.core.reactorsystem.ReActorRef; import io.reacted.core.reactorsystem.ReActorSystem; +import io.reacted.core.serialization.ReActedMessage; import javax.annotation.Nonnull; -import java.time.Duration; import java.time.Instant; import java.time.temporal.ChronoUnit; @@ -78,7 +78,7 @@ private CrunchingWorker(String dispatcher, String name) { .setDispatcherName(dispatcher) .build(); this.reActions = ReActions.newBuilder() - .reAct(Long.class, this::onPayload) + .reAct(ReActedMessage.LongMessage.class, this::onPayload) .reAct(ReActorStop.class, this::onStop) .build(); } @@ -88,7 +88,7 @@ private CrunchingWorker(String dispatcher, String name) { private void onStop(ReActorContext reActorContext, ReActorStop stopCrunching) { reActorContext.stop(); } - private void onPayload(ReActorContext ctx, Long payLoad) { + private void onPayload(ReActorContext ctx, ReActedMessage.LongMessage payLoad) { if (marker != 0) { System.err.println("CRITIC!"); System.exit(1); diff --git a/streams/src/test/java/io/reacted/streams/PublisherTCKTest.java b/streams/src/test/java/io/reacted/streams/PublisherTCKTest.java index adbcf8ae..cf440e9b 100644 --- a/streams/src/test/java/io/reacted/streams/PublisherTCKTest.java +++ b/streams/src/test/java/io/reacted/streams/PublisherTCKTest.java @@ -32,7 +32,7 @@ import java.util.concurrent.atomic.AtomicLong; @Test -public class PublisherTCKTest extends FlowPublisherVerification { +public class PublisherTCKTest extends FlowPublisherVerification { private static final Logger LOGGER = LoggerFactory.getLogger(PublisherTCKTest.class); private final AtomicLong counter = new AtomicLong(0); private final ReActorSystem localReActorSystem; @@ -51,7 +51,7 @@ public PublisherTCKTest() { } @Override - public Flow.Publisher createFlowPublisher(long l) { + public Flow.Publisher createFlowPublisher(long l) { var publisher = new ReactedSubmissionPublisher(localReActorSystem, 10_000, "TckFeed-" + counter.getAndIncrement()); generatedFlows.add(publisher); @@ -60,8 +60,8 @@ public Flow.Publisher createFlowPublisher(long l) { } @Override - public Flow.Publisher createFailedFlowPublisher() { - var publisher = new ReactedSubmissionPublisher(localReActorSystem, 10_000, + public Flow.Publisher createFailedFlowPublisher() { + var publisher = new ReactedSubmissionPublisher(localReActorSystem, 10_000, "FailedTckFeed-" + counter.getAndIncrement()); publisher.close(); Try.ofRunnable(() -> TimeUnit.MILLISECONDS.sleep(20)) @@ -98,13 +98,15 @@ public void cleanup() { localReActorSystem.shutDown(); } - private void asyncPublishMessages(ReactedSubmissionPublisher publisher, + private void asyncPublishMessages(ReactedSubmissionPublisher publisher, long messagesNum) { submitterThread.submit(() -> { //The subscription handshake needs some time to complete Try.ofRunnable(() -> TimeUnit.MILLISECONDS.sleep(50)); for(long cycle = 0; cycle < messagesNum && !Thread.currentThread().isInterrupted(); cycle++) { - if (publisher.submit(cycle).isNotSent()) { + ReActedMessage.LongMessage payload = new ReActedMessage.LongMessage(); + payload.setPayload(cycle); + if (publisher.submit(payload).isNotSent()) { LOGGER.error("Critic! Message {} not sent!", cycle); } } From 7e89c5b8ee62cbc65cffb7ae349e456b3108f123 Mon Sep 17 00:00:00 2001 From: wireknight Date: Tue, 4 Apr 2023 23:22:57 +0200 Subject: [PATCH 13/16] Fixed tests --- .../core/serialization/ReActedMessage.java | 23 ++++++++++++++++++- .../StreamToMultipleSubscribersApp.java | 14 +++++++---- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/io/reacted/core/serialization/ReActedMessage.java b/core/src/main/java/io/reacted/core/serialization/ReActedMessage.java index 34ffc165..31fee61f 100644 --- a/core/src/main/java/io/reacted/core/serialization/ReActedMessage.java +++ b/core/src/main/java/io/reacted/core/serialization/ReActedMessage.java @@ -9,6 +9,8 @@ package io.reacted.core.serialization; import java.io.Serializable; +import java.util.Arrays; +import java.util.Comparator; public interface ReActedMessage extends Serializable { default Class getMessageType() { @@ -86,6 +88,9 @@ public void encode(Serializer serializer) { public void decode(Deserializer deserializer) { ReActedMessage.super.decode(deserializer); } + + @Override + public String toString() { return "EnumMessage{" + "payload=" + payload + '}'; } } class LongMessage implements ReActedMessage { private Long payload = null; @@ -104,6 +109,9 @@ public void encode(Serializer serializer) { public void decode(Deserializer deserializer) { this.payload = deserializer.getLong(); } + + @Override + public String toString() { return "LongMessage{" + "payload=" + payload + '}'; } } class LongsMessage implements ReActedMessage { @@ -120,10 +128,14 @@ public void decode(Deserializer deserializer) { this.payload = new long[deserializer.getInt()]; deserializer.getLongs(payload); } + + @Override + public String toString() { return "LongsMessage{" + "payload=" + Arrays.toString(payload) + '}'; } } class IntMessage implements ReActedMessage { - private Integer payload = null; + public static final Comparator COMPARATOR = Comparator.comparingInt(m -> m.payload); + private int payload; public IntMessage() { } @@ -137,6 +149,9 @@ public void encode(Serializer serializer) { public void decode(Deserializer deserializer) { this.payload = deserializer.getInt(); } + + @Override + public String toString() { return "IntMessage{" + "payload=" + payload + '}'; } } class IntsMessage implements ReActedMessage { @@ -151,6 +166,9 @@ public void decode(Deserializer deserializer) { this.payload = new int[deserializer.getInt()]; deserializer.getInts(payload); } + + @Override + public String toString() { return "IntsMessage{" + "payload=" + Arrays.toString(payload) + '}'; } } class StringMessage implements ReActedMessage { @@ -167,6 +185,9 @@ public void encode(Serializer serializer) { public void decode(Deserializer deserializer) { this.payload = deserializer.getString(); } + + @Override + public String toString() { return "StringMessage{" + "payload='" + payload + '\'' + '}'; } } class ThrowableMessage extends SerializableMessage { } diff --git a/examples/src/main/java/io/reacted/examples/streams/StreamToMultipleSubscribersApp.java b/examples/src/main/java/io/reacted/examples/streams/StreamToMultipleSubscribersApp.java index 67a6acb7..bba5e072 100644 --- a/examples/src/main/java/io/reacted/examples/streams/StreamToMultipleSubscribersApp.java +++ b/examples/src/main/java/io/reacted/examples/streams/StreamToMultipleSubscribersApp.java @@ -8,9 +8,12 @@ package io.reacted.examples.streams; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.examples.ExampleUtils; import io.reacted.patterns.NonNullByDefault; import io.reacted.streams.ReactedSubmissionPublisher; +import org.awaitility.Awaitility; + import java.io.FileNotFoundException; import java.time.Duration; import java.util.Comparator; @@ -19,7 +22,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.LongAdder; import java.util.stream.IntStream; -import org.awaitility.Awaitility; @NonNullByDefault class StreamToMultipleSubscribersApp { @@ -27,11 +29,12 @@ class StreamToMultipleSubscribersApp { public static void main(String[] args) throws InterruptedException, FileNotFoundException { var reactorSystem = ExampleUtils.getDefaultInitedReActorSystem(StreamToMultipleSubscribersApp.class.getSimpleName()); - var streamPublisher = new ReactedSubmissionPublisher(reactorSystem, 10_000, + var streamPublisher = new ReactedSubmissionPublisher(reactorSystem, 10_000, StreamToMultipleSubscribersApp.class.getSimpleName() + "-Publisher"); - var subscriber = new TestSubscriber<>(-1, Integer::compareTo); - var subscriber2 = new TestSubscriber<>(-1, Integer::compareTo); - var subscriber3 = new TestSubscriber<>(-1, Integer::compareTo); + var baseMessage = new ReActedMessage.IntMessage(-1); + var subscriber = new TestSubscriber<>(baseMessage, ReActedMessage.IntMessage.COMPARATOR); + var subscriber2 = new TestSubscriber<>(baseMessage, ReActedMessage.IntMessage.COMPARATOR); + var subscriber3 = new TestSubscriber<>(baseMessage, ReActedMessage.IntMessage.COMPARATOR); streamPublisher.subscribe(subscriber); streamPublisher.subscribe(subscriber2); streamPublisher.subscribe(subscriber3); @@ -40,6 +43,7 @@ public static void main(String[] args) throws InterruptedException, FileNotFound var msgNum = 1_000_000; //Produce a stream of updates IntStream.range(0, msgNum) + .mapToObj(ReActedMessage.IntMessage::new) //Propagate them to every consumer, regardless of the location //NOTE: in this example we are not slowing down the producer if a consumer cannot //keep up with the update speed. Delivery guarantee is still valid, but pending From 93cdc508ad8efa2c69fa0152f012944478e2360a Mon Sep 17 00:00:00 2001 From: wireknight Date: Wed, 5 Apr 2023 00:46:38 +0200 Subject: [PATCH 14/16] Fixed tests compilation --- .../io/reacted/core/messages/Message.java | 2 +- .../core/serialization/ReActedMessage.java | 2 +- .../core/services/LoadBalancingPolicies.java | 3 ++- .../chroniclequeue/CQLocalDriver.java | 4 ++-- .../io/reacted/examples/ExampleUtils.java | 12 +++++++--- .../communication/ask/BrokenClockApp.java | 3 +-- .../communication/ask/ReactiveClockApp.java | 6 ++--- .../examples/communication/ask/TimeReply.java | 15 +++++++++++++ .../tell/ping/SendMessagesApp.java | 3 ++- .../tell/ping/SimpleTestReActor.java | 13 ++++++----- .../communication/tell/pingpong/Ping.java | 16 +++++++++++++- .../tell/pingpong/PongReActor.java | 4 ++-- .../examples/flow/ReducingExample.java | 17 +++++++++----- .../examples/httpserver/ReactiveServer.java | 21 +++++++++--------- .../examples/quickstart/GreeterService.java | 2 +- .../examples/quickstart/QuickstartClient.java | 5 +++-- .../examples/replay/SystemReplayApp.java | 4 +++- .../examples/replay/SystemReplayAskApp.java | 12 +++++----- .../services/ServicePublicationApp.java | 13 ++++++----- .../examples/services/TimeMessage.java | 15 +++++++++++++ .../webappbackend/db/StorageMessages.java | 22 +++++++++++++++++-- 21 files changed, 139 insertions(+), 55 deletions(-) create mode 100644 examples/src/main/java/io/reacted/examples/communication/ask/TimeReply.java create mode 100644 examples/src/main/java/io/reacted/examples/services/TimeMessage.java diff --git a/core/src/main/java/io/reacted/core/messages/Message.java b/core/src/main/java/io/reacted/core/messages/Message.java index 054f596f..3873f573 100644 --- a/core/src/main/java/io/reacted/core/messages/Message.java +++ b/core/src/main/java/io/reacted/core/messages/Message.java @@ -102,7 +102,7 @@ public void decode(Deserializer deserializer) { setCreatingReactorSystemId(receivedGeneratingReActorSystem); setAckingPolicy(AckingPolicy.forOrdinal(deserializer.getInt())); setSequenceNumber(deserializer.getLong()); - setPayload((ReActedMessage)deserializer.getObject()); + setPayload(deserializer.getObject()); } public ReActorRef getSender() { return sender; } diff --git a/core/src/main/java/io/reacted/core/serialization/ReActedMessage.java b/core/src/main/java/io/reacted/core/serialization/ReActedMessage.java index 31fee61f..6ca1d06e 100644 --- a/core/src/main/java/io/reacted/core/serialization/ReActedMessage.java +++ b/core/src/main/java/io/reacted/core/serialization/ReActedMessage.java @@ -187,7 +187,7 @@ public void decode(Deserializer deserializer) { } @Override - public String toString() { return "StringMessage{" + "payload='" + payload + '\'' + '}'; } + public String toString() { return payload; } } class ThrowableMessage extends SerializableMessage { } diff --git a/core/src/main/java/io/reacted/core/services/LoadBalancingPolicies.java b/core/src/main/java/io/reacted/core/services/LoadBalancingPolicies.java index ac761654..40281465 100644 --- a/core/src/main/java/io/reacted/core/services/LoadBalancingPolicies.java +++ b/core/src/main/java/io/reacted/core/services/LoadBalancingPolicies.java @@ -66,7 +66,8 @@ ReActorRef selectRoutee(@Nonnull ReActorContext routerCtx, }; private LoadBalancingPolicies() { /* No implementation required */ } - public static LoadBalancingPolicy partitionBy(ToIntFunction partitioner) { + public static LoadBalancingPolicy + partitionBy(ToIntFunction partitioner) { return new LoadBalancingPolicy() { @Nullable @Override diff --git a/drivers/src/main/java/io/reacted/drivers/channels/chroniclequeue/CQLocalDriver.java b/drivers/src/main/java/io/reacted/drivers/channels/chroniclequeue/CQLocalDriver.java index 5002ed61..17509605 100644 --- a/drivers/src/main/java/io/reacted/drivers/channels/chroniclequeue/CQLocalDriver.java +++ b/drivers/src/main/java/io/reacted/drivers/channels/chroniclequeue/CQLocalDriver.java @@ -131,7 +131,7 @@ private void chronicleMainLoop(ExcerptTailer tailer) { } private void readMessage(WireIn in, DriverCtx driverCtx) { - in.read("M").marshallable(m -> offerMessage(readReActorRef(in, driverCtx), + in.read().marshallable(m -> offerMessage(readReActorRef(in, driverCtx), readReActorRef(in, driverCtx), readSequenceNumber(in), readReActorSystemId(in), @@ -141,7 +141,7 @@ private void readMessage(WireIn in, DriverCtx driverCtx) { public static void writeMessage(WireOut out, ReActorRef source, ReActorRef destination, long seqNum, ReActorSystemId localReActorSystemId, AckingPolicy ackingPolicy, PayloadT payload) { - out.write("M") + out.write() .marshallable(m -> writePayload(writeAckingPolicy(writeReActorSystemId(writeSequenceNumber(writeReActorRef(writeReActorRef(m, source), destination), seqNum), diff --git a/examples/src/main/java/io/reacted/examples/ExampleUtils.java b/examples/src/main/java/io/reacted/examples/ExampleUtils.java index 057e766f..9f3998c2 100644 --- a/examples/src/main/java/io/reacted/examples/ExampleUtils.java +++ b/examples/src/main/java/io/reacted/examples/ExampleUtils.java @@ -11,13 +11,15 @@ import io.reacted.core.config.dispatchers.DispatcherConfig; import io.reacted.core.config.drivers.ChannelDriverConfig; import io.reacted.core.config.reactorsystem.ReActorSystemConfig; -import io.reacted.core.drivers.local.SystemLocalDrivers; import io.reacted.core.drivers.serviceregistries.ServiceRegistryDriver; import io.reacted.core.drivers.system.LocalDriver; import io.reacted.core.drivers.system.RemotingDriver; import io.reacted.core.reactorsystem.ReActorSystem; +import io.reacted.drivers.channels.chroniclequeue.CQLocalDriver; +import io.reacted.drivers.channels.chroniclequeue.CQLocalDriverConfig; import io.reacted.drivers.channels.grpc.GrpcDriverConfig; import io.reacted.patterns.NonNullByDefault; + import java.io.FileNotFoundException; import java.util.Collection; import java.util.List; @@ -36,7 +38,11 @@ public static ReActorSystem getDefaultInitedReActorSystem(String reActorSystemNa } public static ReActorSystemConfig getDefaultReActorSystemCfg(String reActorSystemName) { - return getDefaultReActorSystemCfg(reActorSystemName, SystemLocalDrivers.DIRECT_COMMUNICATION, + return getDefaultReActorSystemCfg(reActorSystemName, //SystemLocalDrivers.DIRECT_COMMUNICATION, + new CQLocalDriver(CQLocalDriverConfig.newBuilder() + .setChannelName("LC") + .setChronicleFilesDir("/tmp/chronicle") + .build()), NO_SERVICE_REGISTRIES, NO_REMOTING_DRIVERS); } @@ -52,7 +58,7 @@ public static ReActorSystemConfig getDefaultReActorSystemCfg(String reActorSyste //Fan out pool to message type subscribers .setMsgFanOutPoolSize(1) //Generate extra information for replaying if required - .setRecordExecution(true) + //.setRecordExecution(true) .addDispatcherConfig(DispatcherConfig.newBuilder() .setDispatcherName("FlowDispatcher") .setBatchSize(10) diff --git a/examples/src/main/java/io/reacted/examples/communication/ask/BrokenClockApp.java b/examples/src/main/java/io/reacted/examples/communication/ask/BrokenClockApp.java index 06e4ff69..5683cf2a 100644 --- a/examples/src/main/java/io/reacted/examples/communication/ask/BrokenClockApp.java +++ b/examples/src/main/java/io/reacted/examples/communication/ask/BrokenClockApp.java @@ -15,7 +15,6 @@ import java.io.FileNotFoundException; import java.time.Duration; -import java.time.Instant; public class BrokenClockApp { public static void main(String[] args) throws FileNotFoundException { @@ -31,7 +30,7 @@ public static void main(String[] args) throws FileNotFoundException { var brokenReactiveClock = reActorSystem.spawn(ReActions.NO_REACTIONS, reactiveClockConfig) .orElseSneakyThrow(); //Note: we do not need another reactor to intercept the answer - brokenReactiveClock.ask(new TimeRequest(), Instant.class, Duration.ofSeconds(2), "What's the time?") + brokenReactiveClock.ask(new TimeRequest(), TimeReply.class, Duration.ofSeconds(2), "What's the time?") .handle((timeReply,error) -> error == null ? "Wow, unexpected" : "Clock did not reply as expected") .thenAccept(System.out::println) .thenAccept(nullValue -> reActorSystem.shutDown()); diff --git a/examples/src/main/java/io/reacted/examples/communication/ask/ReactiveClockApp.java b/examples/src/main/java/io/reacted/examples/communication/ask/ReactiveClockApp.java index 061e9ef1..23a4018d 100644 --- a/examples/src/main/java/io/reacted/examples/communication/ask/ReactiveClockApp.java +++ b/examples/src/main/java/io/reacted/examples/communication/ask/ReactiveClockApp.java @@ -27,7 +27,7 @@ public static void main(String[] args) throws FileNotFoundException { var reactiveClockReactions = ReActions.newBuilder() .reAct(TimeRequest.class, (ctx, request) -> ctx.getSender() - .publish(Instant.now())) + .publish(new TimeReply(Instant.now()))) //For any other message type simply ignore the message .reAct((ctx, any) -> { }) @@ -44,10 +44,10 @@ public static void main(String[] args) throws FileNotFoundException { var reactiveClock = reActorSystem.spawn(reactiveClockReactions, reactiveClockConfig) .orElseSneakyThrow(); //Note: we do not need another reactor to intercept the answer - reactiveClock.ask(new TimeRequest(), Instant.class, "What's the time?") + reactiveClock.ask(new TimeRequest(), TimeReply.class, "What's the time?") //Ignore the exception, it's just an example .thenAccept(time -> System.out.printf("It's %s%n", - ZonedDateTime.ofInstant(time, ZoneId.systemDefault()))) + ZonedDateTime.ofInstant(time.time(), ZoneId.systemDefault()))) .thenAcceptAsync(nullValue -> reActorSystem.shutDown()); } } diff --git a/examples/src/main/java/io/reacted/examples/communication/ask/TimeReply.java b/examples/src/main/java/io/reacted/examples/communication/ask/TimeReply.java new file mode 100644 index 00000000..3cdd581c --- /dev/null +++ b/examples/src/main/java/io/reacted/examples/communication/ask/TimeReply.java @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2023 , [ pierre@reacted.io ] + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + +package io.reacted.examples.communication.ask; + +import io.reacted.core.serialization.ReActedMessage; + +import java.time.Instant; + +public record TimeReply(Instant time) implements ReActedMessage { } diff --git a/examples/src/main/java/io/reacted/examples/communication/tell/ping/SendMessagesApp.java b/examples/src/main/java/io/reacted/examples/communication/tell/ping/SendMessagesApp.java index 62ac7d91..10fff74c 100644 --- a/examples/src/main/java/io/reacted/examples/communication/tell/ping/SendMessagesApp.java +++ b/examples/src/main/java/io/reacted/examples/communication/tell/ping/SendMessagesApp.java @@ -9,6 +9,7 @@ package io.reacted.examples.communication.tell.ping; import io.reacted.core.reactorsystem.ReActorRef; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.examples.ExampleUtils; import java.io.FileNotFoundException; @@ -43,7 +44,7 @@ public static void main(String[] args) throws InterruptedException, FileNotFound .parallel() //Tell and apublish are functionally the same if we do not care about the return value //apublish brings more overhead because of the acking system - .forEach(msgNum -> newReActorReference.apublish("Ping Request" + pingDelim + msgNum)); + .forEach(msgNum -> newReActorReference.apublish(ReActedMessage.of("Ping Request" + pingDelim + msgNum))); TimeUnit.SECONDS.sleep(1); simpleReActorSystem.shutDown(); } diff --git a/examples/src/main/java/io/reacted/examples/communication/tell/ping/SimpleTestReActor.java b/examples/src/main/java/io/reacted/examples/communication/tell/ping/SimpleTestReActor.java index 7f416740..ab1e3bba 100644 --- a/examples/src/main/java/io/reacted/examples/communication/tell/ping/SimpleTestReActor.java +++ b/examples/src/main/java/io/reacted/examples/communication/tell/ping/SimpleTestReActor.java @@ -9,16 +9,17 @@ package io.reacted.examples.communication.tell.ping; import io.reacted.core.config.reactors.ReActorConfig; -import io.reacted.core.runtime.Dispatcher; -import io.reacted.core.typedsubscriptions.TypedSubscription; import io.reacted.core.mailboxes.UnboundedMbox; import io.reacted.core.messages.reactors.ReActorInit; import io.reacted.core.messages.reactors.ReActorStop; import io.reacted.core.reactors.ReActions; import io.reacted.core.reactors.ReActor; import io.reacted.core.reactorsystem.ReActorContext; -import io.reacted.patterns.ObjectUtils; +import io.reacted.core.runtime.Dispatcher; +import io.reacted.core.serialization.ReActedMessage; +import io.reacted.core.typedsubscriptions.TypedSubscription; import io.reacted.patterns.NonNullByDefault; +import io.reacted.patterns.ObjectUtils; import io.reacted.patterns.Try; import javax.annotation.Nonnull; @@ -45,12 +46,12 @@ public ReActions getReActions() { .reAct(ReActorStop.class, (ctx, stop) -> ctx.logInfo("ReActor Stopped! Received {}/{} pings", receivedPings, expectedMessages)) .reAct(PreparationRequest.class, (ctx, prepReq) -> ctx.logInfo("ReActor is ready!")) - .reAct(String.class, this::onPing) + .reAct(ReActedMessage.StringMessage.class, this::onPing) .build(); } - private void onPing(ReActorContext ctx, String ping) { - Try.ofRunnable(() -> ctx.logInfo("Received ping {} on dispatcher {}", ping.split(splitter)[1].trim(), + private void onPing(ReActorContext ctx, ReActedMessage.StringMessage ping) { + Try.ofRunnable(() -> ctx.logInfo("Received ping {} on dispatcher {}", ping.toString().split(splitter)[1].trim(), Thread.currentThread().getName())) .ifError(error -> ctx.logError("Illegal ping format received", error)); receivedPings++; diff --git a/examples/src/main/java/io/reacted/examples/communication/tell/pingpong/Ping.java b/examples/src/main/java/io/reacted/examples/communication/tell/pingpong/Ping.java index ee00e7e1..73531f72 100644 --- a/examples/src/main/java/io/reacted/examples/communication/tell/pingpong/Ping.java +++ b/examples/src/main/java/io/reacted/examples/communication/tell/pingpong/Ping.java @@ -8,7 +8,21 @@ package io.reacted.examples.communication.tell.pingpong; +import io.reacted.core.serialization.Deserializer; import io.reacted.core.serialization.ReActedMessage; +import io.reacted.core.serialization.Serializer; -record Ping(int pingValue) implements ReActedMessage { +class Ping implements ReActedMessage { + int pingValue; + + Ping(int pingValue) { this.pingValue = pingValue; } + @Override + public void encode(Serializer serializer) { + serializer.put(pingValue); + } + + @Override + public void decode(Deserializer deserializer) { + this.pingValue = deserializer.getInt(); + } } diff --git a/examples/src/main/java/io/reacted/examples/communication/tell/pingpong/PongReActor.java b/examples/src/main/java/io/reacted/examples/communication/tell/pingpong/PongReActor.java index 4107de97..45aec9d9 100644 --- a/examples/src/main/java/io/reacted/examples/communication/tell/pingpong/PongReActor.java +++ b/examples/src/main/java/io/reacted/examples/communication/tell/pingpong/PongReActor.java @@ -46,11 +46,11 @@ public ReActorConfig getConfig() { } public void onPing(ReActorContext ctx, Ping ping) { - System.out.printf("Pong received a ping for seq %d%n", ping.pingValue()); + System.out.printf("Pong received a ping for seq %d%n", ping.pingValue); //Schedule a reply after 1 second pongTimer.schedule(new TimerTask() { @Override - public void run() { ctx.reply(new Pong(ping.pingValue())); } + public void run() { ctx.reply(new Pong(ping.pingValue)); } }, 1000); } diff --git a/examples/src/main/java/io/reacted/examples/flow/ReducingExample.java b/examples/src/main/java/io/reacted/examples/flow/ReducingExample.java index bb9b3279..1ca62d22 100644 --- a/examples/src/main/java/io/reacted/examples/flow/ReducingExample.java +++ b/examples/src/main/java/io/reacted/examples/flow/ReducingExample.java @@ -11,6 +11,7 @@ import io.reacted.core.config.dispatchers.DispatcherConfig; import io.reacted.core.config.reactorsystem.ReActorSystemConfig; import io.reacted.core.reactorsystem.ReActorSystem; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.core.services.LoadBalancingPolicies; import io.reacted.flow.ReActedGraph; import io.reacted.flow.operators.map.MapOperatorConfig; @@ -25,7 +26,10 @@ public class ReducingExample { private static final Logger LOGGER = LoggerFactory.getLogger(ReducingExample.class); public static void main(String[] args) throws InterruptedException { - var inputData = List.of(1, 2, 3, 4); + var inputData = List.of(new ReActedMessage.IntMessage(1), + new ReActedMessage.IntMessage(2), + new ReActedMessage.IntMessage(3), + new ReActedMessage.IntMessage(4)); var graphDispatcher = "FlowProcessor"; var system = new ReActorSystem(ReActorSystemConfig.newBuilder() .setReactorSystemName("ReducingSystem") @@ -43,14 +47,17 @@ public static void main(String[] args) throws InterruptedException { .setReActorName("Mapper") .setRouteesNum(2) .setInputStreams(List.of(inputData.stream())) - .setLoadBalancingPolicy(LoadBalancingPolicies.partitionBy(message -> ((int)message)%2)) - .setMapper(number -> List.of(String.valueOf((int)number))) + .setLoadBalancingPolicy(LoadBalancingPolicies.partitionBy(message -> ((ReActedMessage.IntMessage)message).getPayload() % 2)) + .setMapper(number -> List.of(ReActedMessage.of(String.valueOf((int)number)))) .setOutputOperators("Reducer") .build()) .addOperator(ReduceOperatorConfig.newBuilder() .setReActorName("Reducer") - .setReductionRules(Map.of(String.class, (long )inputData.size())) - .setReducer(payloads -> List.of(String.join(",", (List)payloads.get(String.class)))) + .setReductionRules(Map.of(ReActedMessage.StringMessage.class, (long )inputData.size())) + .setReducer(payloads -> List.of(new ReActedMessage.StringMessage(String.join(",", ((List)payloads.get(ReActedMessage.StringMessage.class)) + .stream() + .map(ReActedMessage.StringMessage::toString) + .toList())))) .setOutputOperators("Printer") .build()) .addOperator(MapOperatorConfig.newBuilder() diff --git a/examples/src/main/java/io/reacted/examples/httpserver/ReactiveServer.java b/examples/src/main/java/io/reacted/examples/httpserver/ReactiveServer.java index 269a057a..9686031c 100644 --- a/examples/src/main/java/io/reacted/examples/httpserver/ReactiveServer.java +++ b/examples/src/main/java/io/reacted/examples/httpserver/ReactiveServer.java @@ -148,15 +148,16 @@ private void onInit(ReActorContext ctx, ReActorInit init) { .ifError(error -> handleError(ctx, error)); } - private void onDataPublisher(ReActorContext ctx, ReactedSubmissionPublisher publisher) { - publisher.subscribe(ReActedSubscriptionConfig.newBuilder() - .setSubscriberName("sub_" + ctx.getSender().getReActorId().getReActorName()) - .setBufferSize(ReactiveServer.BATCH_BUFFER_SIZE) - .build(), getNexDataConsumer(ctx)) + private void onDataPublisher(ReActorContext ctx, ReactedSubmissionPublisher publisher) { + var publisherCfg = ReActedSubscriptionConfig.newBuilder() + .setSubscriberName("sub_" + ctx.getSender().getReActorId().getReActorName()) + .setBufferSize(ReactiveServer.BATCH_BUFFER_SIZE) + .build(); + publisher.subscribe(publisherCfg, getNexDataConsumer(ctx)) .thenAccept(noVal -> ctx.reply(new PublishRequest(Duration.ofNanos(1)))); } - private Flow.Subscriber getNexDataConsumer(ReActorContext ctx) { + private Flow.Subscriber getNexDataConsumer(ReActorContext ctx) { return new Flow.Subscriber<>() { @Nullable private Flow.Subscription subscription; @@ -167,9 +168,9 @@ public void onSubscribe(Flow.Subscription subscription) { } @Override - public void onNext(String item) { + public void onNext(ReActedMessage.StringMessage item) { try { - sendData(item); + sendData(item.toString()); Objects.requireNonNull(subscription).request(1); } catch (Exception exc) { onError(exc); @@ -222,7 +223,7 @@ private static Try detectAnyError(Try first, Try< private static class ReadFileWorker implements ReActor { private final ReActions readFileWorkerBehavior; private final ReActorConfig readFileWorkerCfg; - private final ReactedSubmissionPublisher dataPublisher; + private final ReactedSubmissionPublisher dataPublisher; @Nullable private InputStreamReader fileLines; @@ -285,7 +286,7 @@ private void readFileLine(ReActorContext ctx, InputStreamReader file, Duration b dataPublisher.close(); return; } - if (dataPublisher.submit(new String(buffer, 0, read)).isBackpressureRequired()) { + if (dataPublisher.submit(new ReActedMessage.StringMessage(new String(buffer, 0, read))).isBackpressureRequired()) { ctx.rescheduleMessage(new PublishRequest(backpressureDelay.multipliedBy(2)), backpressureDelay.multipliedBy(2)); } else { diff --git a/examples/src/main/java/io/reacted/examples/quickstart/GreeterService.java b/examples/src/main/java/io/reacted/examples/quickstart/GreeterService.java index 4b9f980e..05f7aa06 100644 --- a/examples/src/main/java/io/reacted/examples/quickstart/GreeterService.java +++ b/examples/src/main/java/io/reacted/examples/quickstart/GreeterService.java @@ -37,7 +37,7 @@ public ReActions getReActions() { ctx.logInfo("{} was born", ctx.getSelf().getReActorId().getReActorName())) .reAct(GreetingsRequest.class, (ctx, greetingsRequest) -> - ctx.reply("Hello from " + GreeterService.class.getSimpleName())) + ctx.reply(ReActedMessage.of("Hello from " + GreeterService.class.getSimpleName()))) .build(); } static final class GreetingsRequest implements ReActedMessage { } diff --git a/examples/src/main/java/io/reacted/examples/quickstart/QuickstartClient.java b/examples/src/main/java/io/reacted/examples/quickstart/QuickstartClient.java index 2fa26d6d..c6903657 100644 --- a/examples/src/main/java/io/reacted/examples/quickstart/QuickstartClient.java +++ b/examples/src/main/java/io/reacted/examples/quickstart/QuickstartClient.java @@ -11,6 +11,7 @@ import io.reacted.core.config.reactorsystem.ReActorSystemConfig; import io.reacted.core.messages.services.BasicServiceDiscoverySearchFilter; import io.reacted.core.reactorsystem.ReActorSystem; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.drivers.channels.kafka.KafkaDriver; import io.reacted.drivers.channels.kafka.KafkaDriverConfig; import io.reacted.drivers.serviceregistries.zookeeper.ZooKeeperDriver; @@ -47,9 +48,9 @@ public static void main(String[] args) { showOffClientSystem.logInfo("No services found, exiting"); } else { var serviceGate = serviceDiscoveryReply.getServiceGates().iterator().next(); - showOffClientSystem.logInfo(serviceGate.ask(new GreeterService.GreetingsRequest(), String.class, "Request to service") + showOffClientSystem.logInfo(serviceGate.ask(new GreeterService.GreetingsRequest(), ReActedMessage.StringMessage.class, "Request to service") .toCompletableFuture() - .join()); + .join().toString()); } showOffClientSystem.shutDown(); } diff --git a/examples/src/main/java/io/reacted/examples/replay/SystemReplayApp.java b/examples/src/main/java/io/reacted/examples/replay/SystemReplayApp.java index 3f2ac8ef..80d2e854 100644 --- a/examples/src/main/java/io/reacted/examples/replay/SystemReplayApp.java +++ b/examples/src/main/java/io/reacted/examples/replay/SystemReplayApp.java @@ -14,11 +14,13 @@ import io.reacted.core.messages.reactors.DeliveryStatus; import io.reacted.core.reactors.ReActions; import io.reacted.core.reactorsystem.ReActorSystem; +import io.reacted.core.serialization.ReActedMessage; import io.reacted.core.typedsubscriptions.TypedSubscription; import io.reacted.drivers.channels.chroniclequeue.CQLocalDriver; import io.reacted.drivers.channels.chroniclequeue.CQLocalDriverConfig; import io.reacted.drivers.channels.replay.ReplayLocalDriver; import io.reacted.examples.ExampleUtils; + import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; import java.util.concurrent.TimeUnit; @@ -62,7 +64,7 @@ public static void main(String[] args) throws InterruptedException { .orElseSneakyThrow(); if (IntStream.range(0, 5) - .mapToObj(cycle -> "Message number " + cycle) + .mapToObj(cycle -> ReActedMessage.of("Message number " + cycle)) .map(echoReference::apublish) .map(CompletionStage::toCompletableFuture) .map(CompletableFuture::join) diff --git a/examples/src/main/java/io/reacted/examples/replay/SystemReplayAskApp.java b/examples/src/main/java/io/reacted/examples/replay/SystemReplayAskApp.java index cba8f0c5..d4196aad 100644 --- a/examples/src/main/java/io/reacted/examples/replay/SystemReplayAskApp.java +++ b/examples/src/main/java/io/reacted/examples/replay/SystemReplayAskApp.java @@ -10,12 +10,13 @@ import com.google.common.base.Strings; import io.reacted.core.config.reactors.ReActorConfig; -import io.reacted.core.runtime.Dispatcher; -import io.reacted.core.typedsubscriptions.TypedSubscription; import io.reacted.core.mailboxes.UnboundedMbox; import io.reacted.core.reactors.ReActions; import io.reacted.core.reactorsystem.ReActorRef; import io.reacted.core.reactorsystem.ReActorSystem; +import io.reacted.core.runtime.Dispatcher; +import io.reacted.core.serialization.ReActedMessage; +import io.reacted.core.typedsubscriptions.TypedSubscription; import io.reacted.drivers.channels.chroniclequeue.CQLocalDriver; import io.reacted.drivers.channels.chroniclequeue.CQLocalDriverConfig; import io.reacted.drivers.channels.replay.ReplayLocalDriver; @@ -43,6 +44,7 @@ public static void main(String[] args) { var echoReActions = ReActions.newBuilder() .reAct((ctx, payload) -> ctx.getSender() .publish(ReActorRef.NO_REACTOR_REF, + ReActedMessage.of( String.format("%s - Received %s from %s @ %s%n", Instant.now().toString(), payload.toString(), @@ -50,7 +52,7 @@ public static void main(String[] args) { .getReActorName(), ctx.getReActorSystem() .getSystemConfig() - .getReActorSystemName()))) + .getReActorSystemName())))) .build(); var echoReActorConfig = ReActorConfig.newBuilder() .setReActorName("EchoReActor") @@ -62,7 +64,7 @@ public static void main(String[] args) { var echoReference = recordedReactorSystem.spawn(echoReActions, echoReActorConfig) .orElseSneakyThrow(); - echoReference.ask("I am an ask", String.class, "AskRequest") + echoReference.ask(ReActedMessage.of("I am an ask"), ReActedMessage.StringMessage.class, "AskRequest") .thenAccept(System.out::println) .toCompletableFuture() .join(); @@ -78,7 +80,7 @@ public static void main(String[] args) { .initReActorSystem(); //Once the reactor will be created, the system will notify that and will begin its replay echoReference = replayedReActorSystem.spawn(echoReActions, echoReActorConfig).orElseSneakyThrow(); - echoReference.ask("I am an ask", String.class, "AskRequest") + echoReference.ask(ReActedMessage.of("I am an ask"), ReActedMessage.StringMessage.class, "AskRequest") .thenAccept(System.out::println) .toCompletableFuture() .join(); diff --git a/examples/src/main/java/io/reacted/examples/services/ServicePublicationApp.java b/examples/src/main/java/io/reacted/examples/services/ServicePublicationApp.java index 45ba809c..8657d6d3 100644 --- a/examples/src/main/java/io/reacted/examples/services/ServicePublicationApp.java +++ b/examples/src/main/java/io/reacted/examples/services/ServicePublicationApp.java @@ -10,21 +10,21 @@ import io.reacted.core.config.dispatchers.DispatcherConfig; import io.reacted.core.config.reactors.ReActorConfig; -import io.reacted.core.messages.services.BasicServiceDiscoverySearchFilter; -import io.reacted.core.services.LoadBalancingPolicies; -import io.reacted.core.typedsubscriptions.TypedSubscription; +import io.reacted.core.config.reactors.ServiceConfig; import io.reacted.core.config.reactorsystem.ReActorSystemConfig; import io.reacted.core.drivers.local.SystemLocalDrivers; import io.reacted.core.mailboxes.BoundedMbox; +import io.reacted.core.messages.services.BasicServiceDiscoverySearchFilter; import io.reacted.core.messages.services.ServiceDiscoveryReply; import io.reacted.core.messages.services.ServiceDiscoveryRequest; import io.reacted.core.reactors.ReActions; import io.reacted.core.reactors.ReActor; import io.reacted.core.reactorsystem.ReActorContext; import io.reacted.core.reactorsystem.ReActorRef; -import io.reacted.core.config.reactors.ServiceConfig; import io.reacted.core.reactorsystem.ReActorSystem; +import io.reacted.core.services.LoadBalancingPolicies; import io.reacted.core.services.SelectionType; +import io.reacted.core.typedsubscriptions.TypedSubscription; import io.reacted.patterns.UnChecked; import javax.annotation.Nonnull; @@ -107,7 +107,7 @@ public static void main(String[] args) { //get the first gate available .thenApply(services -> services.iterator().next()) //Ask the service for the time - .thenCompose(gate -> gate.ask(new TimeRequest(), ZonedDateTime.class, "Request the time")) + .thenCompose(gate -> gate.ask(new TimeRequest(), TimeMessage.class, "Request the time")) //print the answer .thenAcceptAsync(System.out::println) //kill the reactor system @@ -117,6 +117,7 @@ public static void main(String[] args) { private static void onTimeRequest(ReActorContext ctx, TimeRequest timeRequest) { ctx.logInfo("{} received {}", ctx.getSelf().getReActorId().getReActorName(), timeRequest.getClass().getSimpleName()); - ctx.reply(ReActorRef.NO_REACTOR_REF, ZonedDateTime.ofInstant(Instant.now(), ZoneId.systemDefault())); + ctx.reply(ReActorRef.NO_REACTOR_REF, + new TimeMessage(ZonedDateTime.ofInstant(Instant.now(), ZoneId.systemDefault()))); } } diff --git a/examples/src/main/java/io/reacted/examples/services/TimeMessage.java b/examples/src/main/java/io/reacted/examples/services/TimeMessage.java new file mode 100644 index 00000000..270f5121 --- /dev/null +++ b/examples/src/main/java/io/reacted/examples/services/TimeMessage.java @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2023 , [ pierre@reacted.io ] + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. + */ + +package io.reacted.examples.services; + +import io.reacted.core.serialization.ReActedMessage; + +import java.time.ZonedDateTime; + +public record TimeMessage(ZonedDateTime time) implements ReActedMessage { } diff --git a/examples/src/main/java/io/reacted/examples/webappbackend/db/StorageMessages.java b/examples/src/main/java/io/reacted/examples/webappbackend/db/StorageMessages.java index 220c9b60..ceec31e6 100644 --- a/examples/src/main/java/io/reacted/examples/webappbackend/db/StorageMessages.java +++ b/examples/src/main/java/io/reacted/examples/webappbackend/db/StorageMessages.java @@ -30,8 +30,26 @@ public QueryRequest(String key) { } } - public static class StoreError extends Throwable { - public StoreError(Throwable anyError) { super(anyError); } + public static class StoreError implements ReActedMessage { + private Throwable error; + public StoreError() { } + public StoreError(Throwable anyError) { this.error = anyError; } + + @Override + public Class getMessageType() { return StoreError.class; } + + @Override + public void encode(Serializer serializer) { + serializer.putObject(error); + } + + @Override + public void decode(Deserializer deserializer) { + this.error = deserializer.getObject(); + } + + @Override + public String toString() { return "StoreError{" + "error=" + error + '}'; } } public static class StoreReply implements ReActedMessage { } From c7810d4cba27a9b14aaedfa25af37cd88cbf0842 Mon Sep 17 00:00:00 2001 From: wireknight Date: Wed, 5 Apr 2023 01:40:12 +0200 Subject: [PATCH 15/16] Fixing main core with the new de/serialization abstraction --- .../chroniclequeue/CQDeserializer.java | 2 +- .../chroniclequeue/CQLocalDriver.java | 175 +++++------------- .../chroniclequeue/CQRemoteDriver.java | 61 +++--- .../channels/replay/ReplayLocalDriver.java | 46 +++-- 4 files changed, 102 insertions(+), 182 deletions(-) diff --git a/drivers/src/main/java/io/reacted/drivers/channels/chroniclequeue/CQDeserializer.java b/drivers/src/main/java/io/reacted/drivers/channels/chroniclequeue/CQDeserializer.java index 6e9b648a..fe98777a 100644 --- a/drivers/src/main/java/io/reacted/drivers/channels/chroniclequeue/CQDeserializer.java +++ b/drivers/src/main/java/io/reacted/drivers/channels/chroniclequeue/CQDeserializer.java @@ -18,7 +18,7 @@ public class CQDeserializer implements Deserializer { private WireIn input; - CQDeserializer(WireIn input) { setDeserializerInput(input); } + public CQDeserializer(WireIn input) { setDeserializerInput(input); } CQDeserializer setDeserializerInput(WireIn input) { this.input = input; return this; } diff --git a/drivers/src/main/java/io/reacted/drivers/channels/chroniclequeue/CQLocalDriver.java b/drivers/src/main/java/io/reacted/drivers/channels/chroniclequeue/CQLocalDriver.java index 17509605..43b23248 100644 --- a/drivers/src/main/java/io/reacted/drivers/channels/chroniclequeue/CQLocalDriver.java +++ b/drivers/src/main/java/io/reacted/drivers/channels/chroniclequeue/CQLocalDriver.java @@ -9,9 +9,7 @@ package io.reacted.drivers.channels.chroniclequeue; import io.reacted.core.config.ChannelId; -import io.reacted.core.drivers.DriverCtx; import io.reacted.core.drivers.system.LocalDriver; -import io.reacted.core.drivers.system.ReActorSystemDriver; import io.reacted.core.messages.AckingPolicy; import io.reacted.core.messages.reactors.DeliveryStatus; import io.reacted.core.reactors.ReActorId; @@ -20,7 +18,9 @@ import io.reacted.core.reactorsystem.ReActorSystem; import io.reacted.core.reactorsystem.ReActorSystemId; import io.reacted.core.reactorsystem.ReActorSystemRef; +import io.reacted.core.serialization.Deserializer; import io.reacted.core.serialization.ReActedMessage; +import io.reacted.core.serialization.Serializer; import io.reacted.patterns.NonNullByDefault; import io.reacted.patterns.Try; import io.reacted.patterns.UnChecked; @@ -28,21 +28,20 @@ import net.openhft.chronicle.queue.ExcerptTailer; import net.openhft.chronicle.queue.RollCycles; import net.openhft.chronicle.threads.Pauser; -import net.openhft.chronicle.wire.WireIn; -import net.openhft.chronicle.wire.WireOut; +import net.openhft.chronicle.wire.DocumentContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.annotation.Nullable; import java.util.Objects; import java.util.Properties; -import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; @NonNullByDefault public class CQLocalDriver extends LocalDriver { private static final Logger LOGGER = LoggerFactory.getLogger(CQLocalDriver.class); + private final ThreadLocal serializerThreadLocal = ThreadLocal.withInitial(() -> null); @Nullable private ChronicleQueue chronicle; @Nullable @@ -99,9 +98,14 @@ CompletionStage sendAsyncMessage(ReActorRef source, ReActorConte sendMessage(ReActorRef source, ReActorContext destinationCtx, ReActorRef destination, long seqNum, ReActorSystemId reActorSystemId, AckingPolicy ackingPolicy, PayloadT message) { try { - chronicle.acquireAppender() - .writeDocument(w -> writeMessage(w, source, destination, seqNum, reActorSystemId, - ackingPolicy, message)); + Serializer serializer = serializerThreadLocal.get(); + if (serializer == null) { + serializer = new CQSerializer(Objects.requireNonNull(chronicle.acquireAppender() + .wire())); + serializerThreadLocal.set(serializer); + } + writeMessage(serializer, source, destination, seqNum, reActorSystemId, + ackingPolicy, message); return DeliveryStatus.SENT; } catch (Exception anyException) { getLocalReActorSystem().logError("Unable to send message {}", message, anyException); @@ -116,137 +120,54 @@ public CompletionStage> cleanDriverLoop() { private void chronicleMainLoop(ExcerptTailer tailer) { var waitForNextMsg = Pauser.balanced(); - DriverCtx ctx = Objects.requireNonNull(ReActorSystemDriver.getDriverCtx()); - while(!Thread.currentThread().isInterrupted()) { - try { - if (tailer.readDocument(document -> readMessage(document, ctx))) { - waitForNextMsg.reset(); - } else { - waitForNextMsg.pause(); + try(DocumentContext documentContext = tailer.readingDocument()) { + Deserializer deserializer = new CQDeserializer(Objects.requireNonNull(documentContext.wire())); + while (!Thread.currentThread().isInterrupted()) { + try { + if (documentContext.isPresent()) { + readMessage(deserializer); + waitForNextMsg.reset(); + } else { + waitForNextMsg.pause(); + } + } + catch (Exception anyException) { + LOGGER.error("Unable to decode data", anyException); } - } catch (Exception anyException) { - LOGGER.error("Unable to decode data", anyException); } } } - private void readMessage(WireIn in, DriverCtx driverCtx) { - in.read().marshallable(m -> offerMessage(readReActorRef(in, driverCtx), - readReActorRef(in, driverCtx), - readSequenceNumber(in), - readReActorSystemId(in), - readAckingPolicy(in), - readPayload(in))); + private void readMessage(Deserializer in) { + offerMessage(readReActorRef(in), + readReActorRef(in), + in.getLong(), + readReActorSystemId(in), + in.getEnum(AckingPolicy.class), + in.getObject()); } public static - void writeMessage(WireOut out, ReActorRef source, ReActorRef destination, long seqNum, + void writeMessage(Serializer out, ReActorRef source, ReActorRef destination, long seqNum, ReActorSystemId localReActorSystemId, AckingPolicy ackingPolicy, PayloadT payload) { - out.write() - .marshallable(m -> writePayload(writeAckingPolicy(writeReActorSystemId(writeSequenceNumber(writeReActorRef(writeReActorRef(m, source), - destination), - seqNum), - localReActorSystemId), - ackingPolicy), - payload)); - } - public static WireOut writeReActorRef(WireOut out, ReActorRef reActorRef) { - return writeReActorSystemRef(writeReActorId(out, reActorRef.getReActorId()), - reActorRef.getReActorSystemRef()); + source.encode(out); + destination.encode(out); + out.put(seqNum); + localReActorSystemId.encode(out); + out.putEnum(ackingPolicy); + out.putObject(payload); } - public static ReActorRef readReActorRef(WireIn in, DriverCtx driverCtx) { - ReActorId reActorId = readReActorId(in); - ReActorSystemRef reActorSystemRef = readReActorSystemRef(in, driverCtx); + public static ReActorRef readReActorRef(Deserializer in) { + ReActorId reActorId = new ReActorId(); + reActorId.decode(in); + ReActorSystemRef reActorSystemRef = new ReActorSystemRef(); + reActorSystemRef.decode(in); return new ReActorRef(reActorId, reActorSystemRef) .setHashCode(Objects.hash(reActorId, reActorSystemRef)); } - - public static WireOut writeReActorSystemRef(WireOut out, ReActorSystemRef reActorSystemRef) { - return writeChannelId(writeReActorSystemId(out, reActorSystemRef.getReActorSystemId()), - reActorSystemRef.getChannelId()); - } - - public static ReActorSystemRef readReActorSystemRef(WireIn in, DriverCtx ctx) { - ReActorSystemRef reActorSystemRef = new ReActorSystemRef(); - ReActorSystemId reActorSystemId = readReActorSystemId(in); - ChannelId channelId = readChannelId(in); - ReActorSystemRef.setGateForReActorSystem(reActorSystemRef, reActorSystemId, channelId, ctx); - return reActorSystemRef; - } - public static WireOut writePayload(WireOut wireOut, PayloadT payloadT) { - return wireOut.write().object(payloadT); - } - - @SuppressWarnings("unchecked") - public static PayloadT readPayload(WireIn in) { - return (PayloadT)in.read().object(); - } - public static WireOut writeSequenceNumber(WireOut out, long sequenceNumber) { - return out.write().int64(sequenceNumber); - } - - public static long readSequenceNumber(WireIn in) { - return in.read().int64(); - } - public static WireOut writeReActorSystemId(WireOut out, ReActorSystemId reActorSystemId) { - return reActorSystemId == ReActorSystemId.NO_REACTORSYSTEM_ID - ? out.write().int8(ReActorSystemId.NO_REACTORSYSTEM_ID_MARKER) - : out.write().int8(ReActorSystemId.COMMON_REACTORSYSTEM_ID_MARKER) - .write().writeString(reActorSystemId.getReActorSystemName()); - } - - public static ReActorSystemId readReActorSystemId(WireIn in) { - if (in.read().int8() == ReActorSystemId.NO_REACTORSYSTEM_ID_MARKER) { - return ReActorSystemId.NO_REACTORSYSTEM_ID; - } - return new ReActorSystemId(in.read().readString()); - } - public static WireOut writeChannelId(WireOut out, ChannelId channelId) { - return out.write().int8(channelId.getChannelType().ordinal()) - .write().writeString(channelId.getChannelName()); - } - - public static ChannelId readChannelId(WireIn in) { - return ChannelId.ChannelType.forOrdinal(in.read().int8()) - .forChannelName(in.read().readString()); - } - - public static WireOut writeAckingPolicy(WireOut out, AckingPolicy ackingPolicy) { - return out.write().int8(ackingPolicy.ordinal()); - } - public static AckingPolicy readAckingPolicy(WireIn in) { - return AckingPolicy.forOrdinal(in.read().int8()); - } - public static WireOut writeReActorId(WireOut out, ReActorId reActorId) { - return reActorId == ReActorId.NO_REACTOR_ID - ? out.write().int8(ReActorId.NO_REACTOR_ID_MARKER) - : writeUUID(out.write().int8(ReActorId.COMMON_REACTOR_ID_MARKER) - .write().writeString(reActorId.getReActorName()), reActorId.getReActorUUID()); - } - - public static ReActorId readReActorId(WireIn in) { - if (in.read().int8() == ReActorId.NO_REACTOR_ID_MARKER) { - return ReActorId.NO_REACTOR_ID; - } - String reactorName = in.read().readString(); - UUID uuid = readUUID(in); - return new ReActorId().setReActorName(reactorName) - .setReActorUUID(uuid) - .setHashCode(Objects.hash(uuid, reactorName)); - - } - - public static WireOut writeUUID(WireOut out, UUID uuid) { - return out.write().int64(uuid.getLeastSignificantBits()) - .write().int64(uuid.getMostSignificantBits()); - } - - public static UUID readUUID(WireIn in) { - long least = in.read().int64(); - long most = in.read().int64(); - return ReActorId.NO_REACTOR_ID_UUID.getLeastSignificantBits() == least && - ReActorId.NO_REACTOR_ID_UUID.getMostSignificantBits() == most - ? ReActorId.NO_REACTOR_ID_UUID - : new UUID(most, least); + public static ReActorSystemId readReActorSystemId(Deserializer in) { + ReActorSystemId reActorSystemId = new ReActorSystemId(); + reActorSystemId.decode(in); + return reActorSystemId; } } diff --git a/drivers/src/main/java/io/reacted/drivers/channels/chroniclequeue/CQRemoteDriver.java b/drivers/src/main/java/io/reacted/drivers/channels/chroniclequeue/CQRemoteDriver.java index 0b9a46b0..ba728a13 100644 --- a/drivers/src/main/java/io/reacted/drivers/channels/chroniclequeue/CQRemoteDriver.java +++ b/drivers/src/main/java/io/reacted/drivers/channels/chroniclequeue/CQRemoteDriver.java @@ -9,8 +9,6 @@ package io.reacted.drivers.channels.chroniclequeue; import io.reacted.core.config.ChannelId; -import io.reacted.core.drivers.DriverCtx; -import io.reacted.core.drivers.system.ReActorSystemDriver; import io.reacted.core.drivers.system.RemotingDriver; import io.reacted.core.messages.AckingPolicy; import io.reacted.core.messages.reactors.DeliveryStatus; @@ -18,29 +16,29 @@ import io.reacted.core.reactorsystem.ReActorRef; import io.reacted.core.reactorsystem.ReActorSystem; import io.reacted.core.reactorsystem.ReActorSystemId; +import io.reacted.core.serialization.Deserializer; import io.reacted.core.serialization.ReActedMessage; +import io.reacted.core.serialization.Serializer; import io.reacted.patterns.NonNullByDefault; import io.reacted.patterns.Try; import io.reacted.patterns.UnChecked; import net.openhft.chronicle.queue.ChronicleQueue; -import net.openhft.chronicle.queue.ExcerptAppender; import net.openhft.chronicle.queue.ExcerptTailer; import net.openhft.chronicle.threads.Pauser; -import net.openhft.chronicle.wire.WireIn; +import net.openhft.chronicle.wire.DocumentContext; import javax.annotation.Nullable; import java.util.Objects; import java.util.Properties; import java.util.concurrent.CompletableFuture; -import static io.reacted.drivers.channels.chroniclequeue.CQLocalDriver.readAckingPolicy; -import static io.reacted.drivers.channels.chroniclequeue.CQLocalDriver.readPayload; import static io.reacted.drivers.channels.chroniclequeue.CQLocalDriver.readReActorRef; import static io.reacted.drivers.channels.chroniclequeue.CQLocalDriver.readReActorSystemId; -import static io.reacted.drivers.channels.chroniclequeue.CQLocalDriver.readSequenceNumber; @NonNullByDefault public class CQRemoteDriver extends RemotingDriver { + private final ThreadLocal serializerThreadLocal = ThreadLocal.withInitial(() -> null); + @Nullable private ChronicleQueue chronicle; @Nullable @@ -93,34 +91,43 @@ public ChannelId getChannelId() { DeliveryStatus sendMessage(ReActorRef source, ReActorContext destinationCtx, ReActorRef destination, long seqNum, ReActorSystemId reActorSystemId, AckingPolicy ackingPolicy, PayloadT message) { - return sendMessage(getLocalReActorSystem(), - Objects.requireNonNull(chronicle).acquireAppender(), + Serializer serializer = serializerThreadLocal.get(); + if (serializer == null) { + serializer = new CQSerializer(Objects.requireNonNull(chronicle.acquireAppender() + .wire())); + serializerThreadLocal.set(serializer); + } + return sendMessage(getLocalReActorSystem(), serializer, source, destination, seqNum, ackingPolicy, message); } private void cqRemoteDriverMainLoop(ExcerptTailer cqTailer, ChronicleQueue chronicle) { Pauser readPauser = Pauser.balanced(); - DriverCtx ctx = Objects.requireNonNull(ReActorSystemDriver.getDriverCtx()); - while (!Thread.currentThread().isInterrupted() && !chronicle.isClosed()) { - try { - if (cqTailer.readDocument(document -> readMessage(document, ctx))) { - readPauser.reset(); - } else { - readPauser.pause(); + try(DocumentContext documentContext = cqTailer.readingDocument()) { + Deserializer deserializer = new CQDeserializer(Objects.requireNonNull(documentContext.wire())); + while (!Thread.currentThread() + .isInterrupted() && !chronicle.isClosed()) { + try { + if (documentContext.isPresent()) { + readMessage(deserializer); + readPauser.reset(); + } else { + readPauser.pause(); + } + } catch (Exception anyException) { + getLocalReActorSystem().logError("Unable to properly decode message", anyException); } - } catch (Exception anyException) { - getLocalReActorSystem().logError("Unable to properly decode message", anyException); } } } private static - DeliveryStatus sendMessage(ReActorSystem localReActorSystem, ExcerptAppender cqAppender, + DeliveryStatus sendMessage(ReActorSystem localReActorSystem, Serializer serializer, ReActorRef source, ReActorRef destination, long seqNum, AckingPolicy ackingPolicy, PayloadT message) { try { - cqAppender.writeDocument(document -> CQLocalDriver.writeMessage(document, source, destination, - seqNum, localReActorSystem.getLocalReActorSystemId(), - ackingPolicy, message)); + CQLocalDriver.writeMessage(serializer, source, destination, + seqNum, localReActorSystem.getLocalReActorSystemId(), + ackingPolicy, message); return DeliveryStatus.SENT; } catch (Exception sendError) { localReActorSystem.logError("Error sending message {}", message.toString(), @@ -128,12 +135,8 @@ DeliveryStatus sendMessage(ReActorSystem localReActorSystem, ExcerptAppender cqA return DeliveryStatus.NOT_SENT; } } - private void readMessage(WireIn in, DriverCtx driverCtx) { - in.read("M").marshallable(m -> offerMessage(readReActorRef(in, driverCtx), - readReActorRef(in, driverCtx), - readSequenceNumber(in), - readReActorSystemId(in), - readAckingPolicy(in), - readPayload(in))); + private void readMessage(Deserializer in) { + offerMessage(readReActorRef(in), readReActorRef(in), in.getLong(), readReActorSystemId(in), + in.getEnum(AckingPolicy.class), in.getObject()); } } diff --git a/drivers/src/main/java/io/reacted/drivers/channels/replay/ReplayLocalDriver.java b/drivers/src/main/java/io/reacted/drivers/channels/replay/ReplayLocalDriver.java index dd3a2296..da07bfe0 100644 --- a/drivers/src/main/java/io/reacted/drivers/channels/replay/ReplayLocalDriver.java +++ b/drivers/src/main/java/io/reacted/drivers/channels/replay/ReplayLocalDriver.java @@ -9,9 +9,7 @@ package io.reacted.drivers.channels.replay; import io.reacted.core.config.ChannelId; -import io.reacted.core.drivers.DriverCtx; import io.reacted.core.drivers.system.LocalDriver; -import io.reacted.core.drivers.system.ReActorSystemDriver; import io.reacted.core.messages.AckingPolicy; import io.reacted.core.messages.Message; import io.reacted.core.messages.Recyclable; @@ -23,7 +21,9 @@ import io.reacted.core.reactorsystem.ReActorRef; import io.reacted.core.reactorsystem.ReActorSystem; import io.reacted.core.reactorsystem.ReActorSystemId; +import io.reacted.core.serialization.Deserializer; import io.reacted.core.serialization.ReActedMessage; +import io.reacted.drivers.channels.chroniclequeue.CQDeserializer; import io.reacted.drivers.channels.chroniclequeue.CQLocalDriverConfig; import io.reacted.patterns.NonNullByDefault; import io.reacted.patterns.Try; @@ -31,7 +31,7 @@ import net.openhft.chronicle.queue.ChronicleQueue; import net.openhft.chronicle.queue.ExcerptTailer; import net.openhft.chronicle.threads.Pauser; -import net.openhft.chronicle.wire.WireIn; +import net.openhft.chronicle.wire.DocumentContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -45,11 +45,8 @@ import java.util.concurrent.CompletionStage; import java.util.concurrent.ConcurrentHashMap; -import static io.reacted.drivers.channels.chroniclequeue.CQLocalDriver.readAckingPolicy; -import static io.reacted.drivers.channels.chroniclequeue.CQLocalDriver.readPayload; import static io.reacted.drivers.channels.chroniclequeue.CQLocalDriver.readReActorRef; import static io.reacted.drivers.channels.chroniclequeue.CQLocalDriver.readReActorSystemId; -import static io.reacted.drivers.channels.chroniclequeue.CQLocalDriver.readSequenceNumber; @NonNullByDefault public class ReplayLocalDriver extends LocalDriver { @@ -117,18 +114,21 @@ private void replayerMainLoop(ReActorSystem localReActorSystem, ChronicleQueue c Map emptyMap = new HashMap<>(); ExcerptTailer chronicleReader = chronicle.createTailer(); Map> dstToMessageBySeqNum = new HashMap<>(); - DriverCtx ctx = Objects.requireNonNull(ReActorSystemDriver.getDriverCtx()); Pauser pauser = Pauser.balanced(); - while (!Thread.currentThread().isInterrupted() && !chronicle.isClosed()) { - try { - if (chronicleReader.readDocument(in -> readMessage(in, ctx, localReActorSystem, emptyMap, - dstToMessageBySeqNum))) { - pauser.reset(); - } else { - pauser.pause(); + try(DocumentContext documentContext = chronicleReader.readingDocument()) { + Deserializer deserializer = new CQDeserializer(Objects.requireNonNull(documentContext.wire())); + while (!Thread.currentThread() + .isInterrupted() && !chronicle.isClosed()) { + try { + if (documentContext.isPresent()) { + readMessage(deserializer, localReActorSystem, emptyMap, dstToMessageBySeqNum); + pauser.reset(); + } else { + pauser.pause(); + } + } catch (Exception anyError) { + LOGGER.error("Error reading message from CQ", anyError); } - } catch (Exception anyError) { - LOGGER.error("Error reading message from CQ", anyError); } } } @@ -183,14 +183,10 @@ private boolean isReactorAlreadySpawned(ReActorRef sender) { return spawnedReActors.contains(sender.getReActorId()); } - private void readMessage(WireIn in, DriverCtx driverCtx, ReActorSystem localReActorSystem, Map emptyMap, Map> dstToMessageBySeqNum) { - in.read("M").marshallable(m -> onNewMessage(localReActorSystem, emptyMap, dstToMessageBySeqNum, - readReActorRef(in, driverCtx), - readReActorRef(in, driverCtx), - readSequenceNumber(in), - readReActorSystemId(in), - readAckingPolicy(in), - readPayload(in))); + private void readMessage(Deserializer in, ReActorSystem localReActorSystem, + Map emptyMap, Map> dstToMessageBySeqNum) { + onNewMessage(localReActorSystem, emptyMap, dstToMessageBySeqNum, + readReActorRef(in), readReActorRef(in), in.getLong(), readReActorSystemId(in), + in.getEnum(AckingPolicy.class), in.getObject()); } } From 371439ca400fb765c7609f2ee3a8fac73c440296 Mon Sep 17 00:00:00 2001 From: wireknight Date: Thu, 11 May 2023 21:55:49 +0200 Subject: [PATCH 16/16] Fixing main core with the new de/serialization abstraction --- .../channels/chroniclequeue/CQDeserializer.java | 2 +- .../drivers/channels/chroniclequeue/CQLocalDriver.java | 10 ++++++++-- .../drivers/channels/replay/ReplayLocalDriver.java | 9 +++++++-- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/src/main/java/io/reacted/drivers/channels/chroniclequeue/CQDeserializer.java b/drivers/src/main/java/io/reacted/drivers/channels/chroniclequeue/CQDeserializer.java index fe98777a..3f873147 100644 --- a/drivers/src/main/java/io/reacted/drivers/channels/chroniclequeue/CQDeserializer.java +++ b/drivers/src/main/java/io/reacted/drivers/channels/chroniclequeue/CQDeserializer.java @@ -18,7 +18,7 @@ public class CQDeserializer implements Deserializer { private WireIn input; - public CQDeserializer(WireIn input) { setDeserializerInput(input); } + public CQDeserializer() { } CQDeserializer setDeserializerInput(WireIn input) { this.input = input; return this; } diff --git a/drivers/src/main/java/io/reacted/drivers/channels/chroniclequeue/CQLocalDriver.java b/drivers/src/main/java/io/reacted/drivers/channels/chroniclequeue/CQLocalDriver.java index 43b23248..a3d30d3a 100644 --- a/drivers/src/main/java/io/reacted/drivers/channels/chroniclequeue/CQLocalDriver.java +++ b/drivers/src/main/java/io/reacted/drivers/channels/chroniclequeue/CQLocalDriver.java @@ -29,6 +29,7 @@ import net.openhft.chronicle.queue.RollCycles; import net.openhft.chronicle.threads.Pauser; import net.openhft.chronicle.wire.DocumentContext; +import net.openhft.chronicle.wire.ReadMarshallable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -121,9 +122,14 @@ public CompletionStage> cleanDriverLoop() { private void chronicleMainLoop(ExcerptTailer tailer) { var waitForNextMsg = Pauser.balanced(); try(DocumentContext documentContext = tailer.readingDocument()) { - Deserializer deserializer = new CQDeserializer(Objects.requireNonNull(documentContext.wire())); + var deserializer = new CQDeserializer(); + ReadMarshallable reader = wireIn -> { + deserializer.setDeserializerInput(wireIn); + readMessage(deserializer); + }; while (!Thread.currentThread().isInterrupted()) { try { + tailer.readDocument(reader); if (documentContext.isPresent()) { readMessage(deserializer); waitForNextMsg.reset(); @@ -154,7 +160,7 @@ void writeMessage(Serializer out, ReActorRef source, ReActorRef destination, lon out.put(seqNum); localReActorSystemId.encode(out); out.putEnum(ackingPolicy); - out.putObject(payload); + payload.encode(out); } public static ReActorRef readReActorRef(Deserializer in) { diff --git a/drivers/src/main/java/io/reacted/drivers/channels/replay/ReplayLocalDriver.java b/drivers/src/main/java/io/reacted/drivers/channels/replay/ReplayLocalDriver.java index da07bfe0..b0a2bd96 100644 --- a/drivers/src/main/java/io/reacted/drivers/channels/replay/ReplayLocalDriver.java +++ b/drivers/src/main/java/io/reacted/drivers/channels/replay/ReplayLocalDriver.java @@ -32,6 +32,7 @@ import net.openhft.chronicle.queue.ExcerptTailer; import net.openhft.chronicle.threads.Pauser; import net.openhft.chronicle.wire.DocumentContext; +import net.openhft.chronicle.wire.ReadMarshallable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -116,11 +117,15 @@ private void replayerMainLoop(ReActorSystem localReActorSystem, ChronicleQueue c Map> dstToMessageBySeqNum = new HashMap<>(); Pauser pauser = Pauser.balanced(); try(DocumentContext documentContext = chronicleReader.readingDocument()) { - Deserializer deserializer = new CQDeserializer(Objects.requireNonNull(documentContext.wire())); + var deserializer = new CQDeserializer(); + ReadMarshallable reader = wireIn -> { + deserializer.setDeserializerInput(wireIn); + readMessage(deserializer, localReActorSystem, emptyMap, dstToMessageBySeqNum); + }; while (!Thread.currentThread() .isInterrupted() && !chronicle.isClosed()) { try { - if (documentContext.isPresent()) { + if (chronicleReader.readDocument(reader) readMessage(deserializer, localReActorSystem, emptyMap, dstToMessageBySeqNum); pauser.reset(); } else {