PAGI-Tools
view release on metacpan or search on metacpan
lib/PAGI/Middleware.pm view on Meta::CPAN
stack, and the scope you are handed is shared with the layers around you. Mutating
it in place lets your change leak B<upward> to parent and sibling layers (and, for
a long-lived WebSocket scope, persist across every event on the connection).
Copying keeps your additions B<downward only> -- seen by the inner app you call,
invisible to everyone above.
The copy is B<shallow> on purpose. Top-level keys you add are private to the new
scope, but values that are B<references> -- the C<pagi.connection> object, the
lifespan C<state> namespace, the stash -- are shared, so the inner app still sees
the same connection state and shared objects. A deep copy would sever those. One
corollary worth knowing: a plain B<scalar> set as a top-level scope key does not
propagate back to outer layers, so to share mutable state across layers you mutate
B<through a reference> (see L<PAGI::Stash>). The full model -- and why it works
this way -- is in L<PAGI::Building/MIDDLEWARE>.
=cut
sub modify_scope {
my ($self, $scope, $additions) = @_;
$additions //= {};
t/sse/11-async-close.t view on Meta::CPAN
my $app_f = $app->({ type => 'sse' }, $receive, $send);
# Release the cleanup's I/O so a correctly-awaiting close() can finish.
$gate->done;
my $lived = eval { $app_f->get; 1 };
my $err = $@;
ok($lived, 'SSE app that closes after streaming did not crash')
or diag("app died: $err");
# Guarded by $lived so a resumed orphan coroutine can't fake a green here.
ok($lived && $cleanup_ran, 'async on_close cleanup completed as part of close()');
};
done_testing;
( run in 0.943 second using v1.01-cache-2.11-cpan-7fcb06a456a )