1package Dancer2::Core::Response::Delayed;
2# ABSTRACT: Delayed responses
3$Dancer2::Core::Response::Delayed::VERSION = '0.301004';
4use Moo;
5use Dancer2::Core::Types qw<CodeRef InstanceOf>;
6
7has request => (
8    is       => 'ro',
9    isa      => InstanceOf['Dancer2::Core::Request'],
10    required => 1,
11);
12
13has response => (
14    is       => 'ro',
15    isa      => InstanceOf['Dancer2::Core::Response'],
16    required => 1,
17    handles => [qw/status headers push_header/],
18);
19
20has cb => (
21    is       => 'ro',
22    isa      => CodeRef,
23    required => 1,
24);
25
26has error_cb => (
27    is        => 'ro',
28    isa       => CodeRef,
29    predicate => '_has_error_cb',
30);
31
32sub is_halted()  {0}
33sub has_passed() {0}
34
35sub to_psgi {
36    my $self = shift;
37
38    return sub {
39        my $responder = shift;
40
41        local $Dancer2::Core::Route::REQUEST       = $self->request;
42        local $Dancer2::Core::Route::RESPONSE      = $self->response;
43        local $Dancer2::Core::Route::RESPONDER     = $responder;
44        local $Dancer2::Core::Route::WRITER;
45
46        local $Dancer2::Core::Route::ERROR_HANDLER =
47            $self->_has_error_cb ? $self->error_cb : undef;
48
49        $self->cb->();
50    };
51}
52
531;
54
55__END__
56
57=pod
58
59=encoding UTF-8
60
61=head1 NAME
62
63Dancer2::Core::Response::Delayed - Delayed responses
64
65=head1 VERSION
66
67version 0.301004
68
69=head1 SYNOPSIS
70
71    my $response = Dancer2::Core::Response::Delayed->new(
72        request   => Dancer2::Core::Request->new(...),
73        response  => Dancer2::Core::Response->new(...),
74        cb        => sub {...},
75
76        # optional error handling
77        error_cb  => sub {
78            my ($error) = @_;
79            ...
80        },
81    );
82
83    # or in an app
84    get '/' => sub {
85        # delayed response:
86        delayed {
87            # streaming content
88            content "data";
89            content "more data";
90
91            # close user connection
92            done;
93        } on_error => sub {
94            my ($error) = @_;
95            warning 'Failed to stream to user: ' . request->remote_address;
96        };
97    };
98
99=head1 DESCRIPTION
100
101This object represents a delayed (asynchronous) response for L<Dancer2>.
102It can be used via the C<delayed> keyword.
103
104It keeps references to a request and a response in order to avoid
105keeping a reference to the application.
106
107=head1 ATTRIBUTES
108
109=head2 request
110
111Contains a request the delayed response uses.
112
113In the context of a web request, this will be the request that existed
114when the delayed response has been created.
115
116=head2 response
117
118Contains a response the delayed response uses.
119
120In the context of a web request, this will be the response that existed
121when the delayed response has been created.
122
123=head2 cb
124
125The code that will be run asynchronously.
126
127=head2 error_cb
128
129A callback for handling errors. This callback receives the error as its
130first (and currently only) parameter.
131
132=head1 METHODS
133
134=head2 is_halted
135
136A method indicating whether the response has halted.
137
138This is useless in the context of an asynchronous request so it simply
139returns no.
140
141This method is likely going away.
142
143=head2 has_passed
144
145A method indicating whether the response asked to skip the current
146response.
147
148This is useless in the context of an asynchronous request so it simply
149returns no.
150
151This method is likely going away.
152
153=head2 to_psgi
154
155Create a PSGI response. The way it works is by returning a proper PSGI
156response subroutine which localizes the request and response (in case
157the callback wants to edit them without a reference to them), and then
158calls the callback.
159
160Finally, when the callback is done, it asks the response (whether it
161was changed or not) to create its own PSGI response (calling C<to_psgi>)
162and sends that to the callback it receives as a delayed response.
163
164=head1 AUTHOR
165
166Dancer Core Developers
167
168=head1 COPYRIGHT AND LICENSE
169
170This software is copyright (c) 2021 by Alexis Sukrieh.
171
172This is free software; you can redistribute it and/or modify it under
173the same terms as the Perl 5 programming language system itself.
174
175=cut
176