[Jifty-commit] jifty branch, pubsub, created. 1.10518-105-g9d59fe5

Jifty commits jifty-commit at lists.jifty.org
Tue Sep 4 02:49:46 EDT 2012


The branch, pubsub has been created
        at  9d59fe5e9ba99cf0af66384f3351aa0154b7aef3 (commit)

- Log -----------------------------------------------------------------
commit e4d6512b6c71d699857ed7ab45005b1018879956
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Sun Mar 25 05:23:46 2012 -0400

    Gut the old IPC::PubSub implementation

diff --git a/MANIFEST b/MANIFEST
index dd49cc7..1955ebe 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -65,27 +65,8 @@ doc/packaging
 doc/plugin-requirements
 doc/plugin-syntax
 doc/plugins-restated-assumptions
-doc/pubsub/backend_message_types
-doc/pubsub/subscriptions
-doc/pubsub/system_architecture.graffle
-doc/pubsub/system_architecture.png
 etc/config.yml
 etc/site_config.yml
-examples/Chat/bin/jifty
-examples/Chat/etc/config.yml
-examples/Chat/lib/Chat/Action/Send.pm
-examples/Chat/lib/Chat/Event/Message.pm
-examples/Chat/lib/Chat/View.pm
-examples/Chat/Makefile.PL
-examples/Chat/t/00compile.t
-examples/Chat/t/01startup.t
-examples/Clock/bin/jifty
-examples/Clock/clockserv.pl
-examples/Clock/etc/config.yml
-examples/Clock/lib/Clock/Event/Tick.pm
-examples/Clock/Makefile.PL
-examples/Clock/share/web/templates/fragments/time
-examples/Clock/share/web/templates/index.html
 examples/Doxory/bin/jifty
 examples/Doxory/etc/config.yml
 examples/Doxory/lib/Doxory/Dispatcher.pm
@@ -110,17 +91,6 @@ examples/MyWeblog/share/web/templates/fragments/page_of_posts
 examples/MyWeblog/share/web/templates/index.html
 examples/MyWeblog/share/web/templates/post
 examples/MyWeblog/t/00-model-Post.t
-examples/Ping/bin/jifty
-examples/Ping/etc/config.yml
-examples/Ping/lib/Ping/Action/AddPing.pm
-examples/Ping/lib/Ping/Action/CancelPing.pm
-examples/Ping/lib/Ping/Event/Pong.pm
-examples/Ping/lib/Ping/PingServer.pm
-examples/Ping/Makefile.PL
-examples/Ping/share/web/templates/fragments/pong
-examples/Ping/share/web/templates/index.html
-examples/Ping/t/00compile.t
-examples/Ping/t/01startup.t
 examples/ShrinkURL/bin/jifty
 examples/ShrinkURL/etc/config.yml
 examples/ShrinkURL/lib/ShrinkURL/Action/CreateShrunkenURL.pm
@@ -182,9 +152,6 @@ lib/Jifty/Continuation.pm
 lib/Jifty/CurrentUser.pm
 lib/Jifty/DateTime.pm
 lib/Jifty/Dispatcher.pm
-lib/Jifty/Event.pm
-lib/Jifty/Event/Log.pm
-lib/Jifty/Event/Model.pm
 lib/Jifty/Everything.pm
 lib/Jifty/Filter/DateTime.pm
 lib/Jifty/Filter/JSON.pm
@@ -194,7 +161,6 @@ lib/Jifty/I18N.pm
 lib/Jifty/JSON.pm
 lib/Jifty/LetMe.pm
 lib/Jifty/Logger.pm
-lib/Jifty/Logger/EventAppender.pm
 lib/Jifty/Manual.pm
 lib/Jifty/Manual/AccessControl.pod
 lib/Jifty/Manual/AccessControl_zhtw.pod
@@ -318,8 +284,6 @@ lib/Jifty/Script/Schema.pm
 lib/Jifty/Script/Script.pm
 lib/Jifty/Script/Server.pm
 lib/Jifty/Script/WriteCCJS.pm
-lib/Jifty/Subs.pm
-lib/Jifty/Subs/Render.pm
 lib/Jifty/Test.pm
 lib/Jifty/Test/Dist.pm
 lib/Jifty/Test/Email.pm
@@ -521,7 +485,6 @@ share/web/static/js/iutil.js
 share/web/static/js/jifty.js
 share/web/static/js/jifty_interface.js
 share/web/static/js/jifty_smoothscroll.js
-share/web/static/js/jifty_subs.js
 share/web/static/js/jifty_utils.js
 share/web/static/js/jquery-1.4.1.js
 share/web/static/js/jquery.ajaxQueue.js
@@ -547,7 +510,6 @@ share/web/static/js/yui/menu.js
 share/web/static/js/yui/oom_select.patch
 share/web/static/js/yui/tabview.js
 share/web/static/js/yui/yahoo.js
-share/web/templates/=/subs
 share/web/templates/__jifty/autocomplete.xml
 share/web/templates/__jifty/empty
 share/web/templates/__jifty/error/_elements/error_text
diff --git a/Makefile.PL b/Makefile.PL
index deb2e08..025944f 100644
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -52,7 +52,6 @@ requires('HTTP::Date');
 requires('Hash::Merge', '0.12');
 requires('Hash::MultiValue', 0.05);
 requires('IO::Handle::Util');
-requires('IPC::PubSub' => '0.23' );
 requires('IPC::Run3');
 requires('Jifty::DBI' => '0.68' );            # Jifty::DBI::Collection Jifty::DBI::Handle Jifty::DBI::Record::Cachable Jifty::DBI::SchemaGenerator
 requires('JSON' => 2.17);
diff --git a/doc/pubsub/backend_message_types b/doc/pubsub/backend_message_types
deleted file mode 100644
index 63e6ff3..0000000
--- a/doc/pubsub/backend_message_types
+++ /dev/null
@@ -1,15 +0,0 @@
-Payload Types:
-
-ClientAction --> Republisher
-    #subscription
-    - Add Subscription (IP)
-    - Remove Subscription (IP)
-
-Republisher --> ClientRender
-    #pong-$IP
-    - Pong (IP, IS_ALIVE)
-
-Server --> Republisher
-    #pong
-    - Pong (IP, IS_ALIVE)
-
diff --git a/doc/pubsub/subscriptions b/doc/pubsub/subscriptions
deleted file mode 100644
index 99c2d3b..0000000
--- a/doc/pubsub/subscriptions
+++ /dev/null
@@ -1,83 +0,0 @@
-Subscriptions we want to support
-
-
-
-    Create,Read,Update,Delete
-        
-        Class: MyApp::Record::Foo
-     
-
-
-For hiveminder: NEWS
-
-    * on every page, we have a little box with the 3 most recent news entries:
-
-    <h2>News</h2>
-    <%perl>
-        my $sub = Jifty::ClientSubscription->new( 
-            query_class => 'BTDT::Model::News',
-            query => ['id_not' => undef],
-            # Ordering?
-            on_add => [
-            { render_with => '/fragments/news/item',
-              render => after => 'news.entries.last_child' 
-            },
-            { # how do we remove something if there are more than 3?
-            }
-
-            ]);
-
-
-For hiveminder:
-
-    My page is:
-
-        list of: tasks matching 'owner me, complete is not true'
-        each item is rendered as '/fragments/tasklist/view,  with args %ARGS and record => $found
-
-
-    Subscribe to:
-
-        * creation of things that match 'owner me, complete is not true'
-        * update, delete to anything that matches 'owner me, complete is not true' after the changes
-        * update, delete to anything that matches 'owner me, complete is not true' before the changes
-       
-
-
-    "Render this component as":
-
-        wrapper
-            list of items matching the subscription 'owner me, complete is not true'
-                render each item with '/fragments/tasklist/view', args => %ARGS, item $found
-
-
-            my $subscription = Jifty::ClientSubscription->new(
-                on_add => {
-                    args        => \%ARGS,
-                    render_with => '/fragments/tasklist/view',
-                    render => after => '.parent.last_child'
-                                # before, after, replacing
-                                
-                },
-                on_remove => {
-                    args        => \%ARGS,
-                    render => replacing => 'self'
-                    render_with => '/fragments/tasklist/fade_away'
-                },
-                query_class => 'BTDT::Model::Task',
-                query       => [ owner => 'me', complete_not => 'true' ]
-            );
-
-
-# Session::ClientSide-ish encoding of SIDs to subscribe
-# Each request carries IDs of its existing subs (stashed into ->subs)
-my $sid = Jifty->subs->add(
-    query_class => 'Ping',
-    query       => [ host => '127.0.0.1' ],
-    render_with => '/fragments/pong',
-);
-Jifty->subs->cancel($sid);
-
-# This actually just calls the fragments with Publisher-msg structures as %ARGS
-# Print-on-void-context, return-on-other-contexts
-Jifty->subs->render;
diff --git a/doc/pubsub/system_architecture.graffle b/doc/pubsub/system_architecture.graffle
deleted file mode 100644
index ac2fcc5..0000000
--- a/doc/pubsub/system_architecture.graffle
+++ /dev/null
@@ -1,1744 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>ActiveLayerIndex</key>
-	<integer>0</integer>
-	<key>AutoAdjust</key>
-	<true/>
-	<key>CanvasColor</key>
-	<dict>
-		<key>w</key>
-		<string>1</string>
-	</dict>
-	<key>CanvasOrigin</key>
-	<string>{0, 0}</string>
-	<key>CanvasScale</key>
-	<real>1</real>
-	<key>ColumnAlign</key>
-	<integer>1</integer>
-	<key>ColumnSpacing</key>
-	<real>36</real>
-	<key>CreationDate</key>
-	<string>2006-10-24 12:01:34 -0700</string>
-	<key>Creator</key>
-	<string>Jesse Vincent</string>
-	<key>DisplayScale</key>
-	<string>1 in = 1 in</string>
-	<key>GraphDocumentVersion</key>
-	<integer>5</integer>
-	<key>GraphicsList</key>
-	<array>
-		<dict>
-			<key>Bounds</key>
-			<string>{{756, 39.835}, {211, 137}}</string>
-			<key>Class</key>
-			<string>ShapedGraphic</string>
-			<key>ID</key>
-			<integer>82</integer>
-			<key>Shape</key>
-			<string>Rectangle</string>
-			<key>Text</key>
-			<dict>
-				<key>Text</key>
-				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
-{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
-
-\f0\fs24 \cf0 Jifty Push System Architecture.\
-A. Tang  and J. Vincent - \
-October 2006}</string>
-			</dict>
-		</dict>
-		<dict>
-			<key>Bounds</key>
-			<string>{{330.451, 150.979}, {256, 14}}</string>
-			<key>Class</key>
-			<string>ShapedGraphic</string>
-			<key>FitText</key>
-			<string>YES</string>
-			<key>FontInfo</key>
-			<dict>
-				<key>Color</key>
-				<dict>
-					<key>w</key>
-					<string>0</string>
-				</dict>
-				<key>Font</key>
-				<string>Helvetica</string>
-				<key>Size</key>
-				<real>12</real>
-			</dict>
-			<key>ID</key>
-			<integer>80</integer>
-			<key>Line</key>
-			<dict>
-				<key>ID</key>
-				<integer>24</integer>
-				<key>Position</key>
-				<real>0.62390816211700439</real>
-				<key>RotationType</key>
-				<integer>0</integer>
-			</dict>
-			<key>Shape</key>
-			<string>Rectangle</string>
-			<key>Style</key>
-			<dict>
-				<key>shadow</key>
-				<dict>
-					<key>Draws</key>
-					<string>NO</string>
-				</dict>
-				<key>stroke</key>
-				<dict>
-					<key>Draws</key>
-					<string>NO</string>
-				</dict>
-			</dict>
-			<key>Text</key>
-			<dict>
-				<key>Text</key>
-				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
-{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
-
-\f0\fs24 \cf0 (With a kill-me-when-republish-to-nobody flag)}</string>
-			</dict>
-		</dict>
-		<dict>
-			<key>Class</key>
-			<string>LineGraphic</string>
-			<key>ID</key>
-			<integer>78</integer>
-			<key>Points</key>
-			<array>
-				<string>{822.47, 460.7}</string>
-				<string>{822.329, 431.61}</string>
-			</array>
-			<key>Style</key>
-			<dict>
-				<key>stroke</key>
-				<dict>
-					<key>HeadArrow</key>
-					<string>FilledArrow</string>
-					<key>Pattern</key>
-					<integer>2</integer>
-					<key>TailArrow</key>
-					<string>0</string>
-				</dict>
-			</dict>
-			<key>Tail</key>
-			<dict>
-				<key>ID</key>
-				<integer>77</integer>
-			</dict>
-		</dict>
-		<dict>
-			<key>Bounds</key>
-			<string>{{748.211, 461.2}, {149, 97.8}}</string>
-			<key>Class</key>
-			<string>ShapedGraphic</string>
-			<key>ID</key>
-			<integer>77</integer>
-			<key>Shape</key>
-			<string>Rectangle</string>
-			<key>Style</key>
-			<dict>
-				<key>stroke</key>
-				<dict>
-					<key>Pattern</key>
-					<integer>2</integer>
-				</dict>
-			</dict>
-			<key>Text</key>
-			<dict>
-				<key>Text</key>
-				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
-{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
-
-\f0\fs24 \cf0 Publish unsubscription from 'ping' events \
-($SUB into $DEL-SUBS)\
-\
-(May also happen \
-upon session GC)}</string>
-			</dict>
-		</dict>
-		<dict>
-			<key>Bounds</key>
-			<string>{{45.4648, 366.851}, {907.535, 54}}</string>
-			<key>Class</key>
-			<string>ShapedGraphic</string>
-			<key>FontInfo</key>
-			<dict>
-				<key>Color</key>
-				<dict>
-					<key>w</key>
-					<string>0</string>
-				</dict>
-				<key>Font</key>
-				<string>Helvetica</string>
-				<key>NSKern</key>
-				<real>0.0</real>
-				<key>Size</key>
-				<real>12</real>
-			</dict>
-			<key>ID</key>
-			<integer>1</integer>
-			<key>Shape</key>
-			<string>Rectangle</string>
-			<key>Style</key>
-			<dict>
-				<key>fill</key>
-				<dict>
-					<key>GradientColor</key>
-					<dict>
-						<key>w</key>
-						<string>0.666667</string>
-					</dict>
-				</dict>
-			</dict>
-			<key>Text</key>
-			<dict>
-				<key>Text</key>
-				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
-{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
-
-\f0\fs24 \cf0 Message Bus}</string>
-			</dict>
-		</dict>
-		<dict>
-			<key>Bounds</key>
-			<string>{{241.567, 505}, {149, 54}}</string>
-			<key>Class</key>
-			<string>ShapedGraphic</string>
-			<key>ID</key>
-			<integer>75</integer>
-			<key>Shape</key>
-			<string>Rectangle</string>
-			<key>Text</key>
-			<dict>
-				<key>Text</key>
-				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
-{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
-
-\f0\fs24 \cf0 Publish subscription to 'ping' events \
-($SUB into $ADD-SUBS)}</string>
-			</dict>
-		</dict>
-		<dict>
-			<key>Bounds</key>
-			<string>{{105, 505}, {133, 54}}</string>
-			<key>Class</key>
-			<string>ShapedGraphic</string>
-			<key>ID</key>
-			<integer>74</integer>
-			<key>Shape</key>
-			<string>Rectangle</string>
-			<key>Text</key>
-			<dict>
-				<key>Text</key>
-				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
-{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
-
-\f0\fs24 \cf0 Start ping server}</string>
-			</dict>
-		</dict>
-		<dict>
-			<key>Bounds</key>
-			<string>{{398.5, 285.356}, {49, 28}}</string>
-			<key>Class</key>
-			<string>ShapedGraphic</string>
-			<key>FitText</key>
-			<string>YES</string>
-			<key>FontInfo</key>
-			<dict>
-				<key>Color</key>
-				<dict>
-					<key>w</key>
-					<string>0</string>
-				</dict>
-				<key>Font</key>
-				<string>Helvetica</string>
-				<key>Size</key>
-				<real>12</real>
-			</dict>
-			<key>ID</key>
-			<integer>72</integer>
-			<key>Line</key>
-			<dict>
-				<key>ID</key>
-				<integer>71</integer>
-				<key>Position</key>
-				<real>0.51288449764251709</real>
-				<key>RotationType</key>
-				<integer>0</integer>
-			</dict>
-			<key>Shape</key>
-			<string>Rectangle</string>
-			<key>Style</key>
-			<dict>
-				<key>shadow</key>
-				<dict>
-					<key>Draws</key>
-					<string>NO</string>
-				</dict>
-				<key>stroke</key>
-				<dict>
-					<key>Draws</key>
-					<string>NO</string>
-				</dict>
-			</dict>
-			<key>Text</key>
-			<dict>
-				<key>Text</key>
-				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
-{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
-
-\f0\fs24 \cf0 Send\
-[$SUB]}</string>
-			</dict>
-		</dict>
-		<dict>
-			<key>Class</key>
-			<string>LineGraphic</string>
-			<key>ID</key>
-			<integer>71</integer>
-			<key>Points</key>
-			<array>
-				<string>{423, 349.516}</string>
-				<string>{423, 251.716}</string>
-			</array>
-			<key>Style</key>
-			<dict>
-				<key>stroke</key>
-				<dict>
-					<key>HeadArrow</key>
-					<string>FilledArrow</string>
-					<key>TailArrow</key>
-					<string>0</string>
-				</dict>
-			</dict>
-		</dict>
-		<dict>
-			<key>Bounds</key>
-			<string>{{784.411, 610.503}, {77, 42}}</string>
-			<key>Class</key>
-			<string>ShapedGraphic</string>
-			<key>FitText</key>
-			<string>YES</string>
-			<key>FontInfo</key>
-			<dict>
-				<key>Color</key>
-				<dict>
-					<key>w</key>
-					<string>0</string>
-				</dict>
-				<key>Font</key>
-				<string>Helvetica</string>
-				<key>Size</key>
-				<real>12</real>
-			</dict>
-			<key>ID</key>
-			<integer>69</integer>
-			<key>Line</key>
-			<dict>
-				<key>ID</key>
-				<integer>68</integer>
-				<key>Position</key>
-				<real>0.42627021670341492</real>
-				<key>RotationType</key>
-				<integer>0</integer>
-			</dict>
-			<key>Shape</key>
-			<string>Rectangle</string>
-			<key>Style</key>
-			<dict>
-				<key>shadow</key>
-				<dict>
-					<key>Draws</key>
-					<string>NO</string>
-				</dict>
-				<key>stroke</key>
-				<dict>
-					<key>Draws</key>
-					<string>NO</string>
-				</dict>
-			</dict>
-			<key>Text</key>
-			<dict>
-				<key>Text</key>
-				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
-{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
-
-\f0\fs24 \cf0 Jifty::Action:\
-Unsubscribe\
-Action::Ping}</string>
-			</dict>
-		</dict>
-		<dict>
-			<key>Class</key>
-			<string>LineGraphic</string>
-			<key>Head</key>
-			<dict>
-				<key>ID</key>
-				<integer>77</integer>
-			</dict>
-			<key>ID</key>
-			<integer>68</integer>
-			<key>Points</key>
-			<array>
-				<string>{823, 685}</string>
-				<string>{822.792, 559.5}</string>
-			</array>
-			<key>Style</key>
-			<dict>
-				<key>stroke</key>
-				<dict>
-					<key>HeadArrow</key>
-					<string>FilledArrow</string>
-					<key>Pattern</key>
-					<integer>2</integer>
-					<key>TailArrow</key>
-					<string>0</string>
-				</dict>
-			</dict>
-		</dict>
-		<dict>
-			<key>Bounds</key>
-			<string>{{323.771, 263.402}, {83, 28}}</string>
-			<key>Class</key>
-			<string>ShapedGraphic</string>
-			<key>FitText</key>
-			<string>YES</string>
-			<key>FontInfo</key>
-			<dict>
-				<key>Color</key>
-				<dict>
-					<key>w</key>
-					<string>0</string>
-				</dict>
-				<key>Font</key>
-				<string>Helvetica</string>
-				<key>Size</key>
-				<real>12</real>
-			</dict>
-			<key>ID</key>
-			<integer>62</integer>
-			<key>Line</key>
-			<dict>
-				<key>ID</key>
-				<integer>61</integer>
-				<key>Position</key>
-				<real>0.27589595317840576</real>
-				<key>RotationType</key>
-				<integer>0</integer>
-			</dict>
-			<key>Shape</key>
-			<string>Rectangle</string>
-			<key>Style</key>
-			<dict>
-				<key>shadow</key>
-				<dict>
-					<key>Draws</key>
-					<string>NO</string>
-				</dict>
-				<key>stroke</key>
-				<dict>
-					<key>Draws</key>
-					<string>NO</string>
-				</dict>
-			</dict>
-			<key>Text</key>
-			<dict>
-				<key>Text</key>
-				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
-{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
-
-\f0\fs24 \cf0 Poll\
-$ADD-SUBS }</string>
-			</dict>
-		</dict>
-		<dict>
-			<key>Class</key>
-			<string>LineGraphic</string>
-			<key>ID</key>
-			<integer>61</integer>
-			<key>Points</key>
-			<array>
-				<string>{364.995, 247.455}</string>
-				<string>{365.995, 356}</string>
-			</array>
-			<key>Style</key>
-			<dict>
-				<key>stroke</key>
-				<dict>
-					<key>HeadArrow</key>
-					<string>FilledArrow</string>
-					<key>TailArrow</key>
-					<string>0</string>
-				</dict>
-			</dict>
-		</dict>
-		<dict>
-			<key>Bounds</key>
-			<string>{{982.555, 751.48}, {61, 14}}</string>
-			<key>Class</key>
-			<string>ShapedGraphic</string>
-			<key>FitText</key>
-			<string>YES</string>
-			<key>FontInfo</key>
-			<dict>
-				<key>Color</key>
-				<dict>
-					<key>w</key>
-					<string>0</string>
-				</dict>
-				<key>Font</key>
-				<string>Helvetica</string>
-				<key>Size</key>
-				<real>12</real>
-			</dict>
-			<key>ID</key>
-			<integer>60</integer>
-			<key>Line</key>
-			<dict>
-				<key>ID</key>
-				<integer>59</integer>
-				<key>Position</key>
-				<real>0.89849430322647095</real>
-				<key>RotationType</key>
-				<integer>0</integer>
-			</dict>
-			<key>Shape</key>
-			<string>Rectangle</string>
-			<key>Style</key>
-			<dict>
-				<key>shadow</key>
-				<dict>
-					<key>Draws</key>
-					<string>NO</string>
-				</dict>
-				<key>stroke</key>
-				<dict>
-					<key>Draws</key>
-					<string>NO</string>
-				</dict>
-			</dict>
-			<key>Text</key>
-			<dict>
-				<key>Text</key>
-				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
-{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
-
-\f0\fs24 \cf0 Time >>>}</string>
-			</dict>
-		</dict>
-		<dict>
-			<key>Class</key>
-			<string>LineGraphic</string>
-			<key>ID</key>
-			<integer>59</integer>
-			<key>Points</key>
-			<array>
-				<string>{30.8634, 757}</string>
-				<string>{1124.02, 758.647}</string>
-			</array>
-			<key>Style</key>
-			<dict>
-				<key>stroke</key>
-				<dict>
-					<key>HeadArrow</key>
-					<string>FilledArrow</string>
-					<key>TailArrow</key>
-					<string>0</string>
-				</dict>
-			</dict>
-		</dict>
-		<dict>
-			<key>Bounds</key>
-			<string>{{652.329, 607.255}, {84, 28}}</string>
-			<key>Class</key>
-			<string>ShapedGraphic</string>
-			<key>FitText</key>
-			<string>YES</string>
-			<key>FontInfo</key>
-			<dict>
-				<key>Color</key>
-				<dict>
-					<key>w</key>
-					<string>0</string>
-				</dict>
-				<key>Font</key>
-				<string>Helvetica</string>
-				<key>Size</key>
-				<real>12</real>
-			</dict>
-			<key>ID</key>
-			<integer>55</integer>
-			<key>Line</key>
-			<dict>
-				<key>ID</key>
-				<integer>54</integer>
-				<key>Position</key>
-				<real>0.51953768730163574</real>
-				<key>RotationType</key>
-				<integer>0</integer>
-			</dict>
-			<key>Shape</key>
-			<string>Rectangle</string>
-			<key>Style</key>
-			<dict>
-				<key>shadow</key>
-				<dict>
-					<key>Draws</key>
-					<string>NO</string>
-				</dict>
-				<key>stroke</key>
-				<dict>
-					<key>Draws</key>
-					<string>NO</string>
-				</dict>
-			</dict>
-			<key>Text</key>
-			<dict>
-				<key>Text</key>
-				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
-{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
-
-\f0\fs24 \cf0 Push+Render\
-$EVENT}</string>
-			</dict>
-		</dict>
-		<dict>
-			<key>Class</key>
-			<string>LineGraphic</string>
-			<key>ID</key>
-			<integer>54</integer>
-			<key>Points</key>
-			<array>
-				<string>{694.329, 546.643}</string>
-				<string>{694.329, 690.255}</string>
-			</array>
-			<key>Style</key>
-			<dict>
-				<key>stroke</key>
-				<dict>
-					<key>HeadArrow</key>
-					<string>FilledArrow</string>
-					<key>TailArrow</key>
-					<string>0</string>
-				</dict>
-			</dict>
-		</dict>
-		<dict>
-			<key>Bounds</key>
-			<string>{{655.57, 439.363}, {49, 24}}</string>
-			<key>Class</key>
-			<string>ShapedGraphic</string>
-			<key>FitText</key>
-			<string>YES</string>
-			<key>FontInfo</key>
-			<dict>
-				<key>Color</key>
-				<dict>
-					<key>w</key>
-					<string>0</string>
-				</dict>
-				<key>Font</key>
-				<string>Helvetica-Bold</string>
-				<key>Size</key>
-				<real>10</real>
-			</dict>
-			<key>ID</key>
-			<integer>56</integer>
-			<key>Line</key>
-			<dict>
-				<key>ID</key>
-				<integer>52</integer>
-				<key>Position</key>
-				<real>0.45289328694343567</real>
-				<key>RotationType</key>
-				<integer>0</integer>
-			</dict>
-			<key>Shape</key>
-			<string>Rectangle</string>
-			<key>Style</key>
-			<dict>
-				<key>shadow</key>
-				<dict>
-					<key>Draws</key>
-					<string>NO</string>
-				</dict>
-				<key>stroke</key>
-				<dict>
-					<key>Draws</key>
-					<string>NO</string>
-				</dict>
-			</dict>
-			<key>Text</key>
-			<dict>
-				<key>Text</key>
-				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
-{\fonttbl\f0\fswiss\fcharset77 Helvetica-Bold;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
-
-\f0\b\fs20 \cf0 Send\
-$EVENT}</string>
-			</dict>
-		</dict>
-		<dict>
-			<key>Class</key>
-			<string>LineGraphic</string>
-			<key>ID</key>
-			<integer>52</integer>
-			<key>Points</key>
-			<array>
-				<string>{680.07, 424.383}</string>
-				<string>{680.07, 483.957}</string>
-			</array>
-			<key>Style</key>
-			<dict>
-				<key>stroke</key>
-				<dict>
-					<key>HeadArrow</key>
-					<string>FilledArrow</string>
-					<key>TailArrow</key>
-					<string>0</string>
-				</dict>
-			</dict>
-		</dict>
-		<dict>
-			<key>Bounds</key>
-			<string>{{603.273, 452.914}, {52, 28}}</string>
-			<key>Class</key>
-			<string>ShapedGraphic</string>
-			<key>FitText</key>
-			<string>YES</string>
-			<key>FontInfo</key>
-			<dict>
-				<key>Color</key>
-				<dict>
-					<key>w</key>
-					<string>0</string>
-				</dict>
-				<key>Font</key>
-				<string>Helvetica</string>
-				<key>Size</key>
-				<real>12</real>
-			</dict>
-			<key>ID</key>
-			<integer>51</integer>
-			<key>Line</key>
-			<dict>
-				<key>ID</key>
-				<integer>50</integer>
-				<key>Position</key>
-				<real>0.41240772604942322</real>
-				<key>RotationType</key>
-				<integer>0</integer>
-			</dict>
-			<key>Shape</key>
-			<string>Rectangle</string>
-			<key>Style</key>
-			<dict>
-				<key>shadow</key>
-				<dict>
-					<key>Draws</key>
-					<string>NO</string>
-				</dict>
-				<key>stroke</key>
-				<dict>
-					<key>Draws</key>
-					<string>NO</string>
-				</dict>
-			</dict>
-			<key>Text</key>
-			<dict>
-				<key>Text</key>
-				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
-{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
-
-\f0\fs24 \cf0 Poll\
-[$SUB] }</string>
-			</dict>
-		</dict>
-		<dict>
-			<key>Class</key>
-			<string>LineGraphic</string>
-			<key>ID</key>
-			<integer>50</integer>
-			<key>Points</key>
-			<array>
-				<string>{629, 489.057}</string>
-				<string>{629.661, 435.363}</string>
-			</array>
-			<key>Style</key>
-			<dict>
-				<key>stroke</key>
-				<dict>
-					<key>HeadArrow</key>
-					<string>FilledArrow</string>
-					<key>TailArrow</key>
-					<string>0</string>
-				</dict>
-			</dict>
-		</dict>
-		<dict>
-			<key>Bounds</key>
-			<string>{{532.773, 447.813}, {52, 28}}</string>
-			<key>Class</key>
-			<string>ShapedGraphic</string>
-			<key>FitText</key>
-			<string>YES</string>
-			<key>FontInfo</key>
-			<dict>
-				<key>Color</key>
-				<dict>
-					<key>w</key>
-					<string>0</string>
-				</dict>
-				<key>Font</key>
-				<string>Helvetica</string>
-				<key>Size</key>
-				<real>12</real>
-			</dict>
-			<key>ID</key>
-			<integer>49</integer>
-			<key>Line</key>
-			<dict>
-				<key>ID</key>
-				<integer>48</integer>
-				<key>Position</key>
-				<real>0.41240772604942322</real>
-				<key>RotationType</key>
-				<integer>0</integer>
-			</dict>
-			<key>Shape</key>
-			<string>Rectangle</string>
-			<key>Style</key>
-			<dict>
-				<key>shadow</key>
-				<dict>
-					<key>Draws</key>
-					<string>NO</string>
-				</dict>
-				<key>stroke</key>
-				<dict>
-					<key>Draws</key>
-					<string>NO</string>
-				</dict>
-			</dict>
-			<key>Text</key>
-			<dict>
-				<key>Text</key>
-				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
-{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
-
-\f0\fs24 \cf0 Poll\
-[$SUB] }</string>
-			</dict>
-		</dict>
-		<dict>
-			<key>Class</key>
-			<string>LineGraphic</string>
-			<key>ID</key>
-			<integer>48</integer>
-			<key>Points</key>
-			<array>
-				<string>{558.5, 483.957}</string>
-				<string>{559.161, 430.263}</string>
-			</array>
-			<key>Style</key>
-			<dict>
-				<key>stroke</key>
-				<dict>
-					<key>HeadArrow</key>
-					<string>FilledArrow</string>
-					<key>TailArrow</key>
-					<string>0</string>
-				</dict>
-			</dict>
-		</dict>
-		<dict>
-			<key>Bounds</key>
-			<string>{{432.043, 446.396}, {52, 28}}</string>
-			<key>Class</key>
-			<string>ShapedGraphic</string>
-			<key>FitText</key>
-			<string>YES</string>
-			<key>FontInfo</key>
-			<dict>
-				<key>Color</key>
-				<dict>
-					<key>w</key>
-					<string>0</string>
-				</dict>
-				<key>Font</key>
-				<string>Helvetica</string>
-				<key>Size</key>
-				<real>12</real>
-			</dict>
-			<key>ID</key>
-			<integer>47</integer>
-			<key>Line</key>
-			<dict>
-				<key>ID</key>
-				<integer>46</integer>
-				<key>Position</key>
-				<real>0.36850014328956604</real>
-				<key>RotationType</key>
-				<integer>0</integer>
-			</dict>
-			<key>Shape</key>
-			<string>Rectangle</string>
-			<key>Style</key>
-			<dict>
-				<key>shadow</key>
-				<dict>
-					<key>Draws</key>
-					<string>NO</string>
-				</dict>
-				<key>stroke</key>
-				<dict>
-					<key>Draws</key>
-					<string>NO</string>
-				</dict>
-			</dict>
-			<key>Text</key>
-			<dict>
-				<key>Text</key>
-				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
-{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
-
-\f0\fs24 \cf0 Poll\
-[$SUB] }</string>
-			</dict>
-		</dict>
-		<dict>
-			<key>Class</key>
-			<string>LineGraphic</string>
-			<key>ID</key>
-			<integer>46</integer>
-			<key>Points</key>
-			<array>
-				<string>{458, 481}</string>
-				<string>{458.117, 425.087}</string>
-			</array>
-			<key>Style</key>
-			<dict>
-				<key>stroke</key>
-				<dict>
-					<key>HeadArrow</key>
-					<string>FilledArrow</string>
-					<key>TailArrow</key>
-					<string>0</string>
-				</dict>
-			</dict>
-		</dict>
-		<dict>
-			<key>Bounds</key>
-			<string>{{558.5, 256.36}, {57, 42}}</string>
-			<key>Class</key>
-			<string>ShapedGraphic</string>
-			<key>FitText</key>
-			<string>YES</string>
-			<key>FontInfo</key>
-			<dict>
-				<key>Color</key>
-				<dict>
-					<key>w</key>
-					<string>0</string>
-				</dict>
-				<key>Font</key>
-				<string>Helvetica</string>
-				<key>Size</key>
-				<real>12</real>
-			</dict>
-			<key>ID</key>
-			<integer>45</integer>
-			<key>Line</key>
-			<dict>
-				<key>ID</key>
-				<integer>44</integer>
-				<key>Position</key>
-				<real>0.24552829563617706</real>
-				<key>RotationType</key>
-				<integer>0</integer>
-			</dict>
-			<key>Shape</key>
-			<string>Rectangle</string>
-			<key>Style</key>
-			<dict>
-				<key>shadow</key>
-				<dict>
-					<key>Draws</key>
-					<string>NO</string>
-				</dict>
-				<key>stroke</key>
-				<dict>
-					<key>Draws</key>
-					<string>NO</string>
-				</dict>
-			</dict>
-			<key>Text</key>
-			<dict>
-				<key>Text</key>
-				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
-{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
-
-\f0\fs24 \cf0 Publish \
-$EVENT\
-to $SUB}</string>
-			</dict>
-		</dict>
-		<dict>
-			<key>Class</key>
-			<string>LineGraphic</string>
-			<key>ID</key>
-			<integer>44</integer>
-			<key>Points</key>
-			<array>
-				<string>{587, 249.615}</string>
-				<string>{587, 362.615}</string>
-			</array>
-			<key>Style</key>
-			<dict>
-				<key>stroke</key>
-				<dict>
-					<key>HeadArrow</key>
-					<string>FilledArrow</string>
-					<key>TailArrow</key>
-					<string>0</string>
-				</dict>
-			</dict>
-		</dict>
-		<dict>
-			<key>Class</key>
-			<string>LineGraphic</string>
-			<key>ID</key>
-			<integer>42</integer>
-			<key>Points</key>
-			<array>
-				<string>{315.076, 504.5}</string>
-				<string>{312.334, 428.426}</string>
-			</array>
-			<key>Style</key>
-			<dict>
-				<key>stroke</key>
-				<dict>
-					<key>HeadArrow</key>
-					<string>FilledArrow</string>
-					<key>TailArrow</key>
-					<string>0</string>
-				</dict>
-			</dict>
-			<key>Tail</key>
-			<dict>
-				<key>ID</key>
-				<integer>75</integer>
-			</dict>
-		</dict>
-		<dict>
-			<key>Bounds</key>
-			<string>{{55.0165, 435.416}, {163, 42}}</string>
-			<key>Class</key>
-			<string>ShapedGraphic</string>
-			<key>FitText</key>
-			<string>YES</string>
-			<key>FontInfo</key>
-			<dict>
-				<key>Color</key>
-				<dict>
-					<key>w</key>
-					<string>0</string>
-				</dict>
-				<key>Font</key>
-				<string>Helvetica</string>
-				<key>Size</key>
-				<real>12</real>
-			</dict>
-			<key>ID</key>
-			<integer>41</integer>
-			<key>Line</key>
-			<dict>
-				<key>ID</key>
-				<integer>40</integer>
-				<key>Position</key>
-				<real>0.48351499438285828</real>
-				<key>RotationType</key>
-				<integer>0</integer>
-			</dict>
-			<key>Shape</key>
-			<string>Rectangle</string>
-			<key>Style</key>
-			<dict>
-				<key>shadow</key>
-				<dict>
-					<key>Draws</key>
-					<string>NO</string>
-				</dict>
-				<key>stroke</key>
-				<dict>
-					<key>Draws</key>
-					<string>NO</string>
-				</dict>
-			</dict>
-			<key>Text</key>
-			<dict>
-				<key>Text</key>
-				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
-{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
-
-\f0\fs24 \cf0 Add \
-Subscription Channel $SUB:\
-Action::Ping}</string>
-			</dict>
-		</dict>
-		<dict>
-			<key>Class</key>
-			<string>LineGraphic</string>
-			<key>ID</key>
-			<integer>40</integer>
-			<key>Points</key>
-			<array>
-				<string>{137, 482.62}</string>
-				<string>{136, 428.426}</string>
-			</array>
-			<key>Style</key>
-			<dict>
-				<key>stroke</key>
-				<dict>
-					<key>HeadArrow</key>
-					<string>FilledArrow</string>
-					<key>TailArrow</key>
-					<string>0</string>
-				</dict>
-			</dict>
-		</dict>
-		<dict>
-			<key>Bounds</key>
-			<string>{{383.843, 121.654}, {149, 28}}</string>
-			<key>Class</key>
-			<string>ShapedGraphic</string>
-			<key>FitText</key>
-			<string>YES</string>
-			<key>FontInfo</key>
-			<dict>
-				<key>Color</key>
-				<dict>
-					<key>w</key>
-					<string>0</string>
-				</dict>
-				<key>Font</key>
-				<string>Helvetica</string>
-				<key>Size</key>
-				<real>12</real>
-			</dict>
-			<key>ID</key>
-			<integer>38</integer>
-			<key>Line</key>
-			<dict>
-				<key>ID</key>
-				<integer>24</integer>
-				<key>Position</key>
-				<real>0.42278197407722473</real>
-				<key>RotationType</key>
-				<integer>0</integer>
-			</dict>
-			<key>Shape</key>
-			<string>Rectangle</string>
-			<key>Style</key>
-			<dict>
-				<key>shadow</key>
-				<dict>
-					<key>Draws</key>
-					<string>NO</string>
-				</dict>
-				<key>stroke</key>
-				<dict>
-					<key>Draws</key>
-					<string>NO</string>
-				</dict>
-			</dict>
-			<key>Text</key>
-			<dict>
-				<key>Text</key>
-				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
-{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
-
-\f0\fs24 \cf0 Publishes Event $EVENT:\
-PING 127.0.0.1 1ms}</string>
-			</dict>
-		</dict>
-		<dict>
-			<key>Bounds</key>
-			<string>{{30.8634, 623.165}, {71, 28}}</string>
-			<key>Class</key>
-			<string>ShapedGraphic</string>
-			<key>FitText</key>
-			<string>YES</string>
-			<key>FontInfo</key>
-			<dict>
-				<key>Color</key>
-				<dict>
-					<key>w</key>
-					<string>0</string>
-				</dict>
-				<key>Font</key>
-				<string>Helvetica</string>
-				<key>Size</key>
-				<real>12</real>
-			</dict>
-			<key>ID</key>
-			<integer>36</integer>
-			<key>Line</key>
-			<dict>
-				<key>ID</key>
-				<integer>34</integer>
-				<key>Position</key>
-				<real>0.38565847277641296</real>
-				<key>RotationType</key>
-				<integer>0</integer>
-			</dict>
-			<key>Shape</key>
-			<string>Rectangle</string>
-			<key>Style</key>
-			<dict>
-				<key>shadow</key>
-				<dict>
-					<key>Draws</key>
-					<string>NO</string>
-				</dict>
-				<key>stroke</key>
-				<dict>
-					<key>Draws</key>
-					<string>NO</string>
-				</dict>
-			</dict>
-			<key>Text</key>
-			<dict>
-				<key>Text</key>
-				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
-{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
-
-\f0\fs24 \cf0 Jifty Action:\
-Ping}</string>
-			</dict>
-		</dict>
-		<dict>
-			<key>Class</key>
-			<string>LineGraphic</string>
-			<key>ID</key>
-			<integer>34</integer>
-			<key>Points</key>
-			<array>
-				<string>{65, 690}</string>
-				<string>{68.5352, 553}</string>
-			</array>
-			<key>Style</key>
-			<dict>
-				<key>stroke</key>
-				<dict>
-					<key>HeadArrow</key>
-					<string>FilledArrow</string>
-					<key>TailArrow</key>
-					<string>0</string>
-				</dict>
-			</dict>
-		</dict>
-		<dict>
-			<key>Bounds</key>
-			<string>{{39, 693.868}, {1051.46, 54}}</string>
-			<key>Class</key>
-			<string>ShapedGraphic</string>
-			<key>ID</key>
-			<integer>31</integer>
-			<key>Shape</key>
-			<string>Rectangle</string>
-			<key>Text</key>
-			<dict>
-				<key>Text</key>
-				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
-{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
-
-\f0\fs24 \cf0 Client Browser}</string>
-			</dict>
-		</dict>
-		<dict>
-			<key>Bounds</key>
-			<string>{{470.033, 293.501}, {88.9045, 42}}</string>
-			<key>Class</key>
-			<string>ShapedGraphic</string>
-			<key>FitText</key>
-			<string>Vertical</string>
-			<key>FontInfo</key>
-			<dict>
-				<key>Color</key>
-				<dict>
-					<key>w</key>
-					<string>0</string>
-				</dict>
-				<key>Font</key>
-				<string>Helvetica</string>
-				<key>Size</key>
-				<real>12</real>
-			</dict>
-			<key>ID</key>
-			<integer>29</integer>
-			<key>Line</key>
-			<dict>
-				<key>ID</key>
-				<integer>28</integer>
-				<key>Position</key>
-				<real>0.59332269430160522</real>
-				<key>RotationType</key>
-				<integer>0</integer>
-			</dict>
-			<key>Shape</key>
-			<string>Rectangle</string>
-			<key>Style</key>
-			<dict>
-				<key>shadow</key>
-				<dict>
-					<key>Draws</key>
-					<string>NO</string>
-				</dict>
-				<key>stroke</key>
-				<dict>
-					<key>Draws</key>
-					<string>NO</string>
-				</dict>
-			</dict>
-			<key>Text</key>
-			<dict>
-				<key>Text</key>
-				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
-{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
-
-\f0\fs24 \cf0 Publishes to \
-Channel \
-"$SERVER"}</string>
-			</dict>
-			<key>Wrap</key>
-			<string>YES</string>
-		</dict>
-		<dict>
-			<key>Class</key>
-			<string>LineGraphic</string>
-			<key>ID</key>
-			<integer>28</integer>
-			<key>Points</key>
-			<array>
-				<string>{514.486, 247.455}</string>
-				<string>{514.486, 360.455}</string>
-			</array>
-			<key>Style</key>
-			<dict>
-				<key>stroke</key>
-				<dict>
-					<key>HeadArrow</key>
-					<string>FilledArrow</string>
-					<key>TailArrow</key>
-					<string>0</string>
-				</dict>
-			</dict>
-		</dict>
-		<dict>
-			<key>Bounds</key>
-			<string>{{44.4648, 205.059}, {907.535, 36}}</string>
-			<key>Class</key>
-			<string>ShapedGraphic</string>
-			<key>FontInfo</key>
-			<dict>
-				<key>Color</key>
-				<dict>
-					<key>w</key>
-					<string>0</string>
-				</dict>
-				<key>Font</key>
-				<string>Helvetica</string>
-				<key>NSKern</key>
-				<real>0.0</real>
-				<key>Size</key>
-				<real>12</real>
-			</dict>
-			<key>ID</key>
-			<integer>27</integer>
-			<key>Shape</key>
-			<string>Rectangle</string>
-			<key>Style</key>
-			<dict>
-				<key>fill</key>
-				<dict>
-					<key>GradientColor</key>
-					<dict>
-						<key>w</key>
-						<string>0.666667</string>
-					</dict>
-				</dict>
-			</dict>
-			<key>Text</key>
-			<dict>
-				<key>Text</key>
-				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
-{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
-
-\f0\fs24 \cf0 Republisher}</string>
-			</dict>
-		</dict>
-		<dict>
-			<key>Class</key>
-			<string>LineGraphic</string>
-			<key>ID</key>
-			<integer>24</integer>
-			<key>Points</key>
-			<array>
-				<string>{458.117, 88.7247}</string>
-				<string>{458.652, 199.725}</string>
-			</array>
-			<key>Style</key>
-			<dict>
-				<key>stroke</key>
-				<dict>
-					<key>HeadArrow</key>
-					<string>FilledArrow</string>
-					<key>TailArrow</key>
-					<string>0</string>
-				</dict>
-			</dict>
-		</dict>
-		<dict>
-			<key>Bounds</key>
-			<string>{{174, 29.3902}, {410.773, 59.5743}}</string>
-			<key>Class</key>
-			<string>ShapedGraphic</string>
-			<key>FontInfo</key>
-			<dict>
-				<key>Color</key>
-				<dict>
-					<key>w</key>
-					<string>0</string>
-				</dict>
-				<key>Font</key>
-				<string>Helvetica</string>
-				<key>NSKern</key>
-				<real>0.0</real>
-				<key>Size</key>
-				<real>12</real>
-			</dict>
-			<key>ID</key>
-			<integer>4</integer>
-			<key>Shape</key>
-			<string>Rectangle</string>
-			<key>Style</key>
-			<dict>
-				<key>fill</key>
-				<dict>
-					<key>GradientColor</key>
-					<dict>
-						<key>w</key>
-						<string>0.666667</string>
-					</dict>
-				</dict>
-			</dict>
-			<key>Text</key>
-			<dict>
-				<key>Text</key>
-				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
-{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
-
-\f0\fs24 \cf0 Server $SERVER}</string>
-			</dict>
-		</dict>
-		<dict>
-			<key>Class</key>
-			<string>LineGraphic</string>
-			<key>Head</key>
-			<dict>
-				<key>ID</key>
-				<integer>4</integer>
-			</dict>
-			<key>ID</key>
-			<integer>22</integer>
-			<key>Points</key>
-			<array>
-				<string>{129.731, 504.727}</string>
-				<string>{-23, 405}</string>
-				<string>{344.348, 89.2904}</string>
-			</array>
-			<key>Style</key>
-			<dict>
-				<key>stroke</key>
-				<dict>
-					<key>HeadArrow</key>
-					<string>FilledArrow</string>
-					<key>LineType</key>
-					<integer>1</integer>
-					<key>TailArrow</key>
-					<string>0</string>
-				</dict>
-			</dict>
-			<key>Tail</key>
-			<dict>
-				<key>ID</key>
-				<integer>74</integer>
-			</dict>
-		</dict>
-		<dict>
-			<key>Bounds</key>
-			<string>{{65, 502}, {340.944, 59.5743}}</string>
-			<key>Class</key>
-			<string>ShapedGraphic</string>
-			<key>ID</key>
-			<integer>79</integer>
-			<key>Shape</key>
-			<string>Rectangle</string>
-		</dict>
-		<dict>
-			<key>Bounds</key>
-			<string>{{45.4648, 490.194}, {907.535, 54}}</string>
-			<key>Class</key>
-			<string>ShapedGraphic</string>
-			<key>ID</key>
-			<integer>32</integer>
-			<key>Shape</key>
-			<string>Rectangle</string>
-			<key>Text</key>
-			<dict>
-				<key>Text</key>
-				<string>{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf410
-{\fonttbl\f0\fswiss\fcharset77 Helvetica;}
-{\colortbl;\red255\green255\blue255;}
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural
-
-\f0\fs24 \cf0 Jifty Server}</string>
-			</dict>
-		</dict>
-	</array>
-	<key>GridInfo</key>
-	<dict/>
-	<key>GuidesLocked</key>
-	<string>NO</string>
-	<key>GuidesVisible</key>
-	<string>YES</string>
-	<key>HPages</key>
-	<integer>2</integer>
-	<key>ImageCounter</key>
-	<integer>1</integer>
-	<key>IsPalette</key>
-	<string>NO</string>
-	<key>KeepToScale</key>
-	<false/>
-	<key>Layers</key>
-	<array>
-		<dict>
-			<key>Lock</key>
-			<string>NO</string>
-			<key>Name</key>
-			<string>Layer 1</string>
-			<key>Print</key>
-			<string>YES</string>
-			<key>View</key>
-			<string>YES</string>
-		</dict>
-	</array>
-	<key>LayoutInfo</key>
-	<dict>
-		<key>LayoutTarget</key>
-		<integer>3</integer>
-	</dict>
-	<key>LinksVisible</key>
-	<string>NO</string>
-	<key>MagnetsVisible</key>
-	<string>NO</string>
-	<key>MasterSheet</key>
-	<string>Master 1</string>
-	<key>MasterSheets</key>
-	<array>
-		<dict>
-			<key>ActiveLayerIndex</key>
-			<integer>0</integer>
-			<key>AutoAdjust</key>
-			<true/>
-			<key>CanvasColor</key>
-			<dict>
-				<key>w</key>
-				<string>1</string>
-			</dict>
-			<key>CanvasOrigin</key>
-			<string>{0, 0}</string>
-			<key>CanvasScale</key>
-			<real>1</real>
-			<key>ColumnAlign</key>
-			<integer>1</integer>
-			<key>ColumnSpacing</key>
-			<real>36</real>
-			<key>DisplayScale</key>
-			<string>1 in = 1 in</string>
-			<key>GraphicsList</key>
-			<array/>
-			<key>GridInfo</key>
-			<dict/>
-			<key>HPages</key>
-			<integer>1</integer>
-			<key>IsPalette</key>
-			<string>NO</string>
-			<key>KeepToScale</key>
-			<false/>
-			<key>Layers</key>
-			<array>
-				<dict>
-					<key>Lock</key>
-					<string>NO</string>
-					<key>Name</key>
-					<string>Layer 1</string>
-					<key>Print</key>
-					<string>YES</string>
-					<key>View</key>
-					<string>YES</string>
-				</dict>
-			</array>
-			<key>LayoutInfo</key>
-			<dict>
-				<key>LayoutTarget</key>
-				<integer>3</integer>
-			</dict>
-			<key>Orientation</key>
-			<integer>2</integer>
-			<key>OutlineStyle</key>
-			<string>Basic</string>
-			<key>RowAlign</key>
-			<integer>1</integer>
-			<key>RowSpacing</key>
-			<real>36</real>
-			<key>SheetTitle</key>
-			<string>Master 1</string>
-			<key>UniqueID</key>
-			<integer>1</integer>
-			<key>VPages</key>
-			<integer>1</integer>
-		</dict>
-	</array>
-	<key>ModificationDate</key>
-	<string>2006-10-24 15:25:32 -0700</string>
-	<key>Modifier</key>
-	<string>Jesse Vincent</string>
-	<key>NotesVisible</key>
-	<string>NO</string>
-	<key>Orientation</key>
-	<integer>2</integer>
-	<key>OriginVisible</key>
-	<string>NO</string>
-	<key>OutlineStyle</key>
-	<string>Basic</string>
-	<key>PageBreaks</key>
-	<string>YES</string>
-	<key>PrintInfo</key>
-	<dict>
-		<key>NSBottomMargin</key>
-		<array>
-			<string>float</string>
-			<string>0</string>
-		</array>
-		<key>NSLeftMargin</key>
-		<array>
-			<string>float</string>
-			<string>0</string>
-		</array>
-		<key>NSRightMargin</key>
-		<array>
-			<string>float</string>
-			<string>0</string>
-		</array>
-		<key>NSTopMargin</key>
-		<array>
-			<string>float</string>
-			<string>0</string>
-		</array>
-	</dict>
-	<key>ReadOnly</key>
-	<string>NO</string>
-	<key>RowAlign</key>
-	<integer>1</integer>
-	<key>RowSpacing</key>
-	<real>36</real>
-	<key>SheetTitle</key>
-	<string>Canvas 1</string>
-	<key>SmartAlignmentGuidesActive</key>
-	<string>YES</string>
-	<key>SmartDistanceGuidesActive</key>
-	<string>YES</string>
-	<key>UniqueID</key>
-	<integer>1</integer>
-	<key>UseEntirePage</key>
-	<true/>
-	<key>VPages</key>
-	<integer>1</integer>
-	<key>WindowInfo</key>
-	<dict>
-		<key>CurrentSheet</key>
-		<string>0</string>
-		<key>DrawerOpen</key>
-		<true/>
-		<key>DrawerTab</key>
-		<string>Outline</string>
-		<key>DrawerWidth</key>
-		<real>209</real>
-		<key>FitInWindow</key>
-		<false/>
-		<key>Frame</key>
-		<string>{{0, 0}, {1680, 1072}}</string>
-		<key>ShowRuler</key>
-		<false/>
-		<key>ShowStatusBar</key>
-		<true/>
-		<key>VisibleRegion</key>
-		<string>{{-250, -92}, {1665, 958}}</string>
-		<key>Zoom</key>
-		<string>1</string>
-	</dict>
-</dict>
-</plist>
diff --git a/doc/pubsub/system_architecture.png b/doc/pubsub/system_architecture.png
deleted file mode 100644
index e54e97a..0000000
Binary files a/doc/pubsub/system_architecture.png and /dev/null differ
diff --git a/examples/Chat/Makefile.PL b/examples/Chat/Makefile.PL
deleted file mode 100644
index 9eae546..0000000
--- a/examples/Chat/Makefile.PL
+++ /dev/null
@@ -1,6 +0,0 @@
-use inc::Module::Install;
-name('Chat');
-version('0.01');
-requires('Jifty' => '0.60912');
-
-WriteAll;
diff --git a/examples/Chat/bin/jifty b/examples/Chat/bin/jifty
deleted file mode 100755
index 821cc7d..0000000
--- a/examples/Chat/bin/jifty
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/env perl
-use warnings;
-use strict;
-use File::Basename qw(dirname); 
-use UNIVERSAL::require;
-
-BEGIN {
-    Jifty::Util->require or die $UNIVERSAL::require::ERROR;
-    my $root = Jifty::Util->app_root;
-    unshift @INC, "$root/lib" if ($root);
-}
-
-use Jifty::Script;
-$SIG{INT} = $SIG{TERM} = sub { warn "Stopped\n"; exit; };
-Jifty::Script->dispatch();
diff --git a/examples/Chat/etc/config.yml b/examples/Chat/etc/config.yml
deleted file mode 100644
index 6a9a7ca..0000000
--- a/examples/Chat/etc/config.yml
+++ /dev/null
@@ -1,37 +0,0 @@
----
-framework:
-  AdminMode: 0
-  ApplicationClass: Chat
-  ApplicationName: Chat
-  PubSub:
-    Enable: 1
-  Database:
-    CheckSchema: 1
-    Database: chat
-    Driver: SQLite
-    Host: localhost
-    Password: ''
-    RecordBaseClass: Jifty::DBI::Record::Cachable
-    User: ''
-    Version: 0.0.1
-  DevelMode: 0
-  L10N:
-    PoDir: share/po
-  LogLevel: DEBUG
-  Mailer: Sendmail
-  MailerArgs: []
-  Plugins: []
-  Web:
-    BaseURL: http://localhost
-    DataDir: var/mason
-    Globals: []
-    MasonConfig:
-      autoflush: 0
-      default_escape_flags: h
-      error_format: text
-      error_mode: fatal
-    Port: 8888
-    ServeStaticFiles: 1
-    StaticRoot: share/web/static
-    TemplateRoot: share/web/templates
-    ServerClass: Jifty::Server::Fork
diff --git a/examples/Chat/lib/Chat/Action/Send.pm b/examples/Chat/lib/Chat/Action/Send.pm
deleted file mode 100644
index d32111b..0000000
--- a/examples/Chat/lib/Chat/Action/Send.pm
+++ /dev/null
@@ -1,18 +0,0 @@
-package Chat::Action::Send;
-use warnings;
-use strict;
-
-use Jifty::Param::Schema;
-use Jifty::Action schema {
-    param message =>
-        label is 'Say something witty:';
-};
-
-sub take_action {
-    my $self = shift;
-    my $msg  = $self->argument_value('message');
-    $msg = "<$1\@".Jifty->web->request->address."> $msg" if Jifty->web->request->user_agent =~ /([^\W\d]+)[\W\d]*$/;
-    Chat::Event::Message->new( { message => $msg } )->publish;
-}
-
-1;
diff --git a/examples/Chat/lib/Chat/Event/Message.pm b/examples/Chat/lib/Chat/Event/Message.pm
deleted file mode 100644
index feef5d6..0000000
--- a/examples/Chat/lib/Chat/Event/Message.pm
+++ /dev/null
@@ -1,6 +0,0 @@
-package Chat::Event::Message;
-use strict;
-use warnings;
-use base 'Chat::Event';
-
-1;
diff --git a/examples/Chat/lib/Chat/View.pm b/examples/Chat/lib/Chat/View.pm
deleted file mode 100644
index b3f18e6..0000000
--- a/examples/Chat/lib/Chat/View.pm
+++ /dev/null
@@ -1,31 +0,0 @@
-use warnings;
-use strict;
-
-package Chat::View;
-use Jifty::View::Declare -base;
-
-template 'index.html' => page { title => "Jifty chat server" } content {
-    Jifty->subs->add(
-        class       => 'Message',
-        mode        => 'Bottom',
-        region      => "message",
-        render_with => '/fragments/message'
-    );
-    render_region( name => "message", path => '/__jifty/empty' );
-    render_region( name => "sender",  path => '/fragments/sender' );
-};
-
-template 'fragments/message' => sub {
-    div { get('event')->data->{'message'} }
-};
-
-
-template 'fragments/sender' => sub {
-    my $action = Jifty->web->new_action( class => 'Send' );
-    form {
-        render_param ($action => 'message', focus => 1);
-        form_submit(onclick => [ { submit => $action }, { refresh_self => 1 } ]);
-    }
-};
-
-1;
diff --git a/examples/Chat/t/00compile.t b/examples/Chat/t/00compile.t
deleted file mode 100644
index f77a3aa..0000000
--- a/examples/Chat/t/00compile.t
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/perl -w
-
-use Test::More;
-
-use File::Find;
-
-my @modules;
-find sub {
-    return unless /\.pm$/;
-    push @modules, $File::Find::name;
-}, "lib";
-
- at modules = map { s[^lib/][];  $_ =~ s[.pm$][];  $_ =~ s[/][::]g; $_ } @modules;
-
-plan tests => scalar @modules;
-
-for my $module (@modules) {
-    require_ok $module;
-}
diff --git a/examples/Chat/t/01startup.t b/examples/Chat/t/01startup.t
deleted file mode 100644
index 5ea755e..0000000
--- a/examples/Chat/t/01startup.t
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/usr/bin/perl -w
-
-use Jifty::Test 'no_plan';
-use Jifty::Test::WWW::Mechanize;
-
-# Startup the server.
-my $server = Jifty::Test->make_server;
-isa_ok($server, 'Jifty::Server');
-
-my $URL = $server->started_ok;
-my $mech = Jifty::Test::WWW::Mechanize->new;
-
-$mech->get_ok("$URL", "got the front page");
diff --git a/examples/Clock/Makefile.PL b/examples/Clock/Makefile.PL
deleted file mode 100644
index a535a5f..0000000
--- a/examples/Clock/Makefile.PL
+++ /dev/null
@@ -1,6 +0,0 @@
-use inc::Module::Install;
-name('Clock');
-version('0.01');
-requires('Jifty' => '0.60912');
-
-WriteAll;
diff --git a/examples/Clock/bin/jifty b/examples/Clock/bin/jifty
deleted file mode 100755
index 821cc7d..0000000
--- a/examples/Clock/bin/jifty
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/env perl
-use warnings;
-use strict;
-use File::Basename qw(dirname); 
-use UNIVERSAL::require;
-
-BEGIN {
-    Jifty::Util->require or die $UNIVERSAL::require::ERROR;
-    my $root = Jifty::Util->app_root;
-    unshift @INC, "$root/lib" if ($root);
-}
-
-use Jifty::Script;
-$SIG{INT} = $SIG{TERM} = sub { warn "Stopped\n"; exit; };
-Jifty::Script->dispatch();
diff --git a/examples/Clock/clockserv.pl b/examples/Clock/clockserv.pl
deleted file mode 100644
index 6a34ab6..0000000
--- a/examples/Clock/clockserv.pl
+++ /dev/null
@@ -1,21 +0,0 @@
-use strict;
-use lib 'lib';
-use Time::HiRes qw( time sleep );
-use Jifty;
-
-BEGIN { Jifty->new };
-
-sub ping {
-    my ($class, $sub) = @_;
-    while (1) {
-        my $new_time = time;
-        warn "Time: $new_time\n";
-        Clock::Event::Tick->new($new_time)->publish;
-        sleep 0.5;
-    }
-    exit;
-}
-
-ping();
-
-1;
diff --git a/examples/Clock/etc/config.yml b/examples/Clock/etc/config.yml
deleted file mode 100644
index fbf1f42..0000000
--- a/examples/Clock/etc/config.yml
+++ /dev/null
@@ -1,37 +0,0 @@
----
-framework:
-  AdminMode: 1
-  ApplicationClass: Clock
-  ApplicationName: Clock
-  PubSub:
-    Enable: TRUE
-  Database:
-    CheckSchema: 1
-    Database: clock
-    Driver: SQLite
-    Host: localhost
-    Password: ''
-    RecordBaseClass: Jifty::DBI::Record::Cachable
-    User: ''
-    Version: 0.0.1
-  DevelMode: 1
-  L10N:
-    PoDir: share/po
-  LogLevel: INFO
-  Mailer: Sendmail
-  MailerArgs: []
-  Plugins: []
-  Web:
-    BaseURL: http://localhost
-    DataDir: var/mason
-    Globals: []
-    MasonConfig:
-      autoflush: 0
-      default_escape_flags: h
-      error_format: text
-      error_mode: fatal
-    Port: 8888
-    ServeStaticFiles: 1
-    StaticRoot: share/web/static
-    TemplateRoot: share/web/templates
-    ServerClass: Jifty::Server::Fork
diff --git a/examples/Clock/lib/Clock/Event/Tick.pm b/examples/Clock/lib/Clock/Event/Tick.pm
deleted file mode 100644
index b511c16..0000000
--- a/examples/Clock/lib/Clock/Event/Tick.pm
+++ /dev/null
@@ -1,15 +0,0 @@
-package Clock::Event::Tick;
-use strict;
-use warnings;
-use base 'Clock::Event';
-
-sub match {
-    my $self    = shift;
-    my $query   = shift;
-    if (my $like = $query->{like}) {
-        return(index($$self, $like) >= 0);
-    }
-    return 1;
-}
-
-1;
diff --git a/examples/Clock/share/web/templates/fragments/time b/examples/Clock/share/web/templates/fragments/time
deleted file mode 100644
index 89114b4..0000000
--- a/examples/Clock/share/web/templates/fragments/time
+++ /dev/null
@@ -1,4 +0,0 @@
-<span><% $$event %></span>
-<%ARGS>
-$event
-</%ARGS>
diff --git a/examples/Clock/share/web/templates/index.html b/examples/Clock/share/web/templates/index.html
deleted file mode 100644
index 82dd4ca..0000000
--- a/examples/Clock/share/web/templates/index.html
+++ /dev/null
@@ -1,36 +0,0 @@
-<&| /_elements/wrapper, title => "Hi", subtitle => "Welcome" &>
-<table>
-<tr><td>
-Full: <% $region->render %>
-</td><td>
-Filtered: <% $region_filtered->render %>
-</td></tr>
-</table>
-</&>
-<%init>
-my $region = Jifty::Web::PageRegion->new(
-    name => "clock-time",
-    path => '/__jifty/empty',
-);
-my $region_filtered = Jifty::Web::PageRegion->new(
-    name => "clock-filtered",
-    path => '/__jifty/empty',
-);
-
-Jifty->subs->add(
-  # window_id   => 'random scope',
-    class       => 'Tick',
-    mode        => 'Replace',
-    region      => "clock-time",
-    render_with => '/fragments/time',
-);
-
-Jifty->subs->add(
-  # window_id   => 'random scope',
-    class       => 'Tick',
-    queries     => [{ like => '9' }],
-    mode        => 'Replace',
-    region      => "clock-filtered",
-    render_with => '/fragments/time',
-);
-</%init>
diff --git a/examples/Doxory/etc/config.yml b/examples/Doxory/etc/config.yml
index a181a15..7f3669e 100644
--- a/examples/Doxory/etc/config.yml
+++ b/examples/Doxory/etc/config.yml
@@ -29,9 +29,6 @@ framework:
     - REST: {}
     - SkeletonApp: {}
 
-  PubSub: 
-    Backend: Memcached
-    Enable: ~
   TemplateClass: Doxory::View
   SkipAccessControl: 1
   Web: 
diff --git a/examples/HelloKitty/etc/config.yml b/examples/HelloKitty/etc/config.yml
index 388f50a..d169271 100644
--- a/examples/HelloKitty/etc/config.yml
+++ b/examples/HelloKitty/etc/config.yml
@@ -21,9 +21,6 @@ framework:
 
   Plugins: []
 
-  PubSub: 
-    Backend: Memcached
-    Enable: ~
   TemplateClass: HelloKitty::View
   Web: 
     BaseURL: http://localhost
diff --git a/examples/MyWeblog/etc/config.yml b/examples/MyWeblog/etc/config.yml
index 554e054..ef224d3 100644
--- a/examples/MyWeblog/etc/config.yml
+++ b/examples/MyWeblog/etc/config.yml
@@ -22,9 +22,6 @@ framework:
   Plugins:
    - Login: {}
 
-  PubSub: 
-    Backend: Memcached
-    Enable: ~
   Web: 
     BaseURL: http://localhost
     DataDir: var/mason
diff --git a/examples/Ping/Makefile.PL b/examples/Ping/Makefile.PL
deleted file mode 100644
index a911573..0000000
--- a/examples/Ping/Makefile.PL
+++ /dev/null
@@ -1,7 +0,0 @@
-use inc::Module::Install;
-name('Ping');
-version('0.01');
-requires('Jifty' => '0.61025');
-requires('Net::Server' => 0);
-
-WriteAll;
diff --git a/examples/Ping/bin/jifty b/examples/Ping/bin/jifty
deleted file mode 100755
index 821cc7d..0000000
--- a/examples/Ping/bin/jifty
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/env perl
-use warnings;
-use strict;
-use File::Basename qw(dirname); 
-use UNIVERSAL::require;
-
-BEGIN {
-    Jifty::Util->require or die $UNIVERSAL::require::ERROR;
-    my $root = Jifty::Util->app_root;
-    unshift @INC, "$root/lib" if ($root);
-}
-
-use Jifty::Script;
-$SIG{INT} = $SIG{TERM} = sub { warn "Stopped\n"; exit; };
-Jifty::Script->dispatch();
diff --git a/examples/Ping/etc/config.yml b/examples/Ping/etc/config.yml
deleted file mode 100644
index a375b24..0000000
--- a/examples/Ping/etc/config.yml
+++ /dev/null
@@ -1,40 +0,0 @@
---- 
-framework: 
-  AdminMode: 1
-  ApplicationClass: Ping
-  ApplicationName: Ping
-  PubSub:
-    Enable: 1
-  Database: 
-    CheckSchema: 1
-    Database: ping
-    Driver: SQLite
-    Host: localhost
-    Password: ''
-    RecordBaseClass: Jifty::DBI::Record::Cachable
-    User: ''
-    Version: 0.0.1
-  DevelMode: 0
-  L10N: 
-    PoDir: share/po
-  LogLevel: WARN
-  Mailer: Sendmail
-  MailerArgs: []
-
-  Plugins: []
-
-  Web: 
-    BaseURL: http://localhost
-    DataDir: var/mason
-    Globals: []
-
-    MasonConfig: 
-      autoflush: 0
-      default_escape_flags: h
-      error_format: text
-      error_mode: fatal
-    Port: 8888
-    ServeStaticFiles: 1
-    StaticRoot: share/web/static
-    TemplateRoot: share/web/templates
-    ServerClass: Jifty::Server::Fork
diff --git a/examples/Ping/lib/Ping/Action/AddPing.pm b/examples/Ping/lib/Ping/Action/AddPing.pm
deleted file mode 100644
index 79fea12..0000000
--- a/examples/Ping/lib/Ping/Action/AddPing.pm
+++ /dev/null
@@ -1,51 +0,0 @@
-package Ping::Action::AddPing;
-use strict;
-use Jifty::Param::Schema;
-use Jifty::Action schema {
-
-param host =>
-    label is 'Hostname',
-    is mandatory;
-
-param only_failure =>
-    type is 'checkbox',
-    label is 'Failure only?',
-    hints is 'Show only failed pings to me.',
-    default is 0;
-
-};
-
-sub take_action {
-    my $self = shift;
-    my $host = $self->argument_value('host');
-    my $only_failure = $self->argument_value('only_failure');
-
-    Jifty->bus->modify(hosts => sub {
-        $_->{$host} ||= do {
-            if (my $pid = fork) {
-                $pid;
-            }
-            else {
-                exec($^X => "-Ilib", "-MPing::PingServer", "-e", "Ping::PingServer->ping('$host')");
-            }
-        }
-    });
-
-    my $id = Jifty->web->session->id;
-
-    Jifty->bus->modify("$id-ping" => sub {
-        my $sid = $_->{$host}; 
-        Jifty->subs->cancel($sid) if $sid;
-        $_->{$host} = Jifty->subs->add(
-            class       => 'Pong',
-            queries     => [{ host => $host }, $only_failure ? { fail => 1 } : ()],
-            mode        => 'Bottom',
-            region      => 'pong',
-            render_with => '/fragments/pong',
-        );
-    });
-
-    $self->result->message( "Added host: $host" );
-}
-
-1;
diff --git a/examples/Ping/lib/Ping/Action/CancelPing.pm b/examples/Ping/lib/Ping/Action/CancelPing.pm
deleted file mode 100644
index d5b3e86..0000000
--- a/examples/Ping/lib/Ping/Action/CancelPing.pm
+++ /dev/null
@@ -1,28 +0,0 @@
-package Ping::Action::CancelPing;
-use strict;
-use Jifty::Param::Schema;
-use Jifty::Action schema {
-
-param host =>
-    label is 'Hostname',
-    is mandatory;
-
-};
-
-sub take_action {
-    my $self = shift;
-    my $host = $self->argument_value('host');
-
-    my $id  = Jifty->web->session->id;
-    my $sid = Jifty->bus->modify("$id-ping" => sub {
-        delete($_->{$host});
-    });
-    Jifty->bus->modify("hosts" => sub {
-        kill 2, delete $_->{$host};
-    });
-    Jifty->subs->cancel($sid);
-
-    $self->result->message( "Cancelled host: $host" );
-}
-
-1;
diff --git a/examples/Ping/lib/Ping/Event/Pong.pm b/examples/Ping/lib/Ping/Event/Pong.pm
deleted file mode 100644
index 0190c26..0000000
--- a/examples/Ping/lib/Ping/Event/Pong.pm
+++ /dev/null
@@ -1,25 +0,0 @@
-package Ping::Event::Pong;
-use strict;
-use warnings;
-use base 'Ping::Event';
-
-sub match {
-    my $self    = shift;
-    my $query   = shift;
-
-    if ($query->{fail}) {
-        not $$self->{alive};
-    }
-    elsif (my $host = $query->{host}) {
-        $$self->{host} eq $host;
-    }
-    else {
-        1;
-    }
-}
-
-sub render_arguments {
-    %{$_[0]->data};
-}
-
-1;
diff --git a/examples/Ping/lib/Ping/PingServer.pm b/examples/Ping/lib/Ping/PingServer.pm
deleted file mode 100644
index e2ea061..0000000
--- a/examples/Ping/lib/Ping/PingServer.pm
+++ /dev/null
@@ -1,25 +0,0 @@
-package Ping::PingServer;
-
-use Net::Ping;
-use Time::HiRes qw( time sleep );
-use Jifty;
-
-BEGIN { Jifty->new };
-
-sub ping {
-    my ($class, $host) = @_;
-    my $ping = Net::Ping->new(tcp => 1);
-    while (1) {
-        my $old_time = time;
-        my $alive = $ping->ping($host);
-        my $new_time = time;
-
-        Ping::Event::Pong->new(
-            { host => $host, alive => ($alive ? ($new_time - $old_time + 0.001) : 0), time => $new_time }
-        )->publish;
-        sleep 1;
-    }
-    exit;
-}
-
-1;
diff --git a/examples/Ping/share/web/templates/fragments/pong b/examples/Ping/share/web/templates/fragments/pong
deleted file mode 100644
index 6f6e5d6..0000000
--- a/examples/Ping/share/web/templates/fragments/pong
+++ /dev/null
@@ -1,23 +0,0 @@
-<%init>
-my $res = Jifty::Result->new;
-my $tm  = scalar localtime($time);
-if ($alive) {
-    $res->message( "Pong: $host ($tm)" ); # - $alive ($tm)" );
-}
-else {
-    $res->error( "Fail: $host ($tm)" ); # ($tm)" );
-}
-Jifty->web->response->{results} = {};
-Jifty->web->response->result("~$tm~$host" => $res);
-print  Jifty->web->render_messages;
-Jifty->web->response->{results} = {};
-</%init>
-<script>
-var objDiv = document.getElementById('pushed');
-objDiv.scrollTop = objDiv.scrollHeight;
-</script>
-<%args>
-$time
-$host
-$alive
-</%args>
diff --git a/examples/Ping/share/web/templates/index.html b/examples/Ping/share/web/templates/index.html
deleted file mode 100644
index e708f84..0000000
--- a/examples/Ping/share/web/templates/index.html
+++ /dev/null
@@ -1,49 +0,0 @@
-<&|/_elements/wrapper, title => 'Ping for ' . Jifty->web->session->id &>
-
-<div id="pushed" style="overflow: scroll; width: 100%; height: 250px" >
-        <% $region->render %>
-</div>
-
-<table width="80%"><tr valign="top"><td>
-<fieldset>
-<legend>New Pings</legend>
-% my $form = Jifty->web->form;
-<% $form->start %>
-<% $action->form_field('host') %>
-<% $action->form_field('only_failure')%>
-<% $form->submit( label => 'Start' )%>
-<% $form->end %>
-</fieldset>
-% my $id = Jifty->web->session->id;
-% my $pings = Jifty->bus->modify("$id-ping") || {};
-% if (my @subs = keys %$pings) {
-</td><td>
-<fieldset>
-<legend>Current Pings</legend>
-<table width="100%">
-% foreach my $sub (@subs) {
-% $form = Jifty->web->form;
-<% $form->start %>
-%    my $del = Jifty->web->new_action(class => 'CancelPing', arguments => { host => $sub });
-<tr><td>
-<% $del->form_field('host', render_as => 'Hidden', default_value => $sub) %>
-<% $sub %>
-</td><td>
-<% $form->submit( label => 'Stop' )%>
-<% $form->end %>
-</td></tr>
-% }
-</table>
-</fieldset>
-% }
-</td></tr></table>
-</&>
-
-<%init>
-my $action = Jifty->web->new_action(class => 'AddPing');
-my $region = Jifty::Web::PageRegion->new(
-    name => 'pong',
-    path => '/__jifty/empty',
-);
-
-</%init>
diff --git a/examples/Ping/t/00compile.t b/examples/Ping/t/00compile.t
deleted file mode 100644
index 9241224..0000000
--- a/examples/Ping/t/00compile.t
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/usr/bin/perl -w
-
-use Test::More;
-
-use File::Find;
-
-my @modules;
-find sub {
-    return unless /\.pm$/;
-    push @modules, $File::Find::name;
-}, "lib";
-
- at modules = map { s[^lib/][];  $_ =~ s[.pm$][];  $_ =~ s[/][::]g; $_ } @modules;
-
-plan tests => scalar @modules;
-
-# Ping::PingServer will not compile without a schema.
-system "bin/jifty schema --setup";
-
-for my $module (@modules) {
-    require_ok $module;
-}
diff --git a/examples/Ping/t/01startup.t b/examples/Ping/t/01startup.t
deleted file mode 100644
index 64fc9ec..0000000
--- a/examples/Ping/t/01startup.t
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/usr/bin/perl -w
-
-use Jifty::Test 'no_plan';
-use Jifty::Test::WWW::Mechanize;
-
-# Startup the ping server.
-my $server = Jifty::Test->make_server;
-isa_ok($server, 'Jifty::Server');
-
-my $URL = $server->started_ok;
-my $mech = Jifty::Test::WWW::Mechanize->new;
-
-$mech->get_ok("$URL", "got the front page");
diff --git a/examples/ShrinkURL/etc/config.yml b/examples/ShrinkURL/etc/config.yml
index 85522a0..e56d31a 100644
--- a/examples/ShrinkURL/etc/config.yml
+++ b/examples/ShrinkURL/etc/config.yml
@@ -32,9 +32,6 @@ framework:
     - REST: {}
     - SkeletonApp: {}
 
-  PubSub: 
-    Backend: Memcached
-    Enable: ~
   SkipAccessControl: 0
   TemplateClass: ShrinkURL::View
   Web: 
diff --git a/examples/Yada/etc/config.yml b/examples/Yada/etc/config.yml
index 1674196..ed866fc 100644
--- a/examples/Yada/etc/config.yml
+++ b/examples/Yada/etc/config.yml
@@ -37,9 +37,6 @@ framework:
     - SkeletonApp: {}
     - User: {}
 
-  PubSub: 
-    Backend: Memcached
-    Enable: ~
   TemplateClass: Yada::View
   ClientTemplate: 1
   Web: 
diff --git a/lib/Jifty.pm b/lib/Jifty.pm
index 0e91f97..835493f 100644
--- a/lib/Jifty.pm
+++ b/lib/Jifty.pm
@@ -2,7 +2,6 @@ use warnings;
 use strict;
 
 package Jifty;
-use IPC::PubSub 0.22;
 use Data::UUID;
 use encoding 'utf8';
 use Class::Trigger;
@@ -42,12 +41,6 @@ Jifty - an application framework
  # Configure information related to your application's actions
  my $api      = Jifty->api;
 
- # Make parts of your page "subscribe" to information in a fragment
- my $subs     = Jifty->subs;
-
- # Share information via IPC::PubSub in your application
- my $bus      = Jifty->bus;
-
  # Retrieve general information about Mason
  my $handler  = Jifty->handler;
 
@@ -102,7 +95,7 @@ probably a better place to start.
 use base qw/Jifty::Object/;
 use Jifty::Everything;
 
-use vars qw/$HANDLE $CONFIG $LOGGER $HANDLER $API $CLASS_LOADER $PUB_SUB $WEB @PLUGINS/;
+use vars qw/$HANDLE $CONFIG $LOGGER $HANDLER $API $CLASS_LOADER $WEB @PLUGINS/;
 
 =head1 METHODS
 
@@ -372,52 +365,6 @@ sub web {
     return $Jifty::WEB ||= Jifty::Web->new();
 }
 
-=head2 subs
-
-An accessor for the L<Jifty::Subs> object that the subscription uses. 
-
-=cut
-
-sub subs {
-    return Jifty::Subs->new;
-}
-
-=head2 bus
-
-Returns an IPC::PubSub object for the current application.
-
-=cut
-
-sub bus {
-    my $class = shift;
-    my %args = ( connect => 1, @_ );
-    if (not $PUB_SUB and $args{connect}) {
-        my @args;
-
-        my $backend = Jifty->config->framework('PubSub')->{'Backend'};
-        if ( $backend eq 'Memcached' ) {
-            require IO::Socket::INET;
-
-            # If there's a running memcached on the default port. this should become configurable
-            if ( IO::Socket::INET->new('127.0.0.1:11211') ) {
-                @args = ( Jifty->app_instance_id );
-            } else {
-                $backend = 'JiftyDBI';
-            }
-        } 
-        
-        if ($backend eq 'JiftyDBI' and Jifty->handle ) {
-                @args    = (
-                    db_config    => Jifty->handle->{db_config},
-                    table_prefix => '_jifty_pubsub_',
-                );
-            }
-        $PUB_SUB = IPC::PubSub->new( $backend => @args );
-
-    }
-    return $PUB_SUB;
-}
-
 =head2 plugins
 
 Returns a list of L<Jifty::Plugin> objects for this Jifty application.
@@ -567,7 +514,7 @@ sub admin_mode {
 
 =head1 SEE ALSO
 
-L<http://jifty.org>, L<Jifty::Manual::Tutorial>, L<Jifty::Everything>, L<Jifty::Config>, L<Jifty::Handle>, L<Jifty::Logger>, L<Jifty::Handler>, L<Jifty::Web>, L<Jifty::API>, L<Jifty::Subs>, L<IPC::PubSub>, L<Jifty::Plugin>, L<Jifty::ClassLoader>
+L<http://jifty.org>, L<Jifty::Manual::Tutorial>, L<Jifty::Everything>, L<Jifty::Config>, L<Jifty::Handle>, L<Jifty::Logger>, L<Jifty::Handler>, L<Jifty::Web>, L<Jifty::API>, L<Jifty::Plugin>, L<Jifty::ClassLoader>
 
 =head1 AUTHORS
 
diff --git a/lib/Jifty/Action/Record.pm b/lib/Jifty/Action/Record.pm
index cc5b6a2..d4d2a78 100644
--- a/lib/Jifty/Action/Record.pm
+++ b/lib/Jifty/Action/Record.pm
@@ -569,43 +569,6 @@ sub take_action {
     );
 }
 
-sub _setup_event_before_action {
-    my $self = shift;
-
-    # Setup the information regarding the event for later publishing
-    my $event_info = {};
-    $event_info->{as_hash_before} = $self->record->as_hash;
-    $event_info->{record_id}      = $self->record->id;
-    $event_info->{record_class}   = ref( $self->record );
-    $event_info->{action_class}   = ref($self);
-    $event_info->{action_arguments}
-        = $self->argument_values;    # XXX does this work?
-    $event_info->{current_user_id} = $self->current_user->id || 0;
-    return ($event_info);
-}
-
-sub _setup_event_after_action {
-    my $self       = shift;
-    my $event_info = shift;
-
-    unless ( defined $event_info->{record_id} ) {
-        $event_info->{record_id}    = $self->record->id;
-        $event_info->{record_class} = ref( $self->record );
-        $event_info->{action_class} = ref($self);
-    }
-
-    # Add a few more bits about the result
-    $event_info->{result}        = $self->result;
-    $event_info->{timestamp}     = time();
-    $event_info->{as_hash_after} = $self->record->as_hash;
-
-    # Publish the event
-    my $event_class = $event_info->{'record_class'};
-    $event_class =~ s/::Model::/::Event::Model::/g;
-    Jifty::Util->require($event_class);
-    $event_class->new($event_info)->publish;
-}
-
 =head1 SEE ALSO
 
 L<Jifty::Action>, L<Jifty::Record>, L<Jifty::DBI::Record>,
diff --git a/lib/Jifty/Action/Record/Create.pm b/lib/Jifty/Action/Record/Create.pm
index 6475a54..c049544 100644
--- a/lib/Jifty/Action/Record/Create.pm
+++ b/lib/Jifty/Action/Record/Create.pm
@@ -70,9 +70,6 @@ sub take_action {
     my $self   = shift;
     my $record = $self->record;
 
-    # Build the event to be fired later
-    my $event_info = $self->_setup_event_before_action();
-    
     my %values;
 
     # Iterate through all that are set, except for the virtual ones
@@ -104,9 +101,6 @@ sub take_action {
         $self->report_success if  not $self->result->failure;
     }
 
-    # Publish the event, noting success or failure
-    $self->_setup_event_after_action($event_info);
-
     return ($self->record->id);
 }
 
diff --git a/lib/Jifty/Action/Record/Delete.pm b/lib/Jifty/Action/Record/Delete.pm
index 164a569..acf7224 100644
--- a/lib/Jifty/Action/Record/Delete.pm
+++ b/lib/Jifty/Action/Record/Delete.pm
@@ -53,9 +53,6 @@ delete the row from the database.
 sub take_action {
     my $self = shift;
 
-    # Setup the event info for later publishing
-    my $event_info = $self->_setup_event_before_action();
-
     # Delete the record and return an error if delete fails
     my ( $val, $msg ) = $self->record->delete;
     $self->result->error($msg || _('Permission denied')) if not $val;
@@ -63,9 +60,6 @@ sub take_action {
     # Otherwise, we seem to have succeeded, report that
     $self->report_success if not $self->result->failure;
 
-    # Publish the event
-    $self->_setup_event_after_action($event_info);
-
     return 1;
 }
 
diff --git a/lib/Jifty/Action/Record/Update.pm b/lib/Jifty/Action/Record/Update.pm
index 9d9e3ec..6ac9dd8 100644
--- a/lib/Jifty/Action/Record/Update.pm
+++ b/lib/Jifty/Action/Record/Update.pm
@@ -96,9 +96,6 @@ sub take_action {
     my $self = shift;
     my $changed = 0;
 
-    # Prepare the event for later publishing
-    my $event_info = $self->_setup_event_before_action();
-
     my $detailed_messages = {};
 
     $self->record->call_trigger('start_update_action');
@@ -201,9 +198,6 @@ sub take_action {
 
     $self->record->call_trigger('end_update_action');
 
-    # Publish the update event
-    $self->_setup_event_after_action($event_info);
-
     return 1;
 }
 
diff --git a/lib/Jifty/ClassLoader.pm b/lib/Jifty/ClassLoader.pm
index ec8475b..418f9e9 100644
--- a/lib/Jifty/ClassLoader.pm
+++ b/lib/Jifty/ClassLoader.pm
@@ -103,18 +103,6 @@ An empty class that descends from L<Jifty::CurrentUser>.
 
 An empty class that descends from L<Jifty::Dispatcher>.
 
-=item I<Application>::Event
-
-An empty class that descends from L<Jifty::Event> is created.
-
-=item I<Application>::Event::Model
-
-An empty class that descents from L<Jifty::Event::Model> is created.
-
-=item I<Application>::Event::Model::I<Something>
-
-If I<Application>::Model::I<Something> is a valid model class, then it creates an empty descendant of I<Application>::Event::Model with the C<record_class> set to I<Application>::Model::I<Something>.
-
 =item I<Application>::Handle
 
 An empty class that descends from L<Jifty::Handle> is created.
@@ -178,7 +166,7 @@ sub Jifty::ClassLoader::INC {
     # Handle most of the standard App::Class ISA Jifty::Class
     elsif ( $module =~ /^(?:$base)::(Record|Collection|Notification|
                                       Dispatcher|Bootstrap|Upgrade|CurrentUser|
-                                      Handle|Event|Event::Model|
+                                      Handle|
                                       Action::Record::\w+)$/x ) {
         $AUTOGENERATED{$module} = 1;
         return $self->return_class(
@@ -214,24 +202,6 @@ sub Jifty::ClassLoader::INC {
             );
     } 
     
-    # Autogenerate the the event class for model changes
-    elsif ( $module =~ /^(?:$base)::Event::Model::([^\.]+)$/ ) {
-        
-        # Determine the model class and load it
-        my $modelclass = $base . "::Model::" . $1;
-        Jifty::Util->require($modelclass);
-
-        # Don't generate an event unless it really is a model
-        return undef unless eval { $modelclass->isa('Jifty::Record') };
-
-        $AUTOGENERATED{$module} = 1;
-        return $self->return_class(
-                  "package $module;\n"
-                . "use base qw/${base}::Event::Model/;\n"
-                . "sub record_class { '$modelclass' };\n"
-            );
-    } 
-    
     # Autogenerate the record actions for a model
     elsif ( $module =~ /^(?:$base)::Action::
                         (Create|Update|Delete|Search|Execute)([^\.]+)$/x ) {
@@ -364,11 +334,11 @@ sub require {
     Jifty::Util->require($base);
     Jifty::Util->require($base."::CurrentUser");
 
-    # Use Module::Pluggable to help locate our models, actions, notifications,
-    # and events
+    # Use Module::Pluggable to help locate our models, actions, and
+    # notifications
     Jifty::Module::Pluggable->import(
         # $base goes last so we pull in the view class AFTER the model classes
-        search_path => [map { $base . "::" . $_ } ('Model', 'Action', 'Notification', 'Event')],
+        search_path => [map { $base . "::" . $_ } ('Model', 'Action', 'Notification')],
         require => 0,
         except  => qr/\.#/,
         inner   => 0
@@ -382,7 +352,7 @@ sub require {
     }
     $self->models(sort keys %models);
 
-    # Load all those models and model-related actions, notifications, and events
+    # Load all those models and model-related actions, and notifications
     for my $full ($self->models) {
         $self->_require_model_related_classes($full);
     }
diff --git a/lib/Jifty/Config.pm b/lib/Jifty/Config.pm
index 37ccf95..2bb95c6 100644
--- a/lib/Jifty/Config.pm
+++ b/lib/Jifty/Config.pm
@@ -517,10 +517,6 @@ sub guess {
             ApplicationName   => $app_name,
             ApplicationUUID   => $app_uuid,
             LogLevel          => 'INFO',
-            PubSub            => {
-                Enable  => undef,
-                Backend => 'Memcached',
-            },
             Database => {
                 AutoUpgrade     => 1,
                 Database        => $db_name,
diff --git a/lib/Jifty/Event.pm b/lib/Jifty/Event.pm
deleted file mode 100644
index 3d2282e..0000000
--- a/lib/Jifty/Event.pm
+++ /dev/null
@@ -1,142 +0,0 @@
-use warnings;
-use strict;
-
-package Jifty::Event;
-
-use Jifty::YAML;
-use Digest::MD5 qw(md5_hex);
-use vars qw/%PUBLISHER/;
-
-=head1 NAME
-
-Jifty::Event - Event objects for publish/subscribe communication
-
-=head1 DESCRIPTION
-
-An event object from the Jifty::PubSub stream.
-
-=head1 METHODS
-
-=head2 new($payload)
-
-Constructor.  Takes any kind of payload and blesses a scalar reference to it
-into an Event object.
-
-=cut
-
-sub new {
-    my $class   = shift;
-    my $payload = shift;
-    bless \$payload, $class;
-}
-
-=head2 publish()
-
-Inserts the event into the pubsub stream.  If Jifty is configured into
-synchronous republishing, then this method runs a C<republish> on itself
-with all current subscriptions implicitly.  If not, it's simply inserted
-into its main channel for asynchronous republishing later.  
-
-=cut
-
-sub publish {
-    my $self  = shift;
-    my $class = ref($self) || $self;
-
-    return undef unless (Jifty->config->framework('PubSub')->{'Enable'});
-
-    # Always publish to the main stream (needed for async & debugging)
-    # if ($ASYNC || $DEBUGGING) {
-    #    ($PUBLISHER{$class} ||= Jifty->bus->new_publisher($class))->msg($$self);
-    #    return;
-    # }
-
-    # Synchronized auto-republishing
-    # TODO - Prioritize current-user subscriptions first?
-    my $subscriptions = Jifty->bus->modify("$class-subscriptions") || {};
-    while (my ($channel, $queries) = each %$subscriptions) {
-        if ($self->filter(@$queries)) {
-            ($PUBLISHER{$channel} ||= Jifty->bus->new_publisher($channel))->msg($$self);
-        }
-    }
-}
-
-=head2 filter(@query)
-
-Takes multiple class-specific queries, which are evaluated in order by calling L</match>.
-
-=cut
-
-sub filter {
-    my $self = shift;
-    $self->match($_) or return 0 for @_;
-    return 1;
-}
-
-=head2 republish(@query)
-
-Run C<filter> with the queries; if they all succeed, the event is republished
-into that query-specific channel.
-
-=cut
-
-sub republish {
-    my $self = shift;
-    $self->filter(@_) or return;
-
-    my $channel = $self->encode_queries(@_);
-    ($PUBLISHER{$channel} ||= Jifty->bus->new_publisher($channel))->msg($$self);
-}
-
-
-=head2 encode_queries(@query)
-
-Encode queries into some sort of canonical MD5 encoding.
-
-=cut
-
-sub encode_queries {
-    my $self    = shift;
-    my $class   = ref($self) || $self;
-    return $class unless @_;
-
-    return $class . '-' . md5_hex(join('', sort map { Jifty::YAML::Dump($_) } @_));
-}
-
-
-=head2 match($query)
-
-Takes a class-specific query and returns whether it matches.
-
-You almost always want to override this; the default implementation
-simply always return true;
-
-=cut
-
-sub match {
-    1;
-}
-
-=head2 render_arguments()
-
-A list of additional things to push into the C<%ARGS> of the region that
-is about to render this event; see L<Jifty::Subs::Render> for more information.
-
-=cut
-
-sub render_arguments {
-    ();
-}
-
-=head2 data()
-
-This event's payload as a scalar value.
-
-=cut
-
-sub data {
-    ${$_[0]}
-}
-
-
-1;
diff --git a/lib/Jifty/Event/Log.pm b/lib/Jifty/Event/Log.pm
deleted file mode 100644
index 0bbe053..0000000
--- a/lib/Jifty/Event/Log.pm
+++ /dev/null
@@ -1,45 +0,0 @@
-package Jifty::Event::Log;
-use strict;
-use warnings;
-use base qw/Jifty::Event/;
-
-=head1 NAME
-
-Jifty::Event::Log - An event that L<Jifty::Logger::EventAppender> creates
-
-=head1 DESCRIPTION
-
-This L<Jifty::Event> is created when a log message happens.
-
-=head1 METHODS
-
-=head2 match QUERY
-
-Matches only if all of the keys in the query exist in the data, and
-the values of the keys match the respective values in the data.
-
-=cut
-
-sub match {
-    my $self    = shift;
-    my $query   = shift;
-
-    for my $key (keys %{$query}) {
-        return unless defined $self->data->{$key} and $self->data->{$key} eq $query->{$key};
-    }
-
-    return 1;
-}
-
-=head2 render_arguments
-
-All of the data is dumped into the rendered arguments, verbatim.
-
-=cut
-
-sub render_arguments {
-    my $self = shift;
-    return ( %{ $self->data } );
-}
-
-1;
diff --git a/lib/Jifty/Event/Model.pm b/lib/Jifty/Event/Model.pm
deleted file mode 100644
index eca797d..0000000
--- a/lib/Jifty/Event/Model.pm
+++ /dev/null
@@ -1,52 +0,0 @@
-package Jifty::Event::Model;
-
-use warnings;
-use strict;
-use Carp;
-use base qw/Jifty::Event/;
-
-
-
-=head1 NAME
-
-Jifty::Event::Model - Events representing changes to records
-
-=head1 DESCRIPTION
-
-Objects in this class represent changes to Jifty::Record classes (any action on a model class)
-as Jifty::Events.
-
-As yet, this functionality is unused.
-
-
-=cut
-
-=head2 new
-
-creates a new L<Jifty::Event::Model> object.  If C<PubSub> is enabled for your application, 
-checks to make sure that this event has the following (under-documented) parameters:
-
- record_id record_class action_class action_arguments timestamp result as_hash_before as_hash_after current_user_id
-
-=cut
-
-
-sub new {
-    my $class = shift;
-    my $self = $class->SUPER::new(@_);
-    $self->_check() if (Jifty->config->framework('PubSub')->{'Enable'});
-    return $self;
-}
-
-
-sub _check {
-    my $self = shift;
-    for (qw(record_id record_class action_class
-        action_arguments timestamp result as_hash_before
-        as_hash_after current_user_id)) {
-        Carp::confess("$self missing required parameter $_ ")
-            unless ( defined $$self->{$_} );
-        };
-}
-
-1;
diff --git a/lib/Jifty/Everything.pm b/lib/Jifty/Everything.pm
index c3219f7..e7ae483 100644
--- a/lib/Jifty/Everything.pm
+++ b/lib/Jifty/Everything.pm
@@ -80,9 +80,6 @@ use Jifty::Web::Form::Link ();
 use Jifty::Web::Form::Field ();
 use Jifty::Web::Menu ();
 
-use Jifty::Subs ();
-use Jifty::Subs::Render ();
-
 use Jifty::CAS ();
 
 use Jifty::Module::Pluggable;
diff --git a/lib/Jifty/Logger/EventAppender.pm b/lib/Jifty/Logger/EventAppender.pm
deleted file mode 100644
index caddf41..0000000
--- a/lib/Jifty/Logger/EventAppender.pm
+++ /dev/null
@@ -1,67 +0,0 @@
-package Jifty::Logger::EventAppender;
-use strict;
-use warnings;
-use base qw/Log::Log4perl::Appender/;
-
-# We need to pull these in explicitly because this appender class
-# could be used from programs which aren't Jifty
-use Jifty::Util;
-use Jifty;
-BEGIN {Jifty->new}
-
-=head1 NAME
-
-Jifty::Logger::EventAppender - Create Jifty events from log directives
-
-=head1 SYNOPSIS
-
-In a log4perl config file:
-
-    log4perl.appender.Event=Jifty::Logger::EventAppender
-    log4perl.appender.Event.class=YourApp::Event::Log
-    log4perl.appender.Event.arbitraryData=42
-    log4perl.appender.Event.layout=SimpleLayout
-
-=head1 DESCRIPTION
-
-This class is a L<Log::Log4perl>-compatible appender which creates
-L<Jifty::Event::Log> objects when a logging instruction is received.
-
-=head1 METHODS
-
-=head2 new PARAMHASH
-
-The C<class> configuration parameter controls the class of the event
-to create.  It defaults to L<Jifty::Event::Log>.  All other parameters
-are passed through to the event when it is created.
-
-=cut
-
-sub new {
-    my $class = shift;
-    my %params = (
-        class => "Jifty::Event::Log",
-        @_,
-    );
-
-    my $event_class = delete $params{class};
-    Jifty::Util->require($event_class) or die "Can't find event class $event_class";
-
-    return bless {params => \%params, class => $event_class}, $class;
-}
-
-=head2 log PARAMHASH
-
-Creates an instance of the event with all of the configuration
-parameters set in the log4perl config file, as well as all of the
-contents of the C<PARAMHASH> -- see L<Log::Log4perl::Appender> for
-details of the arguments therein.
-
-=cut
-
-sub log {
-    my $self = shift;
-    $self->{class}->new( { %{$self->{params}}, @_ } )->publish;
-}
-
-1;
diff --git a/lib/Jifty/Plugin/ViewDeclarePage/Page.pm b/lib/Jifty/Plugin/ViewDeclarePage/Page.pm
index eb2c83b..e051af1 100644
--- a/lib/Jifty/Plugin/ViewDeclarePage/Page.pm
+++ b/lib/Jifty/Plugin/ViewDeclarePage/Page.pm
@@ -568,7 +568,7 @@ sub render_salutation {
 
 =head3 render_jifty_page_detritus
 
-Renders admin mode warning, the wait message, the keybindings and PubSub javascript.
+Renders admin mode warning, the wait message, and the keybindings javascript.
 Called from L</render_page>.
 
 =cut
@@ -590,12 +590,6 @@ sub render_jifty_page_detritus {
         div { _('Loading...') };
 
     div { id is "keybindings" };
-
-    # This is required for jifty server push
-    if ( Jifty->config->framework('PubSub')->{'Enable'} && Jifty::Subs->list )
-    {
-        script { outs_raw('new Jifty.Subs({}).start();') };
-    }
 }
 
 1;
diff --git a/lib/Jifty/Schema.pm b/lib/Jifty/Schema.pm
index fb23237..aad1ccf 100644
--- a/lib/Jifty/Schema.pm
+++ b/lib/Jifty/Schema.pm
@@ -57,8 +57,6 @@ Returns a list of Models available to your application.  This includes
 your Models, Collections and those that come from core Jifty and
 plugins.
 
-Unfortunately, this list does not contain any of the PubSub Models
-
 =cut
 
 sub _init_model_list {
diff --git a/lib/Jifty/Script/Schema.pm b/lib/Jifty/Script/Schema.pm
index d3971e0..684de60 100755
--- a/lib/Jifty/Script/Schema.pm
+++ b/lib/Jifty/Script/Schema.pm
@@ -306,14 +306,6 @@ sub create_all_tables {
     # Commit it all
     Jifty->handle->commit or exit 1;
 
-    Jifty::Util->require('IPC::PubSub');
-    IPC::PubSub->new(
-        JiftyDBI => (
-            db_config    => Jifty->handle->{db_config},
-            table_prefix => '_jifty_pubsub_',
-            db_init      => 1,
-        )
-    )->disconnect;
     $log->info("Set up version $appv, jifty version $jiftyv");
 }
 
diff --git a/lib/Jifty/Subs.pm b/lib/Jifty/Subs.pm
deleted file mode 100644
index b2c5e2e..0000000
--- a/lib/Jifty/Subs.pm
+++ /dev/null
@@ -1,237 +0,0 @@
-use warnings;
-use strict;
-
-package Jifty::Subs;
-
-use base qw/Jifty::Object/;
-
-use constant new => __PACKAGE__;
-
-=head1 NAME
-
-Jifty::Subs - Configure subscriptions for the current window or session
-
-=head1 SYNOPSIS
-
- my $sid = Jifty->subs->add(
-    class       => 'Tick',
-    queries     => [{ like => '9' }],
-    mode        => 'Replace',
-    region      => "clock-time",
-    render_with => '/fragments/time',
- );
- Jifty->subs->cancel($sid);
-
- my @sids = Jifty->subs->list;
-
-=head1 DESCRIPTION
-
-
-
-=head1 METHODS
-
-=head2 add PARAMHASH
-
-Add a subscription for the current window or session.
-
-Takes the following parameters
-
-=over
-
-=item class
-
-What class of object shall we subscribe to notifications on
-
-=item queries
-
-An array of queries to match items of class C<class> against. The implementation of C<queries> is dependent on the type of object events are being recorded against
-
-=item mode
-
-How should the fragment sent to the client on matching events be rendered. Valid modes are C<Replace>, C<Bottom> and C<Top>
-
-=item region
-
-The moniker of the region that updates to this subscription should be rendered into
-
-=item render_with
-
-The path of the fragment used to render items matching this subscription
-
-=item effect
-
-The effect to use when showing the region, if any.
-
-=item effect_args
-
-Arguments to the effect
-
-=item remove_effect
-
-The effect to use when removing the old value of the region, if any.
-
-=item remove_effect_args
-
-Arguments to the remove effect
-
-=item coalesce
-
-If multiple events would cause the update of the given region with the
-same C<render_with> path, merge them and only render the region once,
-with the latest update.
-
-=back
-
-=cut
-
-sub add {
-    my $class = shift;
-    my $args = {@_};
-    unless (Jifty->config->framework('PubSub')->{'Enable'}) {
-        $class->log->error("PubSub disabled, but $class->add called");
-        return undef;
-    }
-
-    $args->{coalesce} = 1 if not exists $args->{coalesce} and $args->{mode} eq "Replace";
-
-    my $id          = ($args->{window_id} || Jifty->web->session->id);
-    my $event_class = $args->{class};
-    $event_class = Jifty->app_class("Event", $args->{class}) unless $event_class =~ /^Jifty::Event::/;
-
-    my $queries = $args->{queries} || [];
-    my $region  = $args->{region};
-    my $channel = $event_class->encode_queries(@$queries);
-    $args->{attrs}{$_} = delete $args->{$_}
-        for grep {exists $args->{$_}} qw/effect effect_args remove_effect remove_effect_args/;
-
-    # The ->modify here is calling into the callback sub{...} with
-    # the previous value of $_, that is a hashref of channels to
-    # queries associated with those channels.  The callback then
-    # massages it to add a new channel/queries mapping; the value
-    # of $_ at the end of the callback is then atomically updated
-    # into the message bus under the same key.
-    Jifty->bus->modify(
-        "$event_class-subscriptions" => sub {
-            $_->{$channel} = $queries;
-        }
-    );
-
-    # The per-window/session ($id) rendering information ("$id-render")
-    # contains a hash from subscribed channels to rendering information,
-    # including the frament, region, argument and ajax updating mode.
-    Jifty->bus->modify(
-        "$id-render" => sub {
-            $_->{$channel}{$region} = {
-                map { $_ => $args->{$_} }
-                    qw/render_with region arguments mode coalesce attrs/
-            };
-        }
-    );
-
-    # We create/update a IPC::PubSub::Subscriber object for this $id,
-    # and have it subscribe to the channel that we're adding here.
-    Jifty->bus->modify(
-        "$id-subscriber" => sub {
-            if   ($_) { $_->subscribe($channel) }
-            else      { $_ = Jifty->bus->new_subscriber($channel) }
-        }
-    );
-
-    return "$channel!$id!$region";
-}
-
-=head2 cancel CHANNEL_ID
-
-Cancels session or window's subscription to CHANNEL_ID
-
-=cut
-
-sub cancel {
-    my ($class, $channel_id) = @_;
-
-    unless (Jifty->config->framework('PubSub')->{'Enable'}) {
-        $class->log->error("PubSub disabled, but $class->cancel called");
-        return undef;
-    }
-
-    my ($channel, $id, $region) = split(/!/, $channel_id, 3);
-    my ($event_class)  = split(/-/, $channel);
-
-    $id ||= Jifty->web->session->id;
-
-    my $last;
-    Jifty->bus->modify(
-        "$id-render" => sub {
-            delete $_->{$channel}{$region};
-            $last = 1 unless %{$_->{$channel}};
-        }
-    );
-
-    if ($last) {
-        Jifty->bus->modify(
-            "$event_class-subscriptions" => sub {
-                delete $_->{$channel};
-            }
-        );
-
-        Jifty->bus->modify(
-            "$id-subscriber" => sub {
-                if ($_) { $_->unsubscribe($channel) }
-            }
-        );
-    }
-}
-
-=head2 list [window/sessionid]
-
-Returns a lost of channel ids this session or window is subscribed to.
-
-=cut
-
-
-sub list {
-    my $class = shift;
-
-    unless (Jifty->config->framework('PubSub')->{'Enable'}) {
-        $class->log->error("PubSub disabled, but $class->add called");
-        return undef;
-    }
-
-    my $id   = (shift || Jifty->web->session->id);
-    my $subscribe = Jifty->bus->modify( "$id-subscriber" ) or return ();
-    return $subscribe->channels;
-}
-
-=head2 update_on PARAMHASH
-
-Like L</add>, but provides a sane set of defaults for updating the
-current region, based on inspection of the current region's
-properties.  C<queries> is set to the region's arguments, and C<class>
-is left unspecified.
-
-=cut
-
-sub update_on {
-    my $class = shift;
-
-    my $region = Jifty->web->current_region;
-    unless ($region) {
-        warn "Jifty->subs->update_on called when not in a region";
-        return;
-    }
-
-    my %args = %{ $region->arguments };
-    delete $args{region};
-    delete $args{event};
-
-    $class->add(
-        queries     => [ \%args ],
-        arguments   => \%args,
-        mode        => 'Replace',
-        region      => $region->qualified_name,
-        render_with => $region->path,
-        @_,
-    );
-}
-
-1;
diff --git a/lib/Jifty/Subs/Render.pm b/lib/Jifty/Subs/Render.pm
deleted file mode 100644
index 54d8079..0000000
--- a/lib/Jifty/Subs/Render.pm
+++ /dev/null
@@ -1,122 +0,0 @@
-package Jifty::Subs::Render;
-use strict;
-use warnings;
-
-use base qw/Jifty::Object/;
-
-=head1 NAME
-
-Jifty::Subs::Render - Helper for subscriptions rendering
-
-=head1 SYNOPSIS
-
-  Jifty::Subs::Render->render($id, $callback);
-
-=head1 DESCRIPTION
-
-
-
-=head2 render($id, $callback)
-
-Render all outstanding messages, and call C<$callback> with render
-mode, region name, and content.
-
-=cut
-
-sub render {
-    my ( $class, $id, $callback ) = @_;
-    my $got;
-
-    # # of fragments sent
-    my $sent = 0;
-
-    # Get the IPC::PubSub::Subscriber object and do one fetch of all new
-    # events it subscribes to, and put those into $got.
-    my $subs
-        = Jifty->bus->modify( "$id-subscriber", sub { $got = $_ ? $_->get_all : {} } );
-
-    return 0 unless %$got;
-
-    # Now we the render options for those channels (calling ->modify instead
-    # of ->fetch because we want to block if someone else is touching it;
-    # it's equivalent to ->modify("$id-render", sub { $_ }).
-    my $render = Jifty->bus->modify("$id-render");
-
-    my %coalesce;
-    while ( my ( $channel, $msgs ) = each(%$got) ) {
-        # Channel name is always App::Event::Class-MD5QUERIES
-        my $event_class = $channel;
-        $event_class =~ s/-.*//;
-
-        unless ( UNIVERSAL::can( $event_class => 'new' ) ) {
-            $class->log->error("Receiving unknown event $event_class from the Bus");
-            $event_class = Jifty->app_class("Event");
-        }
-
-        foreach my $rv (@$msgs) {
-
-            # XXX - We don't yet use $timestamp here.
-            my ( $timestamp, $msg ) = @$rv;
-
-            for my $render_info (values %{$render->{$channel}}) {
-                if ($render_info->{coalesce} and $render_info->{mode} eq "Replace") {
-                    my $hash = Digest::MD5::md5_hex( YAML::Dump([$render_info->{region}, $render_info->{render_with}] ) );
-                    $class->log->debug("Coalesced duplicate region @{[$render_info->{region}]} with @{[$render_info->{render_with}]} from $channel event $msg") if exists $coalesce{$hash};
-                    $coalesce{$hash} = [ $timestamp, $event_class, $msg, $render_info ] unless $coalesce{$hash} and $coalesce{$hash}[0] > $timestamp;
-                } else {
-                    $class->log->debug("Rendering $channel event $msg in @{[$render_info->{region}]} with @{[$render_info->{render_with}]}");
-                    render_single( $event_class, $msg, $render_info, $callback );
-                    $sent++;
-                }
-            }
-        }
-    }
-
-    for my $c (values %coalesce) {
-        my (undef, $event_class, $msg, $render_info) = @{$c};
-        $class->log->debug("Rendering @{[$render_info->{region}]} with @{[$render_info->{render_with}]} for $event_class");
-        render_single( $event_class, $msg, $render_info, $callback );
-        $sent++;
-    }
-
-    return ($sent);
-}
-
-=head2 render_single CLASS, MESSAGE, INFO, CALLBACK
-
-Renders a single region, based on the region information in C<INFO>.
-
-=cut
-
-sub render_single {
-    my ($class, $msg, $render_info, $callback) = @_;
-
-    my $region = Jifty::Web::PageRegion->new(
-        name => $render_info->{region},
-        path => $render_info->{render_with},
-    );
-    # So we don't warn about "duplicate region"s
-    delete Jifty->web->{'regions'}{ $region->qualified_name };
-
-    my $event_object   = $class->new($msg);
-    # Region's arguments come from explicit arguments only
-    $region->arguments( $render_info->{arguments} );
-
-    $region->enter;
-    # Also provide an 'event' argument, and fill in the render
-    # arguments.  These don't show up in the region's arguments if
-    # inspected, but do show up in the request.
-    Jifty->handler->buffer->push( private => 1 );
-    $region->render_as_subrequest(
-        { %{$region->arguments}, event => $event_object, $event_object->render_arguments },
-    );
-    $callback->(
-        $render_info->{mode},       
-        $region->qualified_name,
-        Jifty->handler->buffer->pop,
-        $render_info->{attrs},
-    );
-    $region->exit;
-}
-
-1;
diff --git a/lib/Jifty/Test.pm b/lib/Jifty/Test.pm
index 29283f7..4fe97ef 100644
--- a/lib/Jifty/Test.pm
+++ b/lib/Jifty/Test.pm
@@ -688,13 +688,6 @@ sub _ending {
         # Clean up mailbox
         Jifty::Test->teardown_mailbox;
 
-        # Disconnect the PubSub bus, if need be; otherwise we may not
-        # be able to drop the testing database.  Calling ->bus, if we
-        # never dealt with PubSub in the test, can actually _do_ the
-        # connect now, unless we explicitly tell it not to.
-        Jifty->bus->disconnect
-          if Jifty->config and Jifty->bus( connect => 0 );
-
         # Remove testing db
         if (Jifty->handle && !$ENV{JIFTY_FAST_TEST}) {
             Jifty->handle->disconnect();
diff --git a/lib/Jifty/Upgrade/Internal.pm b/lib/Jifty/Upgrade/Internal.pm
index f72a02b..b06a299 100644
--- a/lib/Jifty/Upgrade/Internal.pm
+++ b/lib/Jifty/Upgrade/Internal.pm
@@ -62,4 +62,6 @@ since '0.61210' => sub {
     rename column => 'key', in => 'IPC::PubSub::Cache::JiftyDBI::Stash::Item', to => 'data_key';
 };
 
+# Drop PubSub tables
+
 1;
diff --git a/lib/Jifty/View/Declare/CoreTemplates.pm b/lib/Jifty/View/Declare/CoreTemplates.pm
index 5c923ce..d9b69dc 100644
--- a/lib/Jifty/View/Declare/CoreTemplates.pm
+++ b/lib/Jifty/View/Declare/CoreTemplates.pm
@@ -17,8 +17,6 @@ This library contains templates that Jifty can't function without:
 
 =over
 
-=item PubSub
-
 =item Validate
 
 =item Autocomplete
@@ -35,57 +33,6 @@ This library contains templates that Jifty can't function without:
 
 These templates are still in Masonland. we're doing something wrong with escaping in them
 
-
-template '__jifty/subs' => sub {
-    my ($forever) = get(qw(forever)) || 1;
-
-    Jifty->web->response->content_type("text/html; charset=utf-8");
-    Jifty->web->response->header('Pragma' => 'no-cache');
-    Jifty->web->response->header('Cache-control' => 'no-cache');
-
-    my $writer = XML::Writer->new;
-    $writer->xmlDecl( "UTF-8", "yes" );
-
-    my $begin = <<'END';
-<!DOCTYPE html>
-<html><head><title></title></head>
-END
-    chomp $begin;
-
-    if ($forever) {
-        my $whitespace = " " x ( 1024 - length $begin );
-        $begin =~ s/<body>$/$whitespace/s;
-    }
-
-    Jifty->web->out($begin);
-    $writer->startTag("body");
-
-    while (1) {
-        my $sent = _write_subs_once($writer);
-        flush STDOUT;
-        last if ( $sent && !$forever );
-        sleep 1;
-    }
-    $writer->endTag();
-    return;
-
-};
-
-sub _write_subs_once {
-    my $writer = shift;
-    Jifty::Subs::Render->render(
-        Jifty->web->session->id,
-        sub {
-            my ( $mode, $name, $content ) = @_;
-            $writer->startTag( "pushfrag", mode => $mode );
-            $writer->startTag( "fragment", id   => $name );
-            $writer->dataElement( "content", $content );
-            $writer->endTag();
-            $writer->endTag();
-        }
-    );
-}
-
 template '__jifty/autocomplete.xml' => sub {
 
     # Note: the only point to this file is to set the content_type; the actual
diff --git a/lib/Jifty/View/Declare/Page.pm b/lib/Jifty/View/Declare/Page.pm
index b10ddcf..2af7beb 100644
--- a/lib/Jifty/View/Declare/Page.pm
+++ b/lib/Jifty/View/Declare/Page.pm
@@ -202,7 +202,7 @@ sub render_pre_content_hook {
 
 =head2 render_jifty_page_detritus
 
-Renders the keybinding and PubSub javascript as well as the wait message
+Renders the keybinding javascript as well as the wait message
 
 =cut
 
@@ -211,13 +211,6 @@ sub render_jifty_page_detritus {
     show('/keybindings');
     with( id => "jifty-wait-message", style => "display: none" ),
         div { _('Loading...') };
-
-    # This is required for jifty server push.  If you maintain your own
-    # wrapper, make sure you have this as well.
-    if ( Jifty->config->framework('PubSub')->{'Enable'} && Jifty::Subs->list )
-    {
-        script { outs_raw('jQuery(document).ready(function(){new Jifty.Subs({}).start()});') };
-    }
 }
 
 sub _render_header { 
diff --git a/lib/Jifty/Web.pm b/lib/Jifty/Web.pm
index 9892af7..2defcb3 100644
--- a/lib/Jifty/Web.pm
+++ b/lib/Jifty/Web.pm
@@ -41,7 +41,6 @@ __PACKAGE__->javascript_libs([qw(
     behaviour.js
     jifty.js
     jifty_utils.js
-    jifty_subs.js
     jifty_smoothscroll.js
     calendar.js
     datetime.js
diff --git a/share/web/static/js/jifty_subs.js b/share/web/static/js/jifty_subs.js
deleted file mode 100644
index ca92657..0000000
--- a/share/web/static/js/jifty_subs.js
+++ /dev/null
@@ -1,78 +0,0 @@
-if (typeof Jifty == "undefined") Jifty = { };
-
-(function(){
-
-    /* onPushHandler is called for each new pushed element.
-       (currently, this is always a <pushfrag>).  This routine takes
-       the pushed element and extracts render mode (Before, After,
-       Replace, Delete) , region name and other rendering information.
-       Then it calls jifty's "apply_fragment_updates to the item
-       inside the <pushfrag> (the actual fragment);
-
-        f is the specification for the new fragment. (region, path,
-        mode and other information extracted from the fragment)
-
-       */
-
-    var onPushHandler = function(t) {
-        var rid =  t.firstChild.getAttribute('id');
-        var f = { region: rid, path: '' };
-        f['mode']               =  t.getAttribute('mode');
-        f['effect']             =  t.getAttribute('effect');
-        f['effect_args']        =  t.getAttribute('effect_args');
-        f['remove_effect']      =  t.getAttribute('remove_effect');
-        f['remove_effect_args'] =  t.getAttribute('remove_effect_args');
-
-        // If SinglePlugin is enabled, region name will be prefixed
-        // "__page-" by the time that region was rendered. Therefore
-        // it should also be prefixed the same here.
-        if(Jifty.fragments["__page"] != null) {
-            f['region'] = "__page-" + f['region']
-        }
-
-        f = prepare_element_for_update(f);
-        if (f == null) return;
-        apply_fragment_updates(t.firstChild, f);
-    };
-
-    
-    /* This function constructs a new Jifty.Subs object and sets
-    up a callback with jQuery.ajax to run our onPushHandler each time
-    a new element is added to the hidden iframe's body.
-
-    We could instead say "sets up our transport. every time the
-    transport gets a new item, call onPushHandler" */
-
-    /* Jifty.Subs.start() will connect to the iframe transport */
-
-    Jifty.Subs = function(args) {
-        var window_id = args.window_id; // XXX: not yet
-        var uri = args.uri;
-        if (!uri)
-            uri = "/=/subs?forever=0";
-        
-        this.start = function() {
-            //push.start();
-            var self = this;
-
-            jQuery.ajax({
-                url: uri,
-                type: "get",
-                success: function(responseText) {
-                    var container = document.createElement('div');
-                    container.innerHTML = responseText;
-                    jQuery("pushfrag", container).each(function() {
-                        onPushHandler(this);
-                    });
-
-                    setTimeout(function() {
-                        self.start();
-                    }, 1000)
-                },
-                error: function() {
-                }
-            });
-        }          
-    }
-
-})();
diff --git a/share/web/templates/=/subs b/share/web/templates/=/subs
deleted file mode 100644
index e91a3d5..0000000
--- a/share/web/templates/=/subs
+++ /dev/null
@@ -1,60 +0,0 @@
-<%args>
-$forever => 1
-</%args>
-<%init>
-
-Jifty->web->response->content_type("text/html; charset=utf-8");
-Jifty->web->response->header('Pragma' => 'no-cache');
-Jifty->web->response->header('Cache-control' => 'no-cache');
-Jifty->handler->send_http_header;
-
-my $writer = XML::Writer->new;
-$writer->xmlDecl( "UTF-8", "yes" );
-
-my $begin = <<'END';
-<!DOCTYPE html>
-<html><head><title></title></head>
-END
-chomp $begin;
-
-if ($forever) {
-    my $whitespace = " " x ( 1024 - length $begin );
-    $begin =~ s/<body>$/$whitespace<body>/s;
-}
-
-$m->print($begin);
-$m->flush_buffer;
-Jifty->handler->buffer->flush_output;
-$writer->startTag("body");
-
-local $SIG{PIPE} = sub {
-    die "ABORT";
-};
-
-my $loops;
-while (Jifty->config->framework('PubSub')->{'Enable'}) {
-    Jifty->web->out(" ") if ++$loops % 10 == 0;
-    my $sent = write_subs_once($writer);
-    Jifty->handler->buffer->flush_output;
-    flush STDOUT;
-    last if ( $sent && !$forever );
-    sleep 1;
-}
-$writer->endTag();
-return;
-
-sub write_subs_once {
-    my $writer = shift;
-    Jifty::Subs::Render->render(
-        Jifty->web->session->id,
-        sub {
-            my ( $mode, $name, $content, $attrs ) = @_;
-            $writer->startTag( "pushfrag", mode => $mode, %{$attrs || {}} );
-            $writer->startTag( "fragment", id   => $name );
-            $writer->dataElement( "content", $content );
-            $writer->endTag();
-            $writer->endTag();
-        }
-    );
-}
-</%init>
diff --git a/share/web/templates/_elements/wrapper b/share/web/templates/_elements/wrapper
index 51e5170..1a4fef2 100644
--- a/share/web/templates/_elements/wrapper
+++ b/share/web/templates/_elements/wrapper
@@ -19,9 +19,6 @@
   </div>
   <div id="jifty-wait-message" style="display: none"><%_('Loading...')%></div>
 % Jifty::View->call_trigger('body_end');
-% if ( Jifty->config->framework('PubSub')->{'Enable'} && Jifty::Subs->list ) {
-<script>new Jifty.Subs({}).start();</script>
-% }
 </body>
 </html>
 <%args>
diff --git a/t/TestApp-Collection-Select/etc/config.yml b/t/TestApp-Collection-Select/etc/config.yml
index 9175d5e..ec3e955 100644
--- a/t/TestApp-Collection-Select/etc/config.yml
+++ b/t/TestApp-Collection-Select/etc/config.yml
@@ -32,9 +32,6 @@ framework:
     - REST: {}
     - SkeletonApp: {}
 
-  PubSub: 
-    Backend: Memcached
-    Enable: ~
   SkipAccessControl: 0
   TemplateClass: TestApp::View
   View: 
diff --git a/t/TestApp-Dispatcher/etc/config.yml b/t/TestApp-Dispatcher/etc/config.yml
index 5d46b62..b6af8a5 100644
--- a/t/TestApp-Dispatcher/etc/config.yml
+++ b/t/TestApp-Dispatcher/etc/config.yml
@@ -25,9 +25,6 @@ framework:
     - CompressedCSSandJS: {}
     - ErrorTemplates: {}
     - SkeletonApp: {}
-  PubSub: 
-    Backend: Memcached
-    Enable: ~
   SkipAccessControl: 0
   TemplateClass: TestApp::Dispatcher::View
   View: 
diff --git a/t/TestApp-JiftyJS/etc/config.yml b/t/TestApp-JiftyJS/etc/config.yml
index 6ef467b..aec903a 100644
--- a/t/TestApp-JiftyJS/etc/config.yml
+++ b/t/TestApp-JiftyJS/etc/config.yml
@@ -33,9 +33,6 @@ framework:
     - REST: {}
     - SkeletonApp: {}
 
-  PubSub: 
-    Backend: Memcached
-    Enable: ~
   SkipAccessControl: 0
   TemplateClass: TestApp::JiftyJS::View
   Web: 
diff --git a/t/TestApp-Mason/etc/config.yml b/t/TestApp-Mason/etc/config.yml
index 34d656f..e9440f9 100644
--- a/t/TestApp-Mason/etc/config.yml
+++ b/t/TestApp-Mason/etc/config.yml
@@ -23,9 +23,6 @@ framework:
   MailerArgs: []
 
   Plugins: []
-  PubSub: 
-    Backend: Memcached
-    Enable: ~
   SkipAccessControl: 0
   TemplateClass: TestApp::Mason::View
   View: 
diff --git a/t/TestApp-Notifications/etc/config.yml b/t/TestApp-Notifications/etc/config.yml
index ee59991..b434190 100644
--- a/t/TestApp-Notifications/etc/config.yml
+++ b/t/TestApp-Notifications/etc/config.yml
@@ -32,9 +32,6 @@ framework:
     - REST: {}
     - SkeletonApp: {}
 
-  PubSub: 
-    Backend: Memcached
-    Enable: ~
   SkipAccessControl: 0
   TemplateClass: TestApp::Notifications::View
   View: 
diff --git a/t/TestApp-Plugin-ActorMetadata/etc/config.yml b/t/TestApp-Plugin-ActorMetadata/etc/config.yml
index 70ae7a4..cb88b9d 100644
--- a/t/TestApp-Plugin-ActorMetadata/etc/config.yml
+++ b/t/TestApp-Plugin-ActorMetadata/etc/config.yml
@@ -34,9 +34,6 @@ framework:
     - SkeletonApp: {}
     - User: {}
 
-  PubSub: 
-    Backend: Memcached
-    Enable: ~
   SkipAccessControl: 0
   TemplateClass: TestApp::Plugin::ActorMetadata::View
   View: 
diff --git a/t/TestApp-Plugin-AppPluginHasModels/etc/config.yml b/t/TestApp-Plugin-AppPluginHasModels/etc/config.yml
index 2dfb89b..3cc8a6b 100644
--- a/t/TestApp-Plugin-AppPluginHasModels/etc/config.yml
+++ b/t/TestApp-Plugin-AppPluginHasModels/etc/config.yml
@@ -33,9 +33,6 @@ framework:
     - SkeletonApp: {}
     - TestApp::Plugin::AppPluginHasModels::Plugin::MyAppPlugin: {}
 
-  PubSub: 
-    Backend: Memcached
-    Enable: ~
   SkipAccessControl: 0
   TemplateClass: TestApp::Plugin::AppPluginHasModels::View
   Web: 
diff --git a/t/TestApp-Plugin-CompressedCSSandJS/etc/config.yml b/t/TestApp-Plugin-CompressedCSSandJS/etc/config.yml
index 80c5292..91912e0 100644
--- a/t/TestApp-Plugin-CompressedCSSandJS/etc/config.yml
+++ b/t/TestApp-Plugin-CompressedCSSandJS/etc/config.yml
@@ -33,9 +33,6 @@ framework:
     - SkeletonApp: {}
     - User: {}
 
-  PubSub: 
-    Backend: Memcached
-    Enable: ~
   SkipAccessControl: 0
   TemplateClass: TestApp::Plugin::CompressedCSSandJS::View
   Web: 
diff --git a/t/TestApp-Plugin-News/etc/config.yml b/t/TestApp-Plugin-News/etc/config.yml
index 2412cbc..eb7a429 100644
--- a/t/TestApp-Plugin-News/etc/config.yml
+++ b/t/TestApp-Plugin-News/etc/config.yml
@@ -29,9 +29,6 @@ framework:
     - REST: {}
     - SkeletonApp: {}
 
-  PubSub: 
-    Backend: Memcached
-    Enable: ~
   SkipAccessControl: 0
   TemplateClass: TestApp::Plugin::News::View
   Web: 
diff --git a/t/TestApp-Plugin-OnClick/etc/config.yml b/t/TestApp-Plugin-OnClick/etc/config.yml
index 7fadd1a..23b8cf7 100644
--- a/t/TestApp-Plugin-OnClick/etc/config.yml
+++ b/t/TestApp-Plugin-OnClick/etc/config.yml
@@ -31,9 +31,6 @@ framework:
     - REST: {}
     - SkeletonApp: {}
 
-  PubSub: 
-    Backend: Memcached
-    Enable: ~
   SkipAccessControl: 0
   TemplateClass: TestApp::Plugin::OnClick::View
   Web: 
diff --git a/t/TestApp-Plugin-PasswordAuth/etc/config.yml b/t/TestApp-Plugin-PasswordAuth/etc/config.yml
index a655abb..f71bd2b 100644
--- a/t/TestApp-Plugin-PasswordAuth/etc/config.yml
+++ b/t/TestApp-Plugin-PasswordAuth/etc/config.yml
@@ -26,9 +26,6 @@ framework:
     - CompressedCSSandJS: {}
     - OnlineDocs: {}
     - REST: {}
-  PubSub: 
-    Backend: Memcached
-    Enable: ~
   TemplateClass: TestApp::Plugin::PasswordAuth::View
   Web: 
     BaseURL: http://localhost
diff --git a/t/TestApp-Plugin-SinglePage/etc/config.yml b/t/TestApp-Plugin-SinglePage/etc/config.yml
index 3b4e1f0..8ea8b89 100644
--- a/t/TestApp-Plugin-SinglePage/etc/config.yml
+++ b/t/TestApp-Plugin-SinglePage/etc/config.yml
@@ -34,9 +34,6 @@ framework:
     - SkeletonApp: {}
     - User: {}
 
-  PubSub: 
-    Backend: Memcached
-    Enable: ~
   SkipAccessControl: 0
   TemplateClass: TestApp::Plugin::SinglePage::View
   Web: 
diff --git a/t/TestApp-Regions/etc/config.yml b/t/TestApp-Regions/etc/config.yml
index e188147..36e8dab 100644
--- a/t/TestApp-Regions/etc/config.yml
+++ b/t/TestApp-Regions/etc/config.yml
@@ -32,9 +32,6 @@ framework:
     - REST: {}
     - SkeletonApp: {}
 
-  PubSub: 
-    Backend: Memcached
-    Enable: ~
   SkipAccessControl: 0
   TemplateClass: TestApp::Regions::View
   View: 
diff --git a/t/TestApp-RestartServer/etc/config.yml b/t/TestApp-RestartServer/etc/config.yml
index c8e82fd..ae1ef7a 100644
--- a/t/TestApp-RestartServer/etc/config.yml
+++ b/t/TestApp-RestartServer/etc/config.yml
@@ -23,9 +23,6 @@ framework:
   MailerArgs: []
 
   Plugins: []
-  PubSub: 
-    Backend: Memcached
-    Enable: ~
   SkipAccessControl: 0
   TemplateClass: TestApp::Mason::View
   View: 
diff --git a/t/TestApp-Template-Declare/etc/config.yml b/t/TestApp-Template-Declare/etc/config.yml
index a73eeef..5f0fd60 100644
--- a/t/TestApp-Template-Declare/etc/config.yml
+++ b/t/TestApp-Template-Declare/etc/config.yml
@@ -32,9 +32,6 @@ framework:
     - REST: {}
     - SkeletonApp: {}
 
-  PubSub: 
-    Backend: Memcached
-    Enable: ~
   SkipAccessControl: 0
   TemplateClass: TestApp::View
   View: 
diff --git a/t/TestApp-Uploads/etc/config.yml b/t/TestApp-Uploads/etc/config.yml
index 6c3faa7..e51f068 100644
--- a/t/TestApp-Uploads/etc/config.yml
+++ b/t/TestApp-Uploads/etc/config.yml
@@ -47,9 +47,6 @@ framework:
     - 
       SkeletonApp: {}
 
-  PubSub: 
-    Backend: Memcached
-    Enable: ~
   SkipAccessControl: 0
   TemplateClass: TestApp::Uploads::View
   View: 
diff --git a/t/TestApp/share/web/templates/_elements/wrapper b/t/TestApp/share/web/templates/_elements/wrapper
index e6486fc..51977f4 100644
--- a/t/TestApp/share/web/templates/_elements/wrapper
+++ b/t/TestApp/share/web/templates/_elements/wrapper
@@ -21,9 +21,6 @@
 % Jifty::View::Mason::Halo->render_component_tree() if (Jifty->config->framework('DevelMode') );
 %# This is required for jifty server push.  If you maintain your own
 %# wrapper, make sure you have this as well.
-% if ( Jifty->config->framework('PubSub')->{'Enable'} && Jifty::Subs->list ) {
-<script>new Jifty.Subs({}).start();</script>
-% }
 </body>
 </html>
 % Jifty->handler->stash->{'in_body'} = 0;

commit d742324987bc66b387636a9d6d58bd8e84326608
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Fri May 18 00:15:42 2012 -0400

    Add a minimal Pubsub plugin
    
    This establishes an AnyMQ::AMQP bus, and adds Jifty->bus to refer to it.

diff --git a/lib/Jifty/Plugin/PubSub.pm b/lib/Jifty/Plugin/PubSub.pm
new file mode 100644
index 0000000..c145dce
--- /dev/null
+++ b/lib/Jifty/Plugin/PubSub.pm
@@ -0,0 +1,26 @@
+use strict;
+use warnings;
+
+package Jifty::Plugin::PubSub;
+use base qw/Jifty::Plugin/;
+
+use AnyMQ;
+
+sub init {
+    my $self = shift;
+    my %opt  = @_;
+
+    my $anymq = AnyMQ->new_with_traits(
+        traits => ['AMQP'],
+        host   => 'localhost',
+        port   => 5672,
+        user   => 'guest',
+        pass   => 'guest',
+        vhost  => '/',
+        exchange => 'events',
+        %opt,
+    );
+    *Jifty::bus = sub { $anymq };
+}
+
+1;

commit 0b2db6abbc7a258f30c260b0edad158392cf1f7c
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Fri May 18 00:24:50 2012 -0400

    Add a basic Web::Hippie::Pipe endpoint at /__jifty/_hippie
    
    Using the Jifty->bus AnyMQ object as its base, construct a
    Web::Hippie::Pipe endpoint at /__jifty/_hippie.  This establishes
    bi-directional real-time communication with the client, using wither
    websockets, mxhr (multi-part XMLHttpRequest), or simply polling --
    whichever the browser supports.
    
    This can be used to send messages to the Hippie.Pipe object in the
    browser, by subscribing $listener to topics on new connections (when
    $path is "/new_listener").  Messages recieved from the browser are
    presented as requests to "/message", and disconnects (when the browser
    moves to a new page) are presented as requests to "/error".
    
    For now, simply present a no-op endpoint.

diff --git a/lib/Jifty/Plugin/PubSub.pm b/lib/Jifty/Plugin/PubSub.pm
index c145dce..b09322b 100644
--- a/lib/Jifty/Plugin/PubSub.pm
+++ b/lib/Jifty/Plugin/PubSub.pm
@@ -5,11 +5,22 @@ package Jifty::Plugin::PubSub;
 use base qw/Jifty::Plugin/;
 
 use AnyMQ;
+use Plack::Builder;
+use Web::Hippie::App::JSFiles;
 
 sub init {
     my $self = shift;
     my %opt  = @_;
 
+    Jifty->web->add_javascript(
+        qw!
+              pubsub/DUI.js
+              pubsub/Stream.js
+              pubsub/hippie.js
+              pubsub/hippie.pipe.js
+              pubsub/jquery.ev.js
+          ! );
+
     my $anymq = AnyMQ->new_with_traits(
         traits => ['AMQP'],
         host   => 'localhost',
@@ -21,6 +32,43 @@ sub init {
         %opt,
     );
     *Jifty::bus = sub { $anymq };
+
+    Jifty::View->add_trigger(
+        body_end => sub { $self->body_end }
+    );
+}
+
+sub body_end {
+    my $self = shift;
+    Jifty->web->out( qq|<script type="text/javascript">var hpipe = new Hippie.Pipe(); hpipe.init({path: "/__jifty"})</script>|);
+}
+
+sub psgi_app_static {
+    my $self = shift;
+    my $static_root = $self->static_root;
+    builder {
+        mount '/'          => Plack::App::File->new(root => $static_root)->to_app;
+        mount '/js/pubsub' => Web::Hippie::App::JSFiles->new->to_app;
+    };
+}
+
+sub wrap {
+    my $self = shift;
+    my $app = shift;
+
+    builder {
+        mount '/__jifty/_hippie' => builder {
+            enable "+Web::Hippie";
+            enable "+Web::Hippie::Pipe", bus => Jifty->bus;
+            sub { my $env = shift;
+                  my $listener  = $env->{'hippie.listener'}; # AnyMQ::Queue
+                  my $client_id = $env->{'hippie.client_id'}; # client id
+                  my $path = $env->{PATH_INFO};
+            };
+        };
+
+        mount '/' => $app;
+    };
 }
 
 1;

commit 6df3a524438ad8d2729eb6bfc0c81b16c1e794bf
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Sun Mar 25 05:55:28 2012 -0400

    Accept -s Twiggy, and auto-detect if we should run that rather than Standalone

diff --git a/lib/Jifty/Script/Server.pm b/lib/Jifty/Script/Server.pm
index ef89aa7..95d492c 100755
--- a/lib/Jifty/Script/Server.pm
+++ b/lib/Jifty/Script/Server.pm
@@ -113,6 +113,7 @@ sub options {
         'host=s'     => 'host',
         'u|user=s'   => 'user',
         'g|group=s'  => 'group',
+        's|server=s' => 'server',
     )
 }
 
@@ -205,7 +206,17 @@ sub _run_server {
 
     $args{$_} = $self->{$_} for grep defined $self->{$_}, qw/host user group/;
 
-    $Jifty::SERVER = Plack::Loader->load('Standalone', %args);
+    my $server_class = $self->{server} || 'Standalone';
+    if (Jifty->find_plugin('Jifty::Plugin::PubSub') and $server_class !~ /^(Twiggy|Feersum)$/i) {
+        if (Jifty::Util->try_to_require("Twiggy")) {
+            $server_class = "Twiggy";
+        } elsif (Jifty::Util->try_to_require("Feersum")) {
+            $server_class = "Feersum";
+        } else {
+            die "An event-based PSGI server (i.e. Twiggy, Feersum) is needed to run PubSub or RPC";
+        }
+    }
+    $Jifty::SERVER = Plack::Loader->load($server_class, %args);
     $Jifty::SERVER->run(Jifty->handler->psgi_app);
 }
 

commit e47b467ad3c9e0546deff18e968bf3ebbed1c479
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Fri May 18 01:22:11 2012 -0400

    Factor client handling code into its own (still no-op) module

diff --git a/lib/Jifty/Plugin/PubSub.pm b/lib/Jifty/Plugin/PubSub.pm
index b09322b..c0973c9 100644
--- a/lib/Jifty/Plugin/PubSub.pm
+++ b/lib/Jifty/Plugin/PubSub.pm
@@ -7,6 +7,7 @@ use base qw/Jifty::Plugin/;
 use AnyMQ;
 use Plack::Builder;
 use Web::Hippie::App::JSFiles;
+use Jifty::Plugin::PubSub::Connection;
 
 sub init {
     my $self = shift;
@@ -56,6 +57,7 @@ sub wrap {
     my $self = shift;
     my $app = shift;
 
+    my %connections;
     builder {
         mount '/__jifty/_hippie' => builder {
             enable "+Web::Hippie";
@@ -63,7 +65,20 @@ sub wrap {
             sub { my $env = shift;
                   my $listener  = $env->{'hippie.listener'}; # AnyMQ::Queue
                   my $client_id = $env->{'hippie.client_id'}; # client id
+
+                  $connections{$client_id}
+                      ||= Jifty::Plugin::PubSub::Connection->new($env);
+                  my $c = $connections{$client_id};
+
                   my $path = $env->{PATH_INFO};
+                  if ($path eq "/new_listener") {
+                      $c->connect;
+                  } elsif ($path eq "/message") {
+                      $c->receive($env->{'hippie.message'});
+                  } elsif ($path eq "/error") {
+                      delete $connections{$client_id};
+                      $c->disconnect;
+                  }
             };
         };
 
diff --git a/lib/Jifty/Plugin/PubSub/Connection.pm b/lib/Jifty/Plugin/PubSub/Connection.pm
new file mode 100644
index 0000000..7d2ed53
--- /dev/null
+++ b/lib/Jifty/Plugin/PubSub/Connection.pm
@@ -0,0 +1,27 @@
+use strict;
+use warnings;
+
+package Jifty::Plugin::PubSub::Connection;
+
+sub new {
+    my $class = shift;
+    my $env = shift;
+
+    my $self = bless {}, $class;
+
+    $self->{listener}  = $env->{'hippie.listener'};
+    $self->{client_id} = $env->{'hippie.client_id'};
+
+    return $self;
+}
+
+sub listener  { shift->{listener} }
+sub client_id { shift->{client_id} }
+
+sub connect {}
+
+sub receive {}
+
+sub disconnect {}
+
+1;

commit 3640f947904a5f00b85ff1b8e9afb8854685fb3e
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Fri May 18 01:24:45 2012 -0400

    Use AppName::PubSub as the standard app-specific class for connectons

diff --git a/lib/Jifty/Plugin/PubSub.pm b/lib/Jifty/Plugin/PubSub.pm
index c0973c9..a8015fa 100644
--- a/lib/Jifty/Plugin/PubSub.pm
+++ b/lib/Jifty/Plugin/PubSub.pm
@@ -22,6 +22,11 @@ sub init {
               pubsub/jquery.ev.js
           ! );
 
+    $opt{connection} ||= Jifty->app_class({require => 0}, 'PubSub');
+    $opt{connection} = 'Jifty::Plugin::PubSub::Connection'
+        unless Jifty::Util->try_to_require($opt{connection});
+    $self->{connection} = $opt{connection};
+
     my $anymq = AnyMQ->new_with_traits(
         traits => ['AMQP'],
         host   => 'localhost',
@@ -67,7 +72,7 @@ sub wrap {
                   my $client_id = $env->{'hippie.client_id'}; # client id
 
                   $connections{$client_id}
-                      ||= Jifty::Plugin::PubSub::Connection->new($env);
+                      ||= $self->{connection}->new($env);
                   my $c = $connections{$client_id};
 
                   my $path = $env->{PATH_INFO};

commit 0a34bc4037672c15322358b9309f79286024d0bb
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Fri May 18 01:35:55 2012 -0400

    Subscribe each connection to its own channel, for targetted delivery of messages

diff --git a/lib/Jifty/Plugin/PubSub/Connection.pm b/lib/Jifty/Plugin/PubSub/Connection.pm
index 7d2ed53..b81f539 100644
--- a/lib/Jifty/Plugin/PubSub/Connection.pm
+++ b/lib/Jifty/Plugin/PubSub/Connection.pm
@@ -12,6 +12,8 @@ sub new {
     $self->{listener}  = $env->{'hippie.listener'};
     $self->{client_id} = $env->{'hippie.client_id'};
 
+    $self->subscribe( "client." . $self->client_id );
+
     return $self;
 }
 
@@ -20,6 +22,18 @@ sub client_id { shift->{client_id} }
 
 sub connect {}
 
+sub subscribe {
+    my $self = shift;
+    $self->{listener}->subscribe( $_ )
+        for map { Jifty->bus->topic( $_) } @_;
+}
+
+sub send {
+    my $self = shift;
+    Jifty->bus->topic("client." . $self->client_id )
+        ->publish( @_ );
+}
+
 sub receive {}
 
 sub disconnect {}

commit 0fbf9555c23b436a0c15785cb5e5aefa455538ef
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Fri May 18 01:56:02 2012 -0400

    Store (and re-enter on each message) the request and current user

diff --git a/lib/Jifty/Plugin/PubSub.pm b/lib/Jifty/Plugin/PubSub.pm
index a8015fa..81ebc68 100644
--- a/lib/Jifty/Plugin/PubSub.pm
+++ b/lib/Jifty/Plugin/PubSub.pm
@@ -75,6 +75,10 @@ sub wrap {
                       ||= $self->{connection}->new($env);
                   my $c = $connections{$client_id};
 
+                  local $Jifty::WEB = $c->web;
+                  local $Jifty::API = $c->api;
+                  Jifty::Record->flush_cache if Jifty::Record->can('flush_cache');
+
                   my $path = $env->{PATH_INFO};
                   if ($path eq "/new_listener") {
                       $c->connect;
diff --git a/lib/Jifty/Plugin/PubSub/Connection.pm b/lib/Jifty/Plugin/PubSub/Connection.pm
index b81f539..1fed0db 100644
--- a/lib/Jifty/Plugin/PubSub/Connection.pm
+++ b/lib/Jifty/Plugin/PubSub/Connection.pm
@@ -8,7 +8,17 @@ sub new {
     my $env = shift;
 
     my $self = bless {}, $class;
-
+    $self->{web} = Jifty::Web->new;
+    $self->{web}->request(
+        Jifty::Request->promote( Plack::Request->new( $env ) ),
+    );
+    $self->{web}->response( Jifty::Response->new );
+    {
+        local $Jifty::WEB = $self->{web};
+        Jifty->web->setup_session;
+    }
+
+    $self->{api} = Jifty::API->new;
     $self->{listener}  = $env->{'hippie.listener'};
     $self->{client_id} = $env->{'hippie.client_id'};
 
@@ -17,6 +27,8 @@ sub new {
     return $self;
 }
 
+sub web       { shift->{web} }
+sub api       { shift->{api} }
 sub listener  { shift->{listener} }
 sub client_id { shift->{client_id} }
 

commit e984ef35917a06c25c2f0158d07d6a5f5a1b664e
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Fri May 18 01:58:31 2012 -0400

    Parse and run actions passed from the client over the pipe

diff --git a/lib/Jifty/Plugin/PubSub/Connection.pm b/lib/Jifty/Plugin/PubSub/Connection.pm
index 1fed0db..260212c 100644
--- a/lib/Jifty/Plugin/PubSub/Connection.pm
+++ b/lib/Jifty/Plugin/PubSub/Connection.pm
@@ -46,7 +46,35 @@ sub send {
         ->publish( @_ );
 }
 
-sub receive {}
+sub receive {
+    my $self = shift;
+    my $msg = shift;
+
+    return 1 if $self->action_message($msg);
+    return;
+}
+
+sub action_message {
+    my $self = shift;
+    my $msg = shift;
+    return unless exists $msg->{type}
+        and ($msg->{type} || '') eq "action"
+            and exists $msg->{class}
+                and defined $msg->{class};
+
+    my $class = Jifty->api->qualify($msg->{class});
+    unless (Jifty->api->is_allowed($class)) {
+        warn "Attempt to call denied action $class: ".Jifty->api->explain($class);
+        return 1;
+    }
+    my $action = Jifty->web->new_action(
+        class     => $class,
+        arguments => $msg->{arguments} || {},
+    );
+    $action->validate;
+    $action->run if $action->result->success;
+    return 1;
+}
 
 sub disconnect {}
 

commit 0cba44ffd540dcb38c6db1c39757872e2c1385e3
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Fri May 18 02:03:16 2012 -0400

    Split hpipe functions into their own .js file

diff --git a/lib/Jifty/Plugin/PubSub.pm b/lib/Jifty/Plugin/PubSub.pm
index 81ebc68..84fb7a0 100644
--- a/lib/Jifty/Plugin/PubSub.pm
+++ b/lib/Jifty/Plugin/PubSub.pm
@@ -20,6 +20,7 @@ sub init {
               pubsub/hippie.js
               pubsub/hippie.pipe.js
               pubsub/jquery.ev.js
+              pubsub.js
           ! );
 
     $opt{connection} ||= Jifty->app_class({require => 0}, 'PubSub');
@@ -46,7 +47,7 @@ sub init {
 
 sub body_end {
     my $self = shift;
-    Jifty->web->out( qq|<script type="text/javascript">var hpipe = new Hippie.Pipe(); hpipe.init({path: "/__jifty"})</script>|);
+    Jifty->web->out( qq|<script type="text/javascript">hpipe_init()</script>|);
 }
 
 sub psgi_app_static {
diff --git a/share/plugins/Jifty/Plugin/PubSub/web/static/js/pubsub.js b/share/plugins/Jifty/Plugin/PubSub/web/static/js/pubsub.js
new file mode 100644
index 0000000..a3f543a
--- /dev/null
+++ b/share/plugins/Jifty/Plugin/PubSub/web/static/js/pubsub.js
@@ -0,0 +1,4 @@
+var hpipe = new Hippie.Pipe();
+var hpipe_init = function() {
+    hpipe.init({path: "/__jifty"});
+};

commit a71793c84ff01a15ac081c142260156fe98918fc
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Fri May 18 02:05:26 2012 -0400

    Display hpipe-sent action results using jgrowl

diff --git a/lib/Jifty/Plugin/PubSub/Connection.pm b/lib/Jifty/Plugin/PubSub/Connection.pm
index 260212c..e577a31 100644
--- a/lib/Jifty/Plugin/PubSub/Connection.pm
+++ b/lib/Jifty/Plugin/PubSub/Connection.pm
@@ -73,6 +73,11 @@ sub action_message {
     );
     $action->validate;
     $action->run if $action->result->success;
+
+    my $result = $action->result->as_hash;
+    $result->{type} = "jifty.result";
+    $self->send($result);
+
     return 1;
 }
 
diff --git a/share/plugins/Jifty/Plugin/PubSub/web/static/js/pubsub.js b/share/plugins/Jifty/Plugin/PubSub/web/static/js/pubsub.js
index a3f543a..59ffa5e 100644
--- a/share/plugins/Jifty/Plugin/PubSub/web/static/js/pubsub.js
+++ b/share/plugins/Jifty/Plugin/PubSub/web/static/js/pubsub.js
@@ -1,4 +1,15 @@
 var hpipe = new Hippie.Pipe();
+jQuery(hpipe).bind("message.jifty.result", function (event, d) {
+    if (d.error)
+        jQuery.jGrowl( d.error, { theme: 'result-error' } );
+    else if (d.failure)
+        jQuery.each( d.field_errors, function (field, err) {
+            jQuery.jGrowl( field+': '+err, { theme: 'result-error' } );
+        });
+    else
+        jQuery.jGrowl( d.message, { theme: 'result-message' } );
+});
+
 var hpipe_init = function() {
     hpipe.init({path: "/__jifty"});
 };

commit 0f59f9fe5a08a86babd1fcb961088a43c841727a
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Fri May 18 02:39:45 2012 -0400

    Store subscriptions generated during the request to be subscribed to in the pipe

diff --git a/lib/Jifty/Plugin/PubSub.pm b/lib/Jifty/Plugin/PubSub.pm
index 84fb7a0..3bfb329 100644
--- a/lib/Jifty/Plugin/PubSub.pm
+++ b/lib/Jifty/Plugin/PubSub.pm
@@ -8,6 +8,7 @@ use AnyMQ;
 use Plack::Builder;
 use Web::Hippie::App::JSFiles;
 use Jifty::Plugin::PubSub::Connection;
+use Jifty::Plugin::PubSub::Subscriptions;
 
 sub init {
     my $self = shift;
@@ -40,14 +41,23 @@ sub init {
     );
     *Jifty::bus = sub { $anymq };
 
+    my $subs = Jifty::Plugin::PubSub::Subscriptions->new;
+    *Jifty::subs = sub { $subs };
+
     Jifty::View->add_trigger(
         body_end => sub { $self->body_end }
     );
 }
 
+sub new_request {
+    Jifty->subs->reset;
+}
+
 sub body_end {
     my $self = shift;
-    Jifty->web->out( qq|<script type="text/javascript">hpipe_init()</script>|);
+    my $client_id = Jifty->subs->client_id || "";
+    $client_id = "'$client_id'" if $client_id;
+    Jifty->web->out( qq|<script type="text/javascript">hpipe_init($client_id)</script>|);
 }
 
 sub psgi_app_static {
diff --git a/lib/Jifty/Plugin/PubSub/Connection.pm b/lib/Jifty/Plugin/PubSub/Connection.pm
index e577a31..49e42dc 100644
--- a/lib/Jifty/Plugin/PubSub/Connection.pm
+++ b/lib/Jifty/Plugin/PubSub/Connection.pm
@@ -22,6 +22,15 @@ sub new {
     $self->{listener}  = $env->{'hippie.listener'};
     $self->{client_id} = $env->{'hippie.client_id'};
 
+    $self->{subs} = Jifty->subs->retrieve($self->client_id);
+    if ( @{ $self->{subs} } ) {
+        my @subs = map {$_->{topic}} @{ $self->{subs} };
+        $self->{bus} = Jifty->bus->new_listener;
+        $self->{bus}->subscribe( $_ )
+            for map {Jifty->bus->topic($_)} @subs;
+        # Would ->poll for updates here
+    }
+
     $self->subscribe( "client." . $self->client_id );
 
     return $self;
diff --git a/lib/Jifty/Plugin/PubSub/Subscriptions.pm b/lib/Jifty/Plugin/PubSub/Subscriptions.pm
new file mode 100644
index 0000000..15c0a08
--- /dev/null
+++ b/lib/Jifty/Plugin/PubSub/Subscriptions.pm
@@ -0,0 +1,45 @@
+use strict;
+use warnings;
+
+package Jifty::Plugin::PubSub::Subscriptions;
+
+sub new {
+    my $class = shift;
+    my $env = shift;
+
+    my $self = bless {
+        store       => {},
+        client_id   => undef,
+    }, $class;
+    return $self;
+}
+
+sub reset {
+    my $self = shift;
+    $self->{client_id} = undef;
+}
+
+sub retrieve {
+    my $self = shift;
+    my $client_id = shift;
+    return delete $self->{store}{$client_id} || [];
+}
+
+sub client_id {
+    my $self = shift;
+    return $self->{client_id};
+}
+
+sub add {
+    my $self = shift;
+    my %args = (
+        topic => undef,
+        @_
+    );
+
+    $self->{client_id} ||= "jifty_" . Jifty->web->serial;
+
+    push @{$self->{store}{$self->{client_id}}}, \%args;
+}
+
+1;
diff --git a/share/plugins/Jifty/Plugin/PubSub/web/static/js/pubsub.js b/share/plugins/Jifty/Plugin/PubSub/web/static/js/pubsub.js
index 59ffa5e..1e84aa5 100644
--- a/share/plugins/Jifty/Plugin/PubSub/web/static/js/pubsub.js
+++ b/share/plugins/Jifty/Plugin/PubSub/web/static/js/pubsub.js
@@ -11,5 +11,8 @@ jQuery(hpipe).bind("message.jifty.result", function (event, d) {
 });
 
 var hpipe_init = function() {
-    hpipe.init({path: "/__jifty"});
+    var opt = {path: "/__jifty"};
+    if (arguments.length)
+        opt.client_id = arguments[0];
+    hpipe.init(opt);
 };

commit 80b4ce05d31d9dbd9ba809fd878312f86f421408
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Fri May 18 02:41:25 2012 -0400

    Don't bother adding action limits during subrequests

diff --git a/lib/Jifty/Dispatcher.pm b/lib/Jifty/Dispatcher.pm
index 20f42ff..e71dd92 100644
--- a/lib/Jifty/Dispatcher.pm
+++ b/lib/Jifty/Dispatcher.pm
@@ -873,7 +873,8 @@ sub _do_dispatch {
     $self->log->debug("Dispatching request to ".$self->{path});
 
     # Disable most actions on GET requests
-    Jifty->api->deny_for_get() if $self->_match_method('GET');
+    Jifty->api->deny_for_get() if $self->_match_method('GET')
+        and not Jifty->web->request->is_subrequest;
 
     # Setup -- we we don't abort out of setup, then run the
     # actions and then the RUN stage.

commit a97dedcd8742bd0c57b95a729b57704e339c84bb
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Sun Apr 8 11:56:21 2012 -0400

    Re-indent

diff --git a/share/web/static/js/jifty.js b/share/web/static/js/jifty.js
index bd78989..5facbec 100644
--- a/share/web/static/js/jifty.js
+++ b/share/web/static/js/jifty.js
@@ -922,77 +922,77 @@ var current_args = {};
 //  - 'fragment' is a hash, see fragments in update()
 
 function prepare_element_for_update(f) {
-        var name = f['region'];
+    var name = f['region'];
 
-        // Find where we are going to go
-        var element = document.getElementById('region-' + f['region']);
-        if (f['element']) {
-            element = jQuery(f['element'])[0];
-        }
-        f['element'] = element;
-
-        // If we can't find out where we're going, bail
-        if (element == null)
-            return;
-
-        // If we're removing the element, do it now
-        if (f['mode'] == "Delete") {
-            fragments[name] = null;
-            if (f['effect']) {
-                Jifty.Effect(
-                    Jifty.$('region-'+f['region']),
-                    f['effect'],
-                    f['effect_args']
-                );
-                jQuery(element).queue(function() {
-                    jQuery(element).remove();
-                    jQuery(element).dequeue();
-                });
-            } else if (f['remove_effect']) {
-                Jifty.Effect(
-                    Jifty.$('region-'+f['region']),
-                    f['remove_effect'],
-                    f['remove_effect_args']
-                );
-                jQuery(element).queue(function() {
-                    jQuery(element).remove();
-                    jQuery(element).dequeue();
-                });
-            } else {
+    // Find where we are going to go
+    var element = document.getElementById('region-' + f['region']);
+    if (f['element']) {
+        element = jQuery(f['element'])[0];
+    }
+    f['element'] = element;
+
+    // If we can't find out where we're going, bail
+    if (element == null)
+        return;
+
+    // If we're removing the element, do it now
+    if (f['mode'] == "Delete") {
+        fragments[name] = null;
+        if (f['effect']) {
+            Jifty.Effect(
+                Jifty.$('region-'+f['region']),
+                f['effect'],
+                f['effect_args']
+            );
+            jQuery(element).queue(function() {
                 jQuery(element).remove();
-            }
-            return;
+                jQuery(element).dequeue();
+            });
+        } else if (f['remove_effect']) {
+            Jifty.Effect(
+                Jifty.$('region-'+f['region']),
+                f['remove_effect'],
+                f['remove_effect_args']
+            );
+            jQuery(element).queue(function() {
+                jQuery(element).remove();
+                jQuery(element).dequeue();
+            });
+        } else {
+            jQuery(element).remove();
         }
+        return;
+    }
 
-        f['is_new'] = (fragments[name] ? false : true);
-        // If it's new, we need to create it so we can dump it
-        if (f['is_new']) {
-            // Find what region we're inside
-            f['parent'] = null;
-            if (f['mode'] && ((f['mode'] == "Before") || (f['mode'] == "After")))
-                element = element.parentNode;
-            while ((element != null) && (element.getAttribute) && (f['parent'] == null)) {
-                if (/^region-/.test(element.getAttribute("id")))
-                    f['parent'] = element.getAttribute("id").replace(/^region-/,"");
-                element = element.parentNode;
-            }
-
-            if (f['parent']) {
-                f['region'] = name = f['parent'] + '-' + name;
-            }
+    f['is_new'] = (fragments[name] ? false : true);
+    // If it's new, we need to create it so we can dump it
+    if (f['is_new']) {
+        // Find what region we're inside
+        f['parent'] = null;
+        if (f['mode'] && ((f['mode'] == "Before") || (f['mode'] == "After")))
+            element = element.parentNode;
+        while ((element != null) && (element.getAttribute) && (f['parent'] == null)) {
+            if (/^region-/.test(element.getAttribute("id")))
+                f['parent'] = element.getAttribute("id").replace(/^region-/,"");
+            element = element.parentNode;
+        }
 
-            // Make the region (for now)
-            new Region(name, f['args'], f['path'], f['parent'], f['parent'] ? fragments[f['parent']].in_form : null);
-        } else if ((f['path'] != null) && f['toggle'] && (f['path'] == fragments[name].path)) {
-            // If they set the 'toggle' flag, and clicking wouldn't change the path
-            jQuery(element).empty();
-            fragments[name].path = null;
-            return;
-        } else if (f['path'] == null) {
-            // If they didn't know the path, fill it in now
-            f['path'] == fragments[name].path;
+        if (f['parent']) {
+            f['region'] = name = f['parent'] + '-' + name;
         }
 
+        // Make the region (for now)
+        new Region(name, f['args'], f['path'], f['parent'], f['parent'] ? fragments[f['parent']].in_form : null);
+    } else if ((f['path'] != null) && f['toggle'] && (f['path'] == fragments[name].path)) {
+        // If they set the 'toggle' flag, and clicking wouldn't change the path
+        jQuery(element).empty();
+        fragments[name].path = null;
+        return;
+    } else if (f['path'] == null) {
+        // If they didn't know the path, fill it in now
+        f['path'] == fragments[name].path;
+    }
+
     return f;
 }
 

commit f39b96d25541470b0a4e70ed274d2ca1a714b514
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Fri May 18 00:12:21 2012 -0400

    Split apply_fragment_updates into XML parsing and application
    
    apply_fragment_updates consists of two halves -- walking an XML DOM to
    extract response information, and applying that response information to
    update the fragment on the page.  Split the function into
    xml_fragment_updates and fragment_updates, so that non-XML codepaths can
    reuse the latter function to apply changes to fragments.

diff --git a/share/web/static/js/jifty.js b/share/web/static/js/jifty.js
index 5facbec..42ea4d8 100644
--- a/share/web/static/js/jifty.js
+++ b/share/web/static/js/jifty.js
@@ -1009,12 +1009,10 @@ var walk_node = function(node, table) {
 // applying updates from a fragment
 //   - fragment: the fragment from the server
 //   - f: fragment spec
-var apply_fragment_updates = function(fragment, f) {
-    // We found the right fragment
-    var dom_fragment = fragments[ f['region'] ];
-    var new_dom_args = {};
+var xml_fragment_updates = function(fragment, f) {
+    var args = {};
+    var textContent = '';
 
-    var element = f['element'];
     walk_node(
         fragment,
         {
@@ -1029,60 +1027,66 @@ var apply_fragment_updates = function(fragment, f) {
                 } else if (fragment_bit.firstChild) {
                     textContent = fragment_bit.firstChild.nodeValue;
                 }
-                new_dom_args[ fragment_bit.getAttribute("name") ] = textContent;
+                args[ fragment_bit.getAttribute("name") ] = textContent;
             },
             content: function(fragment_bit) {
-                var textContent = '';
                 if (fragment_bit.textContent) {
                     textContent = fragment_bit.textContent;
                 } else if (fragment_bit.firstChild) {
                     textContent = fragment_bit.firstChild.nodeValue;
                 }
 
-                // Re-arrange all <script> tags to the end of textContent.
-                // This approach easily deal with the uncertain amount of
-                // time we need to wait before the region is ready for running
-                // some javascript.
-
-                var re = new RegExp('<script[^>]*>([\\S\\s]*?)<\/script>', 'img');
-                var scripts = (textContent.match(re) || []).join("");
-                var textContentWithoutScript = textContent.replace(re, '');
-                textContent = textContentWithoutScript + scripts;
-
-                // Once we find it, do the insertion
-                if (f['mode'] == 'Popout') {
-                    jQuery.facebox(textContent);
-                    // Facebox always uses its #facebox element, so point to
-                    // that regardless of what we were told earlier
-                    element = document.getElementById('facebox');
-                } else if (f['mode'] && (f['mode'] != 'Replace')) {
-                    var method = ({
-                        After: 'after',
-                        Before: 'before',
-                        Bottom: 'append',
-                        Top: 'prepend'
-                    })[ f['mode'] ];
-
-                    jQuery.fn[method].call(jQuery(element), textContent);
-                    element = document.getElementById('region-' + f['region']);
-                } else if (f['remove_effect']) {
-                    Jifty.Effect(
-                        Jifty.$('region-'+f['region']),
-                        f['remove_effect'],
-                        f['remove_effect_args']
-                    );
-                    jQuery(element).queue(function() {
-                        jQuery(element).html( textContent );
-                        jQuery(element).dequeue();
-                    });
-                } else {
-                    jQuery(element).html( textContent );
-                }
-                Behaviour.apply(element);
             }
         }
     );
-    dom_fragment.setArgs(new_dom_args);
+    fragment_updates(f, args, textContent);
+};
+
+var fragment_updates = function(f, args, textContent) {
+    // We found the right fragment
+    var dom_fragment = fragments[ f['region'] ];
+    var element = f['element'];
+
+    // Re-arrange all <script> tags to the end of textContent.
+    // This approach easily deal with the uncertain amount of
+    // time we need to wait before the region is ready for running
+    // some javascript.
+    var re = new RegExp('<script[^>]*>([\\S\\s]*?)<\/script>', 'img');
+    var scripts = (textContent.match(re) || []).join("");
+    var textContentWithoutScript = textContent.replace(re, '');
+    textContent = textContentWithoutScript + scripts;
+
+    // Once we find it, do the insertion
+    if (f['mode'] == 'Popout') {
+        jQuery.facebox(textContent);
+        // Facebox always uses its #facebox element, so point to
+        // that regardless of what we were told earlier
+        element = document.getElementById('facebox');
+    } else if (f['mode'] && (f['mode'] != 'Replace')) {
+        var method = ({
+            After: 'after',
+            Before: 'before',
+            Bottom: 'append',
+            Top: 'prepend'
+        })[ f['mode'] ];
+
+        jQuery.fn[method].call(jQuery(element), textContent);
+        element = document.getElementById('region-' + f['region']);
+    } else if (f['remove_effect']) {
+        Jifty.Effect(
+            Jifty.$('region-'+f['region']),
+            f['remove_effect'],
+            f['remove_effect_args']
+        );
+        jQuery(element).queue(function() {
+            jQuery(element).html( textContent );
+            jQuery(element).dequeue();
+        });
+    } else {
+        jQuery(element).html( textContent );
+    }
+    Behaviour.apply(element);
+    dom_fragment.setArgs(args);
 
     // Also, set us up the effect
     if (f['effect']) {
@@ -1457,7 +1461,7 @@ Jifty.update = function () {
 
             // Apply the fragment update to the page
             try {
-                apply_fragment_updates(response_fragment, f);
+                xml_fragment_updates(response_fragment, f);
             } catch (e) { alert(e) }
 
             // f

commit 5c5ccf5f5ecbcf91ec03de0b0cf7c5cc031c0fb6
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Fri May 18 02:43:03 2012 -0400

    Push fragment updates on appropriate events

diff --git a/lib/Jifty/Plugin/PubSub/Connection.pm b/lib/Jifty/Plugin/PubSub/Connection.pm
index 49e42dc..5953098 100644
--- a/lib/Jifty/Plugin/PubSub/Connection.pm
+++ b/lib/Jifty/Plugin/PubSub/Connection.pm
@@ -22,13 +22,13 @@ sub new {
     $self->{listener}  = $env->{'hippie.listener'};
     $self->{client_id} = $env->{'hippie.client_id'};
 
-    $self->{subs} = Jifty->subs->retrieve($self->client_id);
-    if ( @{ $self->{subs} } ) {
-        my @subs = map {$_->{topic}} @{ $self->{subs} };
-        $self->{bus} = Jifty->bus->new_listener;
-        $self->{bus}->subscribe( $_ )
+    $self->{region_subs} = Jifty->subs->retrieve($self->client_id);
+    if ( @{ $self->{region_subs} } ) {
+        my @subs = map {$_->{topic}} @{ $self->{region_subs} };
+        $self->{region_bus} = Jifty->bus->new_listener;
+        $self->{region_bus}->subscribe( $_ )
             for map {Jifty->bus->topic($_)} @subs;
-        # Would ->poll for updates here
+        $self->{region_bus}->poll( sub { $self->region_event( @_ ) } );
     }
 
     $self->subscribe( "client." . $self->client_id );
@@ -90,6 +90,72 @@ sub action_message {
     return 1;
 }
 
-sub disconnect {}
+sub region_event {
+    my $self = shift;
+    my $event = shift;
+    my $type = $event->{type} or return;
+
+    local $Jifty::WEB = $self->web;
+    local $Jifty::API = $self->api;
+    Jifty::Record->flush_cache if Jifty::Record->can('flush_cache');
+
+    for my $sub ( @{$self->{region_subs}} ) {
+        next unless $sub->{topic} eq $type;
+
+        my $content;
+        my $region_name;
+        eval {
+            # So we don't warn about "duplicate region"s
+            local Jifty->web->{'regions'} = {};
+            local Jifty->web->{'region_stack'} = [];
+            # So we don't pick up additional subs
+            local Jifty->subs->{region_subs} = [];
+
+            my $region = Jifty::Web::PageRegion->new(
+                name      => $sub->{region},
+                path      => $sub->{render_with},
+                arguments => $sub->{arguments},
+            );
+            $region_name = $region->qualified_name;
+            Jifty->subs->clear_for( $region_name );
+
+            $region->enter;
+            Jifty->handler->buffer->push( private => 1 );
+            $region->render_as_subrequest( {
+                %{$region->arguments},
+                event => $event,
+            } );
+            $content = Jifty->handler->buffer->pop;
+            $region->exit;
+            1;
+        } or warn "$@";
+
+        $self->send( {
+            type    => "jifty.fragment",
+            region  => $region_name,
+            path    => $sub->{render_with},
+            args    => $sub->{arguments},
+            content => $content,
+            mode    => $sub->{mode},
+            element => $sub->{element},
+            %{ $sub->{attrs} || {} },
+        } );
+    }
+
+    # For some reason, AnyMQ makes a queue sub'd to the topic become
+    # undef after the poll?  Re-subscribing resolves the issue.
+    my @subs = map {$_->{topic}} @{ $self->{region_subs} };
+    $self->{region_bus}->subscribe( $_ )
+        for map {Jifty->bus->topic($_)} @subs;
+}
+
+sub disconnect {
+    my $self = shift;
+    if ($self->{region_bus}) {
+        $self->{region_bus}->timeout(0);
+        $self->{region_bus}->unpoll;
+        undef $self->{region_bus};
+    };
+}
 
 1;
diff --git a/lib/Jifty/Plugin/PubSub/Subscriptions.pm b/lib/Jifty/Plugin/PubSub/Subscriptions.pm
index 15c0a08..7854950 100644
--- a/lib/Jifty/Plugin/PubSub/Subscriptions.pm
+++ b/lib/Jifty/Plugin/PubSub/Subscriptions.pm
@@ -30,16 +30,61 @@ sub client_id {
     return $self->{client_id};
 }
 
+sub clear_for {
+    my $self = shift;
+    my ($region) = @_;
+    $self->{store}{$self->{client_id}} = [
+        grep { $_->{region} ne $region }
+            @{$self->{store}{$self->{client_id}} }
+        ];
+}
+
 sub add {
     my $self = shift;
     my %args = (
-        topic => undef,
+        topic              => undef,
+        region             => undef,
+        render_with        => undef,
+        arguments          => undef,
+        mode               => undef,
+        element            => undef,
+        effect             => undef,
+        effect_args        => undef,
+        remove_effect      => undef,
+        remove_effect_args => undef,
         @_
     );
 
     $self->{client_id} ||= "jifty_" . Jifty->web->serial;
 
+    delete $args{$_} for grep {not defined $args{$_}} keys %args;
+
+    $args{attrs}{$_} = delete $args{$_}
+        for grep {defined $args{$_}}
+            qw/       effect        effect_args
+               remove_effect remove_effect_args/;
+
     push @{$self->{store}{$self->{client_id}}}, \%args;
 }
 
+sub update_on {
+    my $self = shift;
+    my $region = Jifty->web->current_region;
+    unless ($region) {
+        warn "Jifty->subs->update_on called when not in a region";
+        return;
+    }
+
+    my %args = %{ $region->arguments };
+    delete $args{region};
+    delete $args{event};
+    $self->add(
+        arguments   => \%args,
+        mode        => 'Replace',
+        region      => $region->qualified_name,
+        render_with => $region->path,
+        @_,
+    );
+}
+
 1;
diff --git a/share/plugins/Jifty/Plugin/PubSub/web/static/js/pubsub.js b/share/plugins/Jifty/Plugin/PubSub/web/static/js/pubsub.js
index 1e84aa5..173554a 100644
--- a/share/plugins/Jifty/Plugin/PubSub/web/static/js/pubsub.js
+++ b/share/plugins/Jifty/Plugin/PubSub/web/static/js/pubsub.js
@@ -1,4 +1,7 @@
 var hpipe = new Hippie.Pipe();
+jQuery(hpipe).bind("message.jifty.fragment", function (e, d) {
+    hippie_fragment(d);
+});
 jQuery(hpipe).bind("message.jifty.result", function (event, d) {
     if (d.error)
         jQuery.jGrowl( d.error, { theme: 'result-error' } );
@@ -16,3 +19,8 @@ var hpipe_init = function() {
         opt.client_id = arguments[0];
     hpipe.init(opt);
 };
+var hippie_fragment = function(f) {
+    f = prepare_element_for_update(f);
+    if (f == null) return;
+    fragment_updates(f, f['args'], f['content']);
+};

commit 43d87935ae6ae4edbc239bbb99c335e7a1a06e58
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Fri May 18 02:50:26 2012 -0400

    Add a simple RPC class atop the message bus

diff --git a/lib/Jifty/Plugin/RPC.pm b/lib/Jifty/Plugin/RPC.pm
new file mode 100644
index 0000000..9f07aee
--- /dev/null
+++ b/lib/Jifty/Plugin/RPC.pm
@@ -0,0 +1,24 @@
+use strict;
+use warnings;
+
+package Jifty::Plugin::RPC;
+use base qw/Jifty::Plugin/;
+
+use AnyEvent::RabbitMQ::RPC;
+
+sub prereq_plugins { 'PubSub' }
+
+our $RPC;
+sub init {
+    my $self = shift;
+    my %opt  = @_;
+
+    $RPC = AnyEvent::RabbitMQ::RPC->new(
+        serialize => "Storable",
+        connection => Jifty->bus->_rf,
+    );
+
+    *Jifty::rpc = sub { $RPC };
+}
+
+1;

commit 9d59fe5e9ba99cf0af66384f3351aa0154b7aef3
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Sun Jul 8 22:40:46 2012 -0400

    Set a VERSION on the PubSub and RPC plugins

diff --git a/lib/Jifty/Plugin/PubSub.pm b/lib/Jifty/Plugin/PubSub.pm
index 3bfb329..24c1391 100644
--- a/lib/Jifty/Plugin/PubSub.pm
+++ b/lib/Jifty/Plugin/PubSub.pm
@@ -10,6 +10,8 @@ use Web::Hippie::App::JSFiles;
 use Jifty::Plugin::PubSub::Connection;
 use Jifty::Plugin::PubSub::Subscriptions;
 
+our $VERSION = '0.5';
+
 sub init {
     my $self = shift;
     my %opt  = @_;
diff --git a/lib/Jifty/Plugin/RPC.pm b/lib/Jifty/Plugin/RPC.pm
index 9f07aee..3efe2ba 100644
--- a/lib/Jifty/Plugin/RPC.pm
+++ b/lib/Jifty/Plugin/RPC.pm
@@ -8,6 +8,8 @@ use AnyEvent::RabbitMQ::RPC;
 
 sub prereq_plugins { 'PubSub' }
 
+our $VERSION = '0.5';
+
 our $RPC;
 sub init {
     my $self = shift;

-----------------------------------------------------------------------


More information about the Jifty-commit mailing list