akka.cluster.sharding.ShardRegion Java Examples

The following examples show how to use akka.cluster.sharding.ShardRegion. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: ThingsUpdater.java    From ditto with Eclipse Public License 2.0 6 votes vote down vote up
@Override
public Receive createReceive() {
    return ReceiveBuilder.create()
            .match(ThingEvent.class, this::processThingEvent)
            .match(ThingTag.class, this::processThingTag)
            .match(PolicyReferenceTag.class, this::processPolicyReferenceTag)
            .matchEquals(ShardRegion.getShardRegionStateInstance(), getShardRegionState ->
                    shardRegion.forward(getShardRegionState, getContext()))
            .match(RetrieveStatisticsDetails.class, this::handleRetrieveStatisticsDetails)
            .matchEquals(Clock.REBALANCE_TICK, this::retrieveShardIds)
            .match(ShardRegion.ShardRegionStats.class, this::updateSubscriptions)
            .match(ThingsOutOfSync.class, this::updateThings)
            .match(UpdateThing.class, this::updateThing)
            .match(DistributedPubSubMediator.SubscribeAck.class, subscribeAck ->
                    log.debug("Got <{}>", subscribeAck))
            .matchAny(m -> {
                log.warning("Unknown message: {}", m);
                unhandled(m);
            }).build();
}
 
Example #2
Source File: PersistentEntitySharding.java    From spring-boot-akka-event-sourcing-starter with Apache License 2.0 5 votes vote down vote up
@Override
public String shardId(Object command) {
	if (command instanceof ShardRegion.StartEntity) {
		ShardRegion.StartEntity startEntity = (ShardRegion.StartEntity) command;
		return getShardId(startEntity.entityId());
	} else {
		return getShardId(getEntityId(command));
	}

}
 
Example #3
Source File: TestConstants.java    From ditto with Eclipse Public License 2.0 5 votes vote down vote up
@Override
public Receive createReceive() {
    return receiveBuilder()
            .match(ShardRegion.Passivate.class, passivate -> {
                getSender().tell(PoisonPill.getInstance(), getSelf());
                getContext().stop(getSelf());
            })
            .matchAny(m -> child.forward(m, getContext()))
            .build();
}
 
Example #4
Source File: ThingsUpdaterTest.java    From ditto with Eclipse Public License 2.0 5 votes vote down vote up
@Test
public void shardRegionStateIsForwarded() {
    final ShardRegion.GetShardRegionState$ shardRegionState = ShardRegion.getShardRegionStateInstance();
    new TestKit(actorSystem) {{
        final ActorRef underTest = createThingsUpdater();
        underTest.tell(shardRegionState, getRef());
        shardMessageReceiver.expectMsg(shardRegionState);
    }};
}
 
Example #5
Source File: NewEventForwarder.java    From ditto with Eclipse Public License 2.0 5 votes vote down vote up
private static Collection<String> getActiveShardIds(final ShardRegion.ClusterShardingStats stats) {
    return stats.getRegions()
            .values()
            .stream()
            .flatMap(shardRegionStats -> shardRegionStats.getStats().keySet().stream())
            .collect(Collectors.toList());
}
 
Example #6
Source File: NewEventForwarder.java    From ditto with Eclipse Public License 2.0 5 votes vote down vote up
private void updateSubscriptions(final ShardRegion.ClusterShardingStats stats) {
    final Set<String> inactiveShardIds = shardRegionExtractor.getInactiveShardIds(getActiveShardIds(stats));
    log.debug("Updating event subscriptions for inactive shards: <{}> -> <{}>", previousShardIds, inactiveShardIds);
    final List<String> toSubscribe =
            inactiveShardIds.stream().filter(s -> !previousShardIds.contains(s)).collect(Collectors.toList());
    final List<String> toUnsubscribe =
            previousShardIds.stream().filter(s -> !inactiveShardIds.contains(s)).collect(Collectors.toList());
    thingEventSub.subscribeWithoutAck(toSubscribe, getSelf());
    thingEventSub.unsubscribeWithoutAck(toUnsubscribe, getSelf());
    previousShardIds = inactiveShardIds;
}
 
Example #7
Source File: NewEventForwarder.java    From ditto with Eclipse Public License 2.0 5 votes vote down vote up
@Override
public Receive createReceive() {
    return ReceiveBuilder.create()
            .match(ThingEvent.class, this::processThingEvent)
            .matchEquals(Clock.REBALANCE_TICK, this::retrieveClusterShardingStats)
            .match(ShardRegion.ClusterShardingStats.class, this::updateSubscriptions)
            .matchAny(m -> {
                log.warning("Unknown message: {}", m);
                unhandled(m);
            }).build();
}
 
Example #8
Source File: NewEventForwarder.java    From ditto with Eclipse Public License 2.0 5 votes vote down vote up
@SuppressWarnings("unused")
private NewEventForwarder(final DistributedSub thingEventSub,
        final ActorRef thingUpdaterShardRegion,
        final BlockedNamespaces blockedNamespaces) {

    this.thingEventSub = thingEventSub;

    final DittoSearchConfig searchConfig =
            DittoSearchConfig.of(DefaultScopedConfig.dittoScoped(getContext().getSystem().settings().config()));
    final UpdaterConfig updaterConfig = searchConfig.getUpdaterConfig();
    final ClusterConfig clusterConfig = searchConfig.getClusterConfig();

    shardRegion = thingUpdaterShardRegion;

    namespaceBlockingBehavior = BlockNamespaceBehavior.of(blockedNamespaces);

    getClusterShardingStats = new ShardRegion.GetClusterShardingStats(
            FiniteDuration.create(updaterConfig.getShardingStatePollInterval().toMillis(), TimeUnit.MILLISECONDS));

    shardRegionExtractor = ShardRegionExtractor.of(clusterConfig.getNumberOfShards(), getContext().getSystem());

    if (updaterConfig.isEventProcessingActive()) {
        // schedule regular updates of subscriptions
        getTimers().startPeriodicTimer(Clock.REBALANCE_TICK, Clock.REBALANCE_TICK,
                updaterConfig.getShardingStatePollInterval());
        // subscribe for thing events immediately
        getSelf().tell(Clock.REBALANCE_TICK, getSelf());
    }
}
 
Example #9
Source File: ThingsUpdater.java    From ditto with Eclipse Public License 2.0 5 votes vote down vote up
private void updateSubscriptions(final ShardRegion.ShardRegionStats stats) {
    final Set<String> currentShardIds = stats.getStats().keySet();
    log.debug("Updating event subscriptions: <{}> -> <{}>", previousShardIds, currentShardIds);
    final List<String> toSubscribe =
            currentShardIds.stream().filter(s -> !previousShardIds.contains(s)).collect(Collectors.toList());
    final List<String> toUnsubscribe =
            previousShardIds.stream().filter(s -> !currentShardIds.contains(s)).collect(Collectors.toList());
    thingEventSub.subscribeWithoutAck(toSubscribe, getSelf());
    thingEventSub.unsubscribeWithoutAck(toUnsubscribe, getSelf());
    previousShardIds = currentShardIds;
}
 
Example #10
Source File: StatisticsActor.java    From ditto with Eclipse Public License 2.0 5 votes vote down vote up
private void tellShardRegionToSendClusterShardingStats(final String shardRegion) {
    try {
        clusterSharding.shardRegion(shardRegion).tell(
                new ShardRegion.GetClusterShardingStats(FiniteDuration.apply(10, TimeUnit.SECONDS)),
                getSelf());
    } catch (final IllegalArgumentException e) {
        // shard not started; there will not be any sharding stats.
        log.error(e, "Failed to query shard region <{}>", shardRegion);
    }
}
 
Example #11
Source File: StatisticsActor.java    From ditto with Eclipse Public License 2.0 5 votes vote down vote up
@Override
public Receive createReceive() {
    return ReceiveBuilder.create()
            .match(RetrieveStatistics.class, this::respondWithCachedStatistics)
            .match(RetrieveStatisticsDetails.class, this::hasCachedStatisticsDetails,
                    this::respondWithCachedStatisticsDetails)
            .match(RetrieveStatisticsDetails.class, retrieveStatistics -> {
                // no cached statistics details; retrieve them from cluster members.
                final ActorRef sender = getSender();
                final List<ClusterRoleStatus> relevantRoles = clusterStatusSupplier.get()
                        .getRoles()
                        .stream()
                        .filter(this::hasRelevantRole)
                        .collect(Collectors.toList());
                tellRelevantRootActorsToRetrieveStatistics(relevantRoles, retrieveStatistics);
                becomeStatisticsDetailsAwaiting(relevantRoles, details ->
                        respondWithStatisticsDetails(retrieveStatistics, details, sender));
            })
            .matchEquals(InternalRetrieveStatistics.INSTANCE, unit -> {
                tellShardRegionsToSendClusterShardingStats();
                becomeStatisticsAwaiting();
            })
            .matchEquals(InternalResetStatisticsDetails.INSTANCE, this::resetStatisticsDetails)
            .match(ShardRegion.CurrentShardRegionState.class, this::unhandled) // ignore, the message is too late
            .match(ShardRegion.ClusterShardingStats.class, this::unhandled) // ignore, the message is too late
            .match(RetrieveStatisticsDetailsResponse.class, this::unhandled) // ignore, the message is too late
            .match(DistributedPubSubMediator.SubscribeAck.class, this::logSubscribeAck)
            .matchAny(m -> log.warning("Got unknown message, expected a 'RetrieveStatistics': {}", m))
            .build();
}
 
Example #12
Source File: ShardRegionExtractor.java    From ditto with Eclipse Public License 2.0 5 votes vote down vote up
@Override
public String entityId(final Object message) {
    if (message instanceof ShardedMessageEnvelope) {
        return ((ShardedMessageEnvelope) message).getEntityId().toString();
    } else if (message instanceof WithId) {
        return ((WithId) message).getEntityId().toString();
    } else if (message instanceof ShardRegion.StartEntity) {
        return ((ShardRegion.StartEntity) message).entityId();
    }
    return null;
}
 
Example #13
Source File: ThingUpdater.java    From ditto with Eclipse Public License 2.0 4 votes vote down vote up
private void stopThisActor(final ReceiveTimeout receiveTimeout) {
    log.debug("stopping ThingUpdater <{}> due to <{}>", thingId, receiveTimeout);
    getContext().getParent().tell(new ShardRegion.Passivate(PoisonPill.getInstance()), getSelf());
}
 
Example #14
Source File: StatisticsActor.java    From ditto with Eclipse Public License 2.0 4 votes vote down vote up
private void becomeStatisticsAwaiting() {

        final Map<String, ShardStatisticsWrapper> shardStatisticsMap = new HashMap<>();

        final AskTimeoutException askTimeoutException = new AskTimeoutException("Timed out");
        getTimers().startSingleTimer(askTimeoutException, askTimeoutException, statisticsConfig.getAskTimeout());

        getContext().become(ReceiveBuilder.create()
                        .match(RetrieveStatistics.class, this::respondWithCachedStatistics)
                        .match(ShardRegion.ClusterShardingStats.class, clusterShardingStats -> {
                            final Optional<ShardStatisticsWrapper> shardStatistics =
                                    getShardStatistics(shardStatisticsMap, getSender());

                            if (shardStatistics.isPresent()) {
                                final Map<Address, ShardRegion.ShardRegionStats> regions = clusterShardingStats.getRegions();
                                shardStatistics.get().count = regions.isEmpty() ? 0 : regions.values().stream()
                                        .mapToInt(shardRegionStats -> shardRegionStats.getStats().isEmpty() ? 0 :
                                                shardRegionStats.getStats().values().stream()
                                                        .mapToInt(o -> (Integer) o)
                                                        .sum())
                                        .sum();
                            } else {
                                log.warning("Got stats from unknown shard <{}>: <{}>", getSender(), clusterShardingStats);
                            }

                            // all shard statistics are present; no need to wait more.
                            if (shardStatisticsMap.size() >= statisticsConfig.getShards().size()) {
                                getTimers().cancel(askTimeoutException);
                                getSelf().tell(askTimeoutException, getSelf());
                            }
                        })
                        .matchEquals(askTimeoutException, unit -> {
                            updateGauges(shardStatisticsMap);
                            currentStatistics = Statistics.fromGauges(gauges);
                            unbecome();
                        })
                        .matchEquals(InternalResetStatisticsDetails.INSTANCE, this::resetStatisticsDetails)
                        .match(DistributedPubSubMediator.SubscribeAck.class, this::logSubscribeAck)
                        .matchAny(m -> {
                            log.info("Stashing message during 'statisticsAwaiting': {}", m);
                            stash();
                        })
                        .build(),
                false);
    }
 
Example #15
Source File: ThingsUpdater.java    From ditto with Eclipse Public License 2.0 4 votes vote down vote up
private void retrieveShardIds(final Clock rebalanceTick) {
    shardRegion.tell(ShardRegion.getRegionStatsInstance(), getSelf());
}
 
Example #16
Source File: RetrieveStatisticsDetailsResponseSupplier.java    From ditto with Eclipse Public License 2.0 4 votes vote down vote up
@Override
public CompletionStage<RetrieveStatisticsDetailsResponse> apply(final DittoHeaders dittoHeaders) {
    return Patterns.ask(shardRegion, ShardRegion.getShardRegionStateInstance(), Duration.ofSeconds(5))
            .handle((result, throwable) -> {
                if (throwable != null) {
                    log.error(throwable, "Could not determine 'ShardRegionState' for shard region <{}>",
                            shardRegionName);
                    return RetrieveStatisticsDetailsResponse.of(JsonObject.newBuilder()
                                    .set(shardRegionName, JsonFactory.newObject())
                                    .build(),
                            dittoHeaders);
                } else if (result instanceof ShardRegion.CurrentShardRegionState) {
                    final Collector<String, ?, Map<String, Long>> stringMapCollector =
                            Collectors.groupingBy(Function.identity(),
                                    Collectors.mapping(Function.identity(), Collectors.counting()));
                    final Map<String, Long> shardStats =
                            ((ShardRegion.CurrentShardRegionState) result).getShards()
                                    .stream()
                                    .map(ShardRegion.ShardState::getEntityIds)
                                    .flatMap(strSet -> strSet.stream()
                                            .map(str -> {
                                                // groupKey may be either namespace or resource-type+namespace (in case of concierge)
                                                final String[] groupKeys = str.split(":", 3);
                                                // assume String.split(String, int) may not return an empty array
                                                switch (groupKeys.length) {
                                                    case 0:
                                                        // should not happen with Java 8 strings, but just in case
                                                        return EMPTY_ID;
                                                    case 1:
                                                    case 2:
                                                        // normal: namespace
                                                        return ensureNonemptyString(
                                                                groupKeys[0]);
                                                    default:
                                                        // concierge: resource-type + namespace
                                                        return groupKeys[0] + ":" +
                                                                groupKeys[1];
                                                }
                                            })
                                    )
                                    .collect(stringMapCollector);

                    final JsonObject namespaceStats = shardStats.entrySet().stream()
                            .map(entry -> JsonField.newInstance(entry.getKey(),
                                    JsonValue.of(entry.getValue())))
                            .collect(JsonCollectors.fieldsToObject());

                    final JsonObject thingNamespacesStats = JsonObject.newBuilder()
                            .set(shardRegionName, namespaceStats)
                            .build();

                    return RetrieveStatisticsDetailsResponse.of(thingNamespacesStats,
                            dittoHeaders);
                } else {
                    log.warning("Unexpected answer to " +
                            "'ShardRegion.getShardRegionStateInstance()': {}", result);
                    return RetrieveStatisticsDetailsResponse.of(JsonObject.newBuilder()
                                    .set(shardRegionName, JsonFactory.newObject())
                                    .build(),
                            dittoHeaders);
                }
            });
}
 
Example #17
Source File: AbstractPersistenceSupervisor.java    From ditto with Eclipse Public License 2.0 4 votes vote down vote up
private void passivate(final Control passivationTrigger) {
    getContext().getParent().tell(new ShardRegion.Passivate(PoisonPill.getInstance()), getSelf());
}
 
Example #18
Source File: SagaActor.java    From servicecomb-pack with Apache License 2.0 4 votes vote down vote up
private void beforeStop(BaseEvent event, SagaActorState state, SagaData data){
  if (LOG.isDebugEnabled()) {
    LOG.debug("stop [{}] {}", data.getGlobalTxId(), state);
  }
  try{
    sagaEndTime = System.currentTimeMillis();
    data.setLastState(state);
    data.setEndTime(new Date());
    data.setTerminated(true);
    SagaDataExtension.SAGA_DATA_EXTENSION_PROVIDER.get(getContext().getSystem())
        .stopSagaData(data.getGlobalTxId(), data);
    SagaDataExtension.SAGA_DATA_EXTENSION_PROVIDER.get(context().system()).doSagaEndCounter();
    SagaDataExtension.SAGA_DATA_EXTENSION_PROVIDER.get(context().system())
        .doSagaAvgTime(sagaEndTime - sagaBeginTime);

    // destroy self from cluster shard region
    getContext().getParent()
        .tell(new ShardRegion.Passivate(PoisonPill.getInstance()), getSelf());

    //  clear self mailbox from persistence
    //  已经停止的Actor使用以下两个命令清理,但是 highestSequenceNr 不会被删除,需要手工清理
    //  以下基于 journal-redis 说明:
    //    假设 globalTxId=ed2cdb9c-e86c-4b01-9f43-8e34704e7694, 那么在 Redis 中会生成三个 key
    //    journal:persistenceIds
    //    journal:persisted:ed2cdb9c-e86c-4b01-9f43-8e34704e7694
    //    journal:persisted:ed2cdb9c-e86c-4b01-9f43-8e34704e7694:highestSequenceNr
    //
    //    1. journal:persistenceIds 是 set 类型, 记录了所有的 globalTxId, 使用 smembers journal:persistenceIds 可以看到
    //    2. journal:persisted:ed2cdb9c-e86c-4b01-9f43-8e34704e7694 是 zset 类型, 记录了这个事务的所有事件
    //       使用 zrange journal:persisted:ed2cdb9c-e86c-4b01-9f43-8e34704e7694 1 -1 可以看到
    //    3. journal:persisted:ed2cdb9c-e86c-4b01-9f43-8e34704e7694:highestSequenceNr 是 string 类型, 里面记录这序列号
    //
    //    何如清理:
    //      通过 deleteMessages 和 deleteSnapshot 可以清理部分数据,但是 highestSequenceNr 还是无法自动删除,需要定期手动清理
    //      遍历 journal:persistenceIds 集合,用每一条数据item拼接成key journal:persisted:item 和 journal:persisted:item:highestSequenceNr
    //      如果没有成对出现就说明是已经终止的actor 那么可以将 journal:persisted:item 从 journal:persistenceIds 删除
    //      并删除 journal:persisted:item:highestSequenceNr
    //
    //  目前可以看到的解释是 https://github.com/akka/akka/issues/21181
    //
    //  Lua script akka-persistence-redis-clean.lua

    //  local ids = redis.call('smembers','journal:persistenceIds');
    //  local delkeys = {};
    //  for k, v in pairs(ids) do
    //    local jpid = 'journal:persisted:' .. v;
    //    local jpidnr = 'journal:persisted:' .. v .. ':highestSequenceNr';
    //    local hasjpid  = redis.call('exists',jpid);
    //    if(hasjpid == 0)
    //    then
    //      local hasjpidnr  = redis.call('exists',jpidnr);
    //      if(hasjpidnr == 1)
    //      then
    //        redis.call('del',jpidnr);
    //        table.insert(delkeys,jpid);
    //      end
    //    end
    //  end
    //  return delkeys;
    deleteMessages(lastSequenceNr());
    deleteSnapshot(snapshotSequenceNr());
  }catch(Exception e){
    LOG.error("stop [{}] fail",data.getGlobalTxId());
    throw e;
  }
}
 
Example #19
Source File: ThrottleActor.java    From ts-reaktive with MIT License 4 votes vote down vote up
private void passivate() {
    context().parent().tell(new ShardRegion.Passivate(Stop.instance), self());
}
 
Example #20
Source File: PersistentEntity.java    From spring-boot-akka-event-sourcing-starter with Apache License 2.0 2 votes vote down vote up
/**
 * Signals the parent actor (which is expected to be a ShardRegion) to passivate this actor, as a result
 * of not having received any messages for a certain amount of time.
 * <p>
 * You can also invoke this method directly if you want to cleanly stop the actor explicitly.
 */
protected void passivate() {
	context().parent().tell(new ShardRegion.Passivate(STOP), self());
}
 
Example #21
Source File: AbstractStatefulPersistentActor.java    From ts-reaktive with MIT License 2 votes vote down vote up
/**
 * Signals the parent actor (which is expected to be a ShardRegion) to passivate this actor, as a result
 * of not having received any messages for a certain amount of time.
 * 
 * You can also invoke this method directly if you want to cleanly stop the actor explicitly.
 */
protected void passivate() {
    context().parent().tell(new ShardRegion.Passivate(STOP), self());
}