https://github.com/ytake/phluxor
A toolkit for flexible actor models in PHP, empowering the PHP ecosystem
https://github.com/ytake/phluxor
actor-model actorsystem php swoole
Last synced: 6 months ago
JSON representation
A toolkit for flexible actor models in PHP, empowering the PHP ecosystem
- Host: GitHub
- URL: https://github.com/ytake/phluxor
- Owner: ytake
- License: apache-2.0
- Created: 2024-06-07T11:26:08.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2025-01-07T05:48:49.000Z (9 months ago)
- Last Synced: 2025-04-07T00:32:10.525Z (6 months ago)
- Topics: actor-model, actorsystem, php, swoole
- Language: PHP
- Homepage: https://phluxor.github.io/
- Size: 385 KB
- Stars: 33
- Watchers: 1
- Forks: 2
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Phluxor
A toolkit for flexible actor models in PHP, empowering the PHP ecosystem.
requires PHP 8.3 and swoole.
and Protocol Buffers for message serialization. / not supported other serialization formats yet.
Documentation is under preparation.
do not use this in production yet.
[sample web application / phluxor-http-application-samples](https://github.com/ytake/phluxor-http-application-samples)
[demonstrate the use of Phluxor](https://github.com/ytake/phluxor-example)
[demonstrates how to use Phluxor with Event Sourcing and CQRS.](https://github.com/ytake/phluxor-example-event-sourcing-cqrs)
[Documentation](https://phluxor.github.io/en/guide/)PhluxorはPHPでのアクターモデルを実現するためのツールキットです。
PHP 8.3 と swooleが必要です。
メッセージのシリアライズには、Protocol Buffersを利用します。
他のシリアライズフォーマットはまだサポートされていません。```mermaid
sequenceDiagram
participant A as Actor A
participant B as Actor B
participant C as Actor CA->>B: Message(Data X)
Note over B: B processes the received message, updates internal state,
and prepares the next message
B->>C: Message(Data Y)
Note over C: C processes the message from B.
Meanwhile, A or other actors can progress with separate tasks.par Concurrent Execution
A->>C: Another Message(Data Z)
C->>B: Result Message(Computed W)
and
B->>A: State Report(State S)
end
```## Installation
```bash
$ composer require phluxor/phluxor
```## already implemented
- actor model
- actor lifecycle
- supervision
- actor registry
- actor messaging
- become/unbecome
- mailbox / dispatcher
- event stream
- future
- persistent actors (in memory / mysql)
- [OpenTelemetry](https://opentelemetry.io/docs/languages/php/) support (metrics)
- router / round-robin, broadcast, scatter-gather, etc.
- [remoting](https://github.com/ytake/phluxor-remote) / Remoting is the mechanism by which Actors on different nodes talk to each other internally.## work in progress
- open telemetry support (tracing)
- virtual actors / cluster support## Supervision
exception handling is done by the actor system, and the actor can be supervised by parent , root actors.
- `OneForOneStrategy`
- `AllForOneStrategy`
- `ExponentialBackoffStrategy`
- `RestartStrategy`## Easy to use
like a akka http, you can use it with a simple API.
use mezzio / mezzio-swoole / phluxor.
and you can use it with swoole / open swoole.```php
message();
switch (true) {
case $msg instanceof Add:
// change actor state
$this->name = $msg->name;
$this->tickets = $msg->tickets;
$this->id = $context->self()?->protobufPid()->getId();
break;
case $msg instanceof GetEvent:
$context->requestWithCustomSender(
$context->sender(),
new Event($this->name, $this->tickets),
$context->parent()
);
break;
case $msg instanceof Cancel:
$context->requestWithCustomSender(
$context->sender(),
new Cancel(),
$context->parent()
);
$context->poison($context->self());
break;
}
}
}
```send message to actor.
```php
message();
switch (true) {
case $msg instanceof EventDescription:
try {
$result = $context->spawnNamed(
Props::fromProducer(fn() => new TicketSeller()),
$msg->name
);
$context->send($result->getRef(), new Add($msg->name, $msg->tickets));
$context->respond(new EventCreated($msg->name, $msg->tickets));
} catch (SpawnErrorException $e) {
$context->respond(new EventExists());
}
break;
}
}
}
}
```## Become/Unbecome
an actor can change its behavior by `become` and `unbecome` methods.
example:
one, other are the behavior methods.
```php
behavior = new Behavior();
$this->behavior->become(
new ReceiveFunction(
fn(ContextInterface $context) => $this->one($context)
)
);
}public function receive(ContextInterface $context): void
{
$this->behavior->receive($context);
}public function one(ContextInterface $context): void
{
if ($context->message() instanceof BehaviorMessage) {
$this->behavior->become(
new ReceiveFunction(
fn(ContextInterface $context) => $this->other($context)
)
);
}
}public function other(ContextInterface $context): void
{
if ($context->message() instanceof EchoRequest) {
$context->respond(new EchoResponse());
}
}
}
``````php
root()->spawn(
Props::fromProducer(
fn() => new EchoSetBehaviorActor()
)
);
$system->root()->send($pid, new BehaviorMessage());
$future = $system->root()->requestFuture($pid, new EchoRequest(), 1);
var_dump($future->result());
$system->root()->stop($pid);
}, $system);
});
}```
## Persistent Actors
パーシステンスアクターは、以前の状態から復元できるアクターです。
永続化に利用するデータベースは、お使いの環境などに合わせて自由にアダプターを実装することができます。
デフォルトではインメモリとMySQLが実装されています。
メッセージのシリアライズには、Protocol Buffersを利用しますので、事前にProtocol Buffersのファイルを用意しておく必要があります。
以下はサンプルのProtocol Buffersファイルです。persistent actors are actors that can be restored from the previous state.
you can implement an adapter freely according to your environment for the database used for persistence.
by default, in-memory and MySQL are implemented.
Protocol Buffers is used for message serialization, so you need to prepare a Protocol Buffers file in advance.for example, the protocol buffers file is like this.
```protobuf
syntax = "proto3";package Acme.Persistence.ProtoBuf;
option php_namespace = "Acme\\Persistence\\ProtoBuf";
option php_metadata_namespace = "Acme\\Metadata";message Message {
string message = 1;
}message Snapshot {
string message = 1;
}```
詳しい永続化の使い方は、永続アクターのサンプルを参照してください。[Persistence / MySQL](example/persistence/SampleSystem.php)
for example, the persistent actor is like this. [Persistence / MySQL](example/persistence/SampleSystem.php)
use `Phluxor\Persistence\Mixin` trait and implement `Phluxor\Persistence\PersistentInterface`.
```php
message();
switch (true) {
case $msg instanceof RequestSnapshot:
$this->persistenceSnapshot(new TestSnapshot(['message' => $this->state]));
break;
case $msg instanceof TestSnapshot:
$this->state = $msg->getMessage();
break;
case $msg instanceof TestMessage:
if (!$this->recovering()) {
$this->persistenceReceive($msg);
}
$this->state = $msg->getMessage();
break;
case $msg instanceof Query:
$context->respond($this->state);
break;
}
}
}
```more examples are in the [Persistence Tests](tests/Persistence) directory.