Difference between revisions of "Livelets"
(starting notes on WikiFS / Livelets crossover) |
(Change source-code blocks to standard format) |
||
(33 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
− | + | {{legacy}} | |
− | + | ||
− | = What is it? = | + | == What is it? == |
The idea of this extension is to allow live articles to be [[W:Wikipedia:Transclusion costs and benefits|transcluded]] which update automatically on change in a non-polling, fully [[W:Event-driven programming|event-driven]] way. It will use the parser-functions syntax to make it very similar in usage to normal templates. It's called a ''livelet'' since it's very similar in concept to the re-usable areas of options and information in a web page usually referred to as a ''[[w:portlet|portlet]]'', except that these are able to accept spontaneous incoming requests, not just to responses to their own requests, which means that ''livelets'' are able to stay up to date or be communicated with dynamically without any regular polling being necessary. | The idea of this extension is to allow live articles to be [[W:Wikipedia:Transclusion costs and benefits|transcluded]] which update automatically on change in a non-polling, fully [[W:Event-driven programming|event-driven]] way. It will use the parser-functions syntax to make it very similar in usage to normal templates. It's called a ''livelet'' since it's very similar in concept to the re-usable areas of options and information in a web page usually referred to as a ''[[w:portlet|portlet]]'', except that these are able to accept spontaneous incoming requests, not just to responses to their own requests, which means that ''livelets'' are able to stay up to date or be communicated with dynamically without any regular polling being necessary. | ||
− | + | Since we already have all the code written to handle sockets between PERL and [[SWF]], which won't ever be used for anything now since our peer interface is now in C and SDL, it seemed like a good opportunity to get it working in the field. | |
+ | *See also [[:Category:Livelets]] | ||
− | + | == Development Plan == | |
+ | The #live transclusion currently uses an ''xmlhttp request'' (XHR) object for each livelet, but soon this Javascript code will be removed and the livelet container changed to use the [http://mootools.net Mootools] Ajax class. The Javascript code used to make an update request is a function called ''updateLivelet'' defined in [[Livelets.js]], it takes a single parameter containing the ''id'' of the livelet to update. | ||
− | + | ;title (or un-named) | |
− | The | + | The first un-named parameter, or title parameter is used to specify the local article which will be embeded in the livelet's content. |
− | |||
− | |||
− | |||
− | |||
− | + | ;url | |
− | + | This is initially set by the ''#live'' parser-function if the un-named parameter or ''title'' parameter is supplied. It can also be set directly instead of using the ''title'' parameter so that external URL's can be used too. The update URL is read from the livelet's ''url'' attribute when ''updateLivelet'' is called, so it can be changed dynamically any time after page load if desired. | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | ;type | |
− | + | The type of livelet can be ''popup'', ''embed'' (default) or ''append''. | |
− | + | ;update | |
− | + | This specifies when the content should be updated. If this parameter is not supplied, then the livelet will not automatically update at all and will not even load automatically when the page loads. If it is set to 0 (zero), then the content will be requested after the page loads, but will not automatically update. Any other value defines the polling rate that the livelet should request headers to determine if the content has changed, and will then request the rest of the content if it has changed. | |
− | |||
− | + | '''Note:''' If the ''$wgLiveletsUseSWF'' is set to true, then the update functions will be called by the SWF when content changes regardless of the ''update'' parameter setting in the livelet container. | |
− | If | ||
− | The JS | + | The next stage is to get the PERL daemon loading and communicating with the SWF's and the PHP. Currently the SWF is loading into the page and is able to call a JS function that reads data from the SWF. Here's a quick rundown of the current state of the livelets components: |
+ | *'''[[livelets.php]]''' - Mediawiki hooks, needs to have an optional method of ensuring daemon is running. | ||
+ | *'''[[livelets.as]]''' - Routes incoming messages from server to livelet (only one message currently; ''update'') | ||
+ | *'''[[livelets.pl]]''' - maintains hash of clients, titles (in hierarchy of change) and sends update messages to affected clients. | ||
− | === | + | == Livelet Components == |
− | + | === [[livelets.php]] === | |
+ | *Add the ''#live'' parser function | ||
+ | *Ensure [[livelets.pl]] daemon is running | ||
+ | *Add the ''AfterSaveComplete'' hook | ||
+ | *Insert the SWF (compiled from [[livelets.as]]) into the page somewhere invisible but active | ||
− | + | ==== <s>UnknownAction Hook</s> ==== | |
+ | There is no livelet action necessary, the un-named parameter is the article title to transclude. Later, an option could be added to allow passing of parameters and rendering of the content lively, but to start with, the basic request of title is adequate. | ||
− | == | + | ==== Save Hook ==== |
− | The | + | The job of this hook is to send notification to all the SWF's which have live-containers that are out of date. To do this we need a persistent list of all the current SWF clients and their live article titles with ''Last Modified'' times. Each time a save occurs, we update the list. The list should also be periodically checked since templates which are transcluded within many articles can have there invalidation deferred to a job queue (from the ''HTMLCacheUpdate'' class) which takes time to get executed. |
− | + | ==== onChange Processes ==== | |
+ | There should be a method for defining jobs that should be queued when parameters change. These should be defined using parser-functions or semantic annotations in the template definition. The AfterSave hook can then check if any of these have changed (therefore requiring that it have pre-save as well) and queuing the processes accordingly | ||
− | + | === [[livelets.as]] === | |
− | |||
− | == [[livelets.as]] == | ||
Even the SWF ''XMLSocket'' is crippled in three main ways: | Even the SWF ''XMLSocket'' is crippled in three main ways: | ||
*It can only recieve incoming data from servers in the same domain the SWF was served from | *It can only recieve incoming data from servers in the same domain the SWF was served from | ||
Line 59: | Line 56: | ||
'''Note2:''' Although most PHP installations have socket support as standard now, we're still better using PERL because it still needs to be a separate port >1023 and run as a persistent daemon and we already have the code for this in PERL. | '''Note2:''' Although most PHP installations have socket support as standard now, we're still better using PERL because it still needs to be a separate port >1023 and run as a persistent daemon and we already have the code for this in PERL. | ||
− | '''Note3:''' The third limitation listed above is irrelevent to this application because the SWF has to establish the stream to the server rather than vica versa since there can be many SWF's | + | '''Note3:''' The third limitation listed above is irrelevent to this application because the SWF has to establish the stream to the server rather than vica versa since there can be many SWF's running on the local client. They would all have to have separate ports which the server would have to be notified of anyway. |
− | == [[livelets.pl]] == | + | '''Note4:''' Since Flash 9 the SWF client will ask for a policy file before connecting to the server, even if it's on the same domain. This can lead to hours of frustration if you don't know it's happening, see [http://www.lightsphere.com/dev/articles/flash_socket_policy.html this] clear explanation and simple example of responding with a policy file. |
− | Although PHP has socket capability it seems that many users would not have the functionality easily available as it often requires PHP to be recompiled with the --enable-sockets switch. Also, the PHP server script would need to be set up to run as a daemon, and many PHP installs do not support command-line PHP by default. So it seems to me that a PERL server would be simplest to implement, especially since we already have working socket code in PERL, it's available by default on virtually all Linux's, and is easy to install on Win32 as well. | + | |
+ | === [[livelets.pl]] === | ||
+ | *use code from [[wikid.pl]], livelets.pl will probably replace Wikid2 | ||
+ | Although PHP has socket capability it seems that many users would not have the functionality easily available as it often requires PHP to be recompiled with the --enable-sockets switch. Also, the PHP server script would need to be set up to run as a daemon (why? because the SWF must establish a persistent connection with the server since it's not a true listener), and many PHP installs do not support command-line PHP by default. So it seems to me that a PERL server would be simplest to implement, especially since we already have working socket code in PERL, it's available by default on virtually all Linux's, and is easy to install on Win32 as well. | ||
Rather than installing the daemon into init.d or as a service, the PHP script could check whether an instance is running and execute it if not so that the installation would then be no different than for most extensions, of putting the files into the extensions directory and ensuring they have the right permissions. | Rather than installing the daemon into init.d or as a service, the PHP script could check whether an instance is running and execute it if not so that the installation would then be no different than for most extensions, of putting the files into the extensions directory and ensuring they have the right permissions. | ||
− | On linux-like OS's it will run as a daemon, but doesn't install itself into ''init.d'' for automatic startup, instead [[livelets.php]] launches it if it isn' | + | On linux-like OS's it will run as a daemon, but doesn't install itself into ''init.d'' for automatic startup, instead [[livelets.php]] launches it if it isn't already running (it can send a simple ping command to the port to test if an instance is running). |
The code should work on windows, but is being developed and tested for Linux first. The socket code itself has been tested in windows, and we have code to make it run as a windows service, but no doubt there will be trouble and dedicated windows development time will be required which is unlikely to occur for some time since we have little interest in supporting corporate closed-source solutions. Windows users need to have PERL installed with the ''IO::Socket'' module, we recommend the [http://www.activeperl.com ActivePerl] package. | The code should work on windows, but is being developed and tested for Linux first. The socket code itself has been tested in windows, and we have code to make it run as a windows service, but no doubt there will be trouble and dedicated windows development time will be required which is unlikely to occur for some time since we have little interest in supporting corporate closed-source solutions. Windows users need to have PERL installed with the ''IO::Socket'' module, we recommend the [http://www.activeperl.com ActivePerl] package. | ||
− | = | + | == JavaScript & SWF interfacing == |
− | + | This [http://www.permadi.com/tutorial/flashjscommand Permadi example page] shows how SWF and JavaScript can interact, sending data to each other. By using the ability for a SWF to send data to JavaScript in the local page, we can effectively create a fully asynchronous socket to remove the requirement of polling the server-side from the Ajax system. | |
− | + | ||
− | + | MTASC supports version 9 SWF's which support the [http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/external/ExternalInterface.html ExternalInterface] allowing JS and SWF to all each others functions directly. This is a better solution than the ''Set/GetVariable'' solution in the example link above because information can only flow from the SWF to the JS via polling of the SWF's variable state. The ''ExternalInterface'' is made available to the MTASC script by adding the following ''import'' statement on the first line. | |
− | + | <source lang="as"> | |
− | + | import flash.external.ExternalInterface; | |
+ | </source> | ||
+ | |||
+ | == SWF compiling == | ||
+ | Building SWF movies without using the Adobe application can be done using [http://www.mtasc.org/ MTASC], and it's especially easy if the movie is script-only. | ||
− | + | [[Category:Livelets]] | |
− | |||
− | |||
− | |||
− |
Latest revision as of 16:54, 22 May 2015
Contents
What is it?
The idea of this extension is to allow live articles to be transcluded which update automatically on change in a non-polling, fully event-driven way. It will use the parser-functions syntax to make it very similar in usage to normal templates. It's called a livelet since it's very similar in concept to the re-usable areas of options and information in a web page usually referred to as a portlet, except that these are able to accept spontaneous incoming requests, not just to responses to their own requests, which means that livelets are able to stay up to date or be communicated with dynamically without any regular polling being necessary.
Since we already have all the code written to handle sockets between PERL and SWF, which won't ever be used for anything now since our peer interface is now in C and SDL, it seemed like a good opportunity to get it working in the field.
- See also Category:Livelets
Development Plan
The #live transclusion currently uses an xmlhttp request (XHR) object for each livelet, but soon this Javascript code will be removed and the livelet container changed to use the Mootools Ajax class. The Javascript code used to make an update request is a function called updateLivelet defined in Livelets.js, it takes a single parameter containing the id of the livelet to update.
- title (or un-named)
The first un-named parameter, or title parameter is used to specify the local article which will be embeded in the livelet's content.
- url
This is initially set by the #live parser-function if the un-named parameter or title parameter is supplied. It can also be set directly instead of using the title parameter so that external URL's can be used too. The update URL is read from the livelet's url attribute when updateLivelet is called, so it can be changed dynamically any time after page load if desired.
- type
The type of livelet can be popup, embed (default) or append.
- update
This specifies when the content should be updated. If this parameter is not supplied, then the livelet will not automatically update at all and will not even load automatically when the page loads. If it is set to 0 (zero), then the content will be requested after the page loads, but will not automatically update. Any other value defines the polling rate that the livelet should request headers to determine if the content has changed, and will then request the rest of the content if it has changed.
Note: If the $wgLiveletsUseSWF is set to true, then the update functions will be called by the SWF when content changes regardless of the update parameter setting in the livelet container.
The next stage is to get the PERL daemon loading and communicating with the SWF's and the PHP. Currently the SWF is loading into the page and is able to call a JS function that reads data from the SWF. Here's a quick rundown of the current state of the livelets components:
- livelets.php - Mediawiki hooks, needs to have an optional method of ensuring daemon is running.
- livelets.as - Routes incoming messages from server to livelet (only one message currently; update)
- livelets.pl - maintains hash of clients, titles (in hierarchy of change) and sends update messages to affected clients.
Livelet Components
livelets.php
- Add the #live parser function
- Ensure livelets.pl daemon is running
- Add the AfterSaveComplete hook
- Insert the SWF (compiled from livelets.as) into the page somewhere invisible but active
UnknownAction Hook
There is no livelet action necessary, the un-named parameter is the article title to transclude. Later, an option could be added to allow passing of parameters and rendering of the content lively, but to start with, the basic request of title is adequate.
Save Hook
The job of this hook is to send notification to all the SWF's which have live-containers that are out of date. To do this we need a persistent list of all the current SWF clients and their live article titles with Last Modified times. Each time a save occurs, we update the list. The list should also be periodically checked since templates which are transcluded within many articles can have there invalidation deferred to a job queue (from the HTMLCacheUpdate class) which takes time to get executed.
onChange Processes
There should be a method for defining jobs that should be queued when parameters change. These should be defined using parser-functions or semantic annotations in the template definition. The AfterSave hook can then check if any of these have changed (therefore requiring that it have pre-save as well) and queuing the processes accordingly
livelets.as
Even the SWF XMLSocket is crippled in three main ways:
- It can only recieve incoming data from servers in the same domain the SWF was served from
- It can only use port number >1023
- Most importantly - it is not a true listener, it can only listen on streams it has already established with the server. A server cannot spontaneously request a new connection from the SWF socket.
This third item is very important, because it means that a permenantly running server must be present, so we may need to include a simple server daemon using the code from server.pl.
Note1: If we use livelets.pl, then the SWF must be served by that, not by the wiki, because it can only recieve data from the same domain (which includes port number) as that which it was served from.
Note2: Although most PHP installations have socket support as standard now, we're still better using PERL because it still needs to be a separate port >1023 and run as a persistent daemon and we already have the code for this in PERL.
Note3: The third limitation listed above is irrelevent to this application because the SWF has to establish the stream to the server rather than vica versa since there can be many SWF's running on the local client. They would all have to have separate ports which the server would have to be notified of anyway.
Note4: Since Flash 9 the SWF client will ask for a policy file before connecting to the server, even if it's on the same domain. This can lead to hours of frustration if you don't know it's happening, see this clear explanation and simple example of responding with a policy file.
livelets.pl
- use code from wikid.pl, livelets.pl will probably replace Wikid2
Although PHP has socket capability it seems that many users would not have the functionality easily available as it often requires PHP to be recompiled with the --enable-sockets switch. Also, the PHP server script would need to be set up to run as a daemon (why? because the SWF must establish a persistent connection with the server since it's not a true listener), and many PHP installs do not support command-line PHP by default. So it seems to me that a PERL server would be simplest to implement, especially since we already have working socket code in PERL, it's available by default on virtually all Linux's, and is easy to install on Win32 as well.
Rather than installing the daemon into init.d or as a service, the PHP script could check whether an instance is running and execute it if not so that the installation would then be no different than for most extensions, of putting the files into the extensions directory and ensuring they have the right permissions.
On linux-like OS's it will run as a daemon, but doesn't install itself into init.d for automatic startup, instead livelets.php launches it if it isn't already running (it can send a simple ping command to the port to test if an instance is running).
The code should work on windows, but is being developed and tested for Linux first. The socket code itself has been tested in windows, and we have code to make it run as a windows service, but no doubt there will be trouble and dedicated windows development time will be required which is unlikely to occur for some time since we have little interest in supporting corporate closed-source solutions. Windows users need to have PERL installed with the IO::Socket module, we recommend the ActivePerl package.
JavaScript & SWF interfacing
This Permadi example page shows how SWF and JavaScript can interact, sending data to each other. By using the ability for a SWF to send data to JavaScript in the local page, we can effectively create a fully asynchronous socket to remove the requirement of polling the server-side from the Ajax system.
MTASC supports version 9 SWF's which support the ExternalInterface allowing JS and SWF to all each others functions directly. This is a better solution than the Set/GetVariable solution in the example link above because information can only flow from the SWF to the JS via polling of the SWF's variable state. The ExternalInterface is made available to the MTASC script by adding the following import statement on the first line.
import flash.external.ExternalInterface;
SWF compiling
Building SWF movies without using the Adobe application can be done using MTASC, and it's especially easy if the movie is script-only.