Continuity
view release on metacpan or search on metacpan
* Refactor PSGI adaptor (scrottie)
* Random documentation updates
Version 1.1.1 (released 2010.02.05)
* Add PSGI Adapter! Try "plackup -s Coro guess.pl"
* Remove experimental Plack adapter
* PSGI adapter uses AnyEvent, the rest of Continuity will too soon
* Misc cleanups
Version 1.01 (released 2009.06.06)
* Allow callbacks to add callbacks without them getting deleted
* Build README from pod and update copyleft dates
Version 1.0 (released 2009.05.09)
* Improve Continuity::RequestCallbacks documentation
* Add callback clearing options
* Add test for callbacks
Version 0.998 (released 2009.02.28)
* Add RequestCallback mixin along with some documentation
* New inspect API
* Kill a race condition on watching for the inspector callback to finish
Version 0.997 (released 2008.12.11)
* Forgot to update Changes file for 0.996
* Fix debug_callback for adapters
* Slight test-suite improvement
For AJAX applications, we've found it handy to give each user multiple
sessions. In the chat-ajax-push demo each user gets a session for
sending messages, and a session for receiving them. The receiving
session uses a long-running request (aka COMET) and watches the globally
shared chat message log. When a new message is put into the log, it
pushes to all of the ajax listeners.
Lexical storage and callback links
Don't forget about those pretty little lexicals you have at your
disposal. Taking a hint from the Seaside folks, instead of regular links
you could have callbacks that trigger a anonymous subs. Your code could
look like:
use Continuity;
use strict;
my @callbacks;
my $callback_count;
Continuity->new->loop;
sub gen_link {
my ($text, $code) = @_;
$callbacks[$callback_count++] = $code;
return qq{<a href="?cb=$callback_count">$text</a>};
}
sub process_links {
my $request = shift;
my $cb = $request->param('cb');
if(exists $callbacks[$cb]) {
$callbacks[$cb]->($request);
delete $callbacks[$cb];
}
}
sub main {
my $request = shift;
my $x;
my $link1 = gen_link('This is a link to stuff' => sub { $x = 7 });
my $link2 = gen_link('This is another link' => sub { $x = 42 });
$request->print($link1, $link2);
$request->next;
process_links($request);
eg/callback_counter.pl view on Meta::CPAN
# After we're done with that we enter a loop. Forever.
while(1) {
print "Displaying current count and waiting for instructions.\n";
my $increment_link = $request->callback_link(
'++' => sub { $counter++ }
);
my $decrement_link = $request->callback_link(
'--' => sub { $counter-- }
);
$request->print("Count: $counter<br>$increment_link $decrement_link");
$request->next->execute_callbacks;
if($counter == 42) {
$request->print(q{
<h1>The Answer to Life, The Universe, and Everything</h1>
});
}
}
}
1;
lib/Continuity.pm view on Meta::CPAN
sessions. In the chat-ajax-push demo each user gets a session for sending
messages, and a session for receiving them. The receiving session uses a
long-running request (aka COMET) and watches the globally shared chat message
log. When a new message is put into the log, it pushes to all of the ajax
listeners.
=head2 Lexical storage and callback links
Don't forget about those pretty little lexicals you have at your disposal.
Taking a hint from the Seaside folks, instead of regular links you could have
callbacks that trigger a anonymous subs. Your code could look like:
use Continuity;
use strict;
my @callbacks;
my $callback_count;
Continuity->new->loop;
sub gen_link {
my ($text, $code) = @_;
$callbacks[$callback_count++] = $code;
return qq{<a href="?cb=$callback_count">$text</a>};
}
sub process_links {
my $request = shift;
my $cb = $request->param('cb');
if(exists $callbacks[$cb]) {
$callbacks[$cb]->($request);
delete $callbacks[$cb];
}
}
sub main {
my $request = shift;
my $x;
my $link1 = gen_link('This is a link to stuff' => sub { $x = 7 });
my $link2 = gen_link('This is another link' => sub { $x = 42 });
$request->print($link1, $link2);
$request->next;
process_links($request);
lib/Continuity/RequestCallbacks.pm view on Meta::CPAN
# We're importing right into the RequestHolder as a simplistic mixin
package Continuity::RequestHolder;
=head1 NAME
Continuity::RequestCallbacks - Mix callbacks into the Continuity request object
=head1 SYNOPSYS
use Continuity;
use Continuity::RequestCallbacks;
Continuity->new->loop;
sub main {
my $request = shift;
lib/Continuity/RequestCallbacks.pm view on Meta::CPAN
});
my $link_no = $request->callback_link( No => sub {
$request->print("You said no! (please reload)");
$request->next;
});
$request->print(qq{
Do you like fishies?<br>
$link_yes $link_no
});
$request->next;
$request->execute_callbacks;
$request->print("All done here!");
}
=head1 DESCRIPTION
This adds some methods to the $request object so you can easily do some callbacks.
=cut
use strict;
# This holds our current callbacks
sub callbacks { exists $_[1] ? $_[0]->{callbacks} = $_[1] : $_[0]->{callbacks} }
=head1 METHODS
=head2 $html = $request->callback_link( "text" => sub { ... } );
Returns the HTML for an href callback.
=cut
sub callback_link {
my ($self, $text, $subref) = @_;
my $name = scalar $subref;
$name =~ s/CODE\(0x(.*)\)/callback-link-$1/;
$self->callbacks({}) unless defined $self->callbacks;
$self->callbacks->{$name} = $subref;
return qq{<a href="?$name=1">$text</a>};
}
=head2 $html = $request->callback_submit( "text" => sub { ... } );
Returns the HTML for a submit button callback.
=cut
sub callback_submit {
my ($self, $text, $subref) = @_;
my $name = scalar $subref;
$name =~ s/CODE\(0x(.*)\)/callback-submit-$1/;
$self->callbacks({}) unless defined $self->callbacks;
$self->callbacks->{$name} = $subref;
return qq{<input type=submit name="$name" value="$text">};
}
=head2 $request->execute_callbacks
Execute callbacks, based on the params in C<< $request >>. Call this after
you've displayed the form and then done C<< $request->next >>.
We don't call this from within C<< $request->next >> in case you need to do
some processing before executing callbacks. Checking authentication is a good
example of something you might be doing in between :)
By default the callbacks are cleared with ->clear_callbacks after all callbacks
are processed. If you'd like, you can pass a hashref with a flag to indicate
that the remaining callbacks shouldn't be cleared, like this:
$request->execute_callbacks( { no_clear_all => 1 } );
You might want to do this if, for example, you are doing some AJAX and don't
want one js component clearing the callbacks of another. It is most likely a
bad idea though due to the ensuing memory leak. If it makes you feel any
better, you can pass "clear_executed" in the same way to clear at least some,
preventing double-execution. You'd probably use both flags:
$request->execute_callbacks( { no_clear_all => 1, clear_executed => 1 } );
=cut
sub execute_callbacks {
my ($self, $options) = @_;
foreach my $callback_name (keys %{ $self->callbacks }) {
if($self->param($callback_name)) {
$self->callbacks->{$callback_name}->($self, @_);
delete $self->callbacks->{$callback_name} if $options->{clear_executed};
}
delete $self->callbacks->{$callback_name} unless $options->{no_clear_all};
}
}
=head2 $request->clear_callbacks
Explicitly clear the current list of callbacks. This is already called at the
end of execute_callbacks. It additionally exists here in case you want to clear
the callbacks without processing.
=cut
sub clear_callbacks {
my $self = shift;
$self->callbacks({}); # Clear all callbacks
}
1;
( run in 0.525 second using v1.01-cache-2.11-cpan-9b1e4054eb1 )