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 1.315 second using v1.01-cache-2.11-cpan-7fcb06a456a )