-
Update the Stream.md document
- to reflect the new classes
-
Handle event payload serialization
- the pack method might not work
- look into JSON feature for to_JSON methods or something
-
Everything needs controlled shutdown, not DESTROY
- this might make it possible to remove the schedule callback feature in the scheduler
- it is only used internally for:
- scheduling init
- this could be done another way
- scheduling despawn and child stop
- which could be converted to chained signals/events
- scheduling init
- it is only used internally for:
- this might make it possible to remove the schedule callback feature in the scheduler
Think about this more.
$ctx->schedule(
event => event( *Hello::Goodbye => "Cruel World" ),
for => $hello,
after => 2,
);
$ctx->schedule(
event => event( *Hello::Goodbye => "Cruel World" ),
for => $hello,
every => 2, #interval
);
Node1 = perl start-note.pl --at 3000 Node2 = perl start-node.pl --at 3001 --connect 3000
Node2 - connects to Node1
Node1 - accepts connection from Node2 - sends WelcomeMessage to Node2
Node2 - reads WelcomeMessage - sends WelcomeResponse to Node1
Node1 - reach WelcomeResponse - sends WelcomeRepsonse to Node2
WelcomeMessage - container sender for response
WelcomeResponse - contains list of important PIDs and their addresses
Make await blocks support two things:
- multiple event cases
- timeouts (which are delivered as messages to the block)
This means we need to manage the timeout, so we have to cancel if we get a match.
- also decide how Timeout events will look.
- do we use strings?
- known constant (ex:
*Acktor::Scheduler::Timers::Timeout
)? - import a known constant so you can say
*Timeout
- is this a case for Protocols?
use Acktor::Behaviors;
class HTTPServer :isa(Acktor) {
method Request :Receive ($method, $url) {
sender->send( event *Response => '200 OK' );
}
}
class HTTPClient :isa(Acktor) {
field $server;
method Request :Receive ($url) {
$server->send( event *HTTP::Request => ( GET => $url ) );
await { timeout => 10 },
*HTTPServer::Response => method :Receive ($body) {
# ... handle the body
},
'Timeout' => method :Receive {
# timeout!
}
;
}
}
$client->send(
event *HTTPClient::Request, ('http://www.google.com')
);
Would love it if it could be this:
class HTTPClient :isa(Acktor) {
field $server;
method Request :Receive ($url) {
$server->send( event *HTTP::Request => ( GET => $url ) );
await { timeout => 10 },
method :Receive(*HTTPServer::Response) ($body) {
# ... handle the body
},
method :Receive(*Timeout) {
# timeout!
}
;
}
}
But the attributes do not work on methods at runtime, so that sucks.
Add protocols, that create the event symbols and use the Receive
attribute to direct messages to
a given method.
class Acktor::Protocol::HTTP {
use Acktor::Protocol;
event *Request;
event *Response;
}
class HTTPServer :isa(Acktor) {
use Acktor::Behaviors;
use Acktor::Protocol => 'HTTP';
method Request :Receive(*HTTP::Request) ($method, $url) {
sender->send( event *HTTP::Response => '200 OK' );
}
}
class HTTPClient :isa(Acktor) {
use Acktor::Behaviors;
use Acktor::Protocol => 'HTTP';
field $server;
method Get :Receive ($url) {
$server->send( event *HTTP::Request => ( GET => $url ) );
await *HTTP::Response => method :Receive ($body) {
...
};
}
}
$client->send(
event *HTTPClient::Get, ('http://www.google.com')
);
- Make a distributed Hash Table
A future will return a promise (Thenable) that is connected to an Actor instance.
The Actor instance sends the message and awaits the result, assuming the actor
being called will respond to sender
. When this actor instance gets a result, then
it resolves the promise it is attached to.
The advantage of this is that you can launch multiple futures at once, and then
collect them using the collect
function turn them into a single promise.
Another advantage of the future
is that it does not affect the actors state.
Whereas await
affects the state of the instance via become
.
class HTTPClient :isa(Acktor) {
use Acktor::Behaviors;
field $server;
method Request :Receive ($url) {
my $f1 = future[*HTTP::Response] => (
to => $server,
event => event( *HTTP::Request => ( GET => $url1 ) ),
timout => 3,
);
my $f2 = future[*HTTP::Response] => (
to => $server,
event => event( *HTTP::Request => ( GET => $url2 ) ),
timout => 5,
);
# this is async, it does not block
collect($f1, $f2)
->on_success(method ($results) { ... })
->on_error(method ($error) { ... })
->on_timeout(method { ... });
}
}
-
Protocols for cross Process communication
- Spawn
- Send
- Lookup
- Identify
-
- for system messages
- PreRestart - sent to Actor right before it is restarted
- PostStop - fired after the Actor, and all it's children are terminated
- Terminated - sent after PostStop to all watchers of this Actor
- ChildFailed - the child Actor has failed permanently
- for system messages