Continuity

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

  * 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

README  view on Meta::CPAN

    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 )