如何获取所有持久实体

How to fetch all persisted entities

我是 lagom 框架的新手,因此,我今天阅读了文档并开始修改他们的 hello world 示例。

但是,我无法找到一种方法来获取所有持久实体(即本例中的所有持久问候语)。

默认示例是这样获取一个人的问候语的:

@Override
public ServiceCall<GreetingMessage, Done> useGreeting(String id) {
  return request -> {
    // Look up the hello world entity for the given ID.
    PersistentEntityRef<HelloCommand> ref = persistentEntityRegistry.refFor(HelloWorld.class, id);
    // Tell the entity to use the greeting message specified.
    return ref.ask(new UseGreetingMessage(request.message));
  };
}

现在,我想获取所有实体,而不是使用给定 ID 查找实体,例如像 persistentEntityRegistry.getIds() 这样的东西,然后我可以通过 id 一个一个地获取它们。但是实体注册表好像没有这样的方法?

直接使用底层Akka Persistence框架做一个allPersistenceIds or currentPersistenceIds query

可以获得所有的实体ID

您可以在 UserServiceImpl.java:

中看到 Lagom 在线拍卖示例应用程序中使用的示例
public class UserServiceImpl implements UserService {
    //...
    private final CurrentPersistenceIdsQuery currentIdsQuery;
    private final Materializer mat;

    @Inject
    public UserServiceImpl(PersistentEntityRegistry registry, ActorSystem system, Materializer mat) {
        //...
        this.mat = mat;
        this.currentIdsQuery =
                PersistenceQuery.get(system)
                    .getReadJournalFor(
                        CassandraReadJournal.class,
                        CassandraReadJournal.Identifier()
                    );
        //...
    }

    //...
    @Override
    public ServiceCall<NotUsed, PSequence<User>> getUsers() {
        // Note this should never make production....
        return req -> currentIdsQuery.currentPersistenceIds()
                .filter(id -> id.startsWith("UserEntity"))
                .mapAsync(4, id ->
                    entityRef(id.substring(10))
                        .ask(UserCommand.GetUser.INSTANCE))
                .filter(Optional::isPresent)
                .map(Optional::get)
                .runWith(Sink.seq(), mat)
                .thenApply(TreePVector::from);
    }
    //...
}

这种方法虽然可行,但很少是个好主意。您可能已经注意到示例代码中的注释:"this should never make production"。无法使用这种方法执行聚合命令:您只能将命令一个一个地发送到每个实体。这可能会导致服务集群中节点之间的内存消耗和流量激增。也无法通过实体状态的任何标准过滤此 ID 列表,因为您可能习惯于来自面向行的 SQL 数据模型。

为您的数据定义 read-side model 几乎总是更合适。这采用单独的 "read-side" 数据存储的形式,该数据存储专为您的应用程序所需的查询类型而构建,以及一个在您的实体发出事件时自动调用的事件处理器,该事件处理器更新读取端数据存储以反映这些变化。

Lagom 框架通过管理您的读取端事件处理器、跟踪它们在事件日志中的位置以及在重启或失败时自动重启它们来帮助确保您的应用程序的最终一致性。这种类型的弹性对于聚合操作来说很难实现。

(此答案改编自related discussion in the Lagom Framework Google Group。)