An event loop is a message dispatcher. The loop runs, waiting for events, and responding to them. The Kynetx Network Service (KNS) can be envisioned as a system of event loops that run in the cloud. KNS is extremely flexible, allowing developers to create their own event types and then write KRL programs that respond to those events with free form directives.
Event expressions in KRL can be designed to respond to complex event scenarios. KRL includes a set of event operators for combining event primitives into event expressions. Event primitives include some well known and built-in events like those in the Web domain as well as giving developers the ability to define their own event primitives.
See the documentation on event expressions for more information on responding to events from within KRL.
The expression of a KRL program takes one of two possible forms, a JavaScript program or a set of directives, depending on the capabilities of the endpoint. Regardless of the ultimate expression of a KRL program, some of the expressions and statements in KRL program are executed by the rules engine and others are executed by the endpoint. Understanding the execution of a KRL program depends on understanding this distinction. The most important distinction to understand is that rule actions are executed by the endpoint and everything else is executed on the rules engine.
When the Kynetx Rules Engine (KRE) produces a Javascript program, care is taken to ensure that any values bound to names on the engine are bound similarly bound to the same names in the expressed Javascript program so that execution of the Javascript on the endpoint has the same environment as existed on KRE. Closures are created to create a similar scoping of names in Javascript as existed on KRE.
KRL is executed by the KNS service calls to the Kynetx Rules Engine (KRE) from an endpoint. There are two main types of endpoints: those that understand Javascript and those that do not. They are described in the following sections.
An endpoint has two primary tasks:
Raise events appropriate to the endpoint type
Respond to the directives sent from KRE in an appropriate manner
For example, a browser extension serving as a Kynetx endpoint would raise the appropriate events for the Web domain including pageview, submit, and so on. The browser extension also responds to directives from KRE. The most important being to execute the returned Javascript in the context of the page.
As another example, an IMAP endpoint would raise events for the Mail domain, including received, sent, etc. and respond to the directives that might include things like delete, forward, and so on.
Each endpoint, regardless of it's domain raises events and executes directives.
Endpoints that Understand Javascript
The quintessential Javascript (JS) endpoint is a browser extension. Kynetx has significant support for delivering Javascript to browsers through various endpoints. Other endpoints that understand Javascript are also possible and work as described below.
The following diagram shows the KNS operations lifecycle and the interplay between a JS endpoint and KRE:
The endpoint exists in three distinct lifecycle phases:
Preparation - when it starts or is refreshed, the endpoint makes an API call to the selector to determine the RIDs of any installed cards and then uses that data to call KNS and determine on which domains those RIDs are applicable, called the dispatch list.
Wait - the endpoint exists in a wait state until it detects a page with a domain that matches a domain on the dispatch list. When that happens it initiates KRE execution as described below. When the execution is completed, the endpoint returns to a wait state.
Finalize - when the browser is closed, the endpoint completes any clean up tasks and ends.
There are three stages in KRL execution by KRE:
Initialization
Evaluation
Callback
These are described in detail below
Initialization
Initialization configures and initiates the endpoint by downloading a runtime appropriate to the endpoint type.
Configuration is performed by adding a script tag to the page that defines the KOBJ_config object like so:
The config object must contain an array names "rids" that contains the RIDs of rulesets applicable to this page. The config object can also contain an optional object named "init" that can override the URLs of the eval and callback host. The "init" object will not be included under most circumstances.
The other components of the config object are parameters that will be passed to the ruleset when it is evaluates. These can be read and tested using the page:param function in KRL (without the namespace designation). Parameter names should be namespaced by prepending RID with a colon (:) separator like so:
The initialization process will add tags to the page that cause ruleset evaluation to commence. The process results in a custom Javascript program being returned to the endpoint. In the case of a browser endpoint, the Javascript program will run in the context of the current page.
Callback
Some rules create explicit callbacks to KNS for various activities that the user takes. These are managed by the endpoint.
Directive Endpoints
Any device or program that is connected to the Internet and understands HTTP can serve as an endpoint. As described above, endpoints have two primary tasks:
Raise events appropriate to the endpoint type
Respond to the directives sent from KRE in an appropriate manner
Raising an event is accomplished using the event API. By forming the appropriate URL and then using HTTP to call it, the endpoint raises the event.
The result, for endpoints that do not understand Javascript, will be a directive document. A directive document is delivered as JSON that takes the following form:
For each object in the directives array, the endpoint uses the directive name and options to take a particular action. The meta information contains the name of the rule that returned the directive, the ruleset ID that the rule belongs to, and a transaction ID. The transaction ID is guaranteed to be globally unique and will be the same for every directive in a given directive document.
Event and Endpoint Example
The following example shows a simple endpoint written in Perl that implements an echo server and client.
#!/usr/bin/perl -w
use strict;
use Getopt::Std;
use LWP::Simple;
use JSON::XS;
use Kynetx::Raise;
# global options
use vars qw/ %opt /;
my $opt_string = 'h?e:m:';
getopts( "$opt_string", \%opt ); # or &usage();
my $event_type = $opt{'e'} || 'hello';
my $message = $opt{'m'} || '';
my $event = Kynetx::Raise->new('echo',
$event_type,
'a16x66',
{'host' => '127.0.0.1'}
);
my $response = $event->raise({'input' => $message});
foreach my $d (@{$response->{'directives'}}) {
if ($d->{'name'} eq 'say') {
print $d->{'options'}->{'something'}, "\n";
}
}
This simple script uses a module called Kynetx::Raise that takes the relevant information about the event, creates the right URL for the Kynetx event API, raises the event by calling the URL, and processes the response. You can see that it has the possibility of taking the event type from the command line with the -e switch. If none is given, the event type defaults to hello.
To function, this endpoint needs a corresponding set of rules to react to the events it raises. Here are two such rules:
rule hello_world is active {
select when echo hello
send_directive("say") with
something = "Hello World";
}
rule echo is active {
select when echo message input "(.*)" setting(m)
send_directive("say") with
something = m;
}
The rule hello_world responds to the hello event by sending the directive named say with the parameter something set to "Hello World". The rule echo responds to an echo event with a parameter called input. That entire value of the input is caputured and bound to the variable m. The echo rule send a directive named say with the parameter something set to the value of m.
It's critical to note that the underlying KNS engine doesn't know anything about the event domain echo or the event types hello and message. We could define these to be anything we wanted and the example would work the same.
If the endpoint is run with no arguments the default event type, hello, is raised which results in the hello_world rule we defined above firing and the directive say "Hello World" being sent to the program which prints the message.
Running the program with the -e switch like so:
./echo.pl -e message -m 'KRL programs the Internet!'
raises the event type message in the echo domain. KNS returns the following directive document:
Execution Model
Event Loops
An event loop is a message dispatcher. The loop runs, waiting for events, and responding to them. The Kynetx Network Service (KNS) can be envisioned as a system of event loops that run in the cloud. KNS is extremely flexible, allowing developers to create their own event types and then write KRL programs that respond to those events with free form directives.
Event expressions in KRL can be designed to respond to complex event scenarios. KRL includes a set of event operators for combining event primitives into event expressions. Event primitives include some well known and built-in events like those in the Web domain as well as giving developers the ability to define their own event primitives.
See the documentation on event expressions for more information on responding to events from within KRL.
In KNS, endpoints raise events using event API.
Language Execution Duality
The expression of a KRL program takes one of two possible forms, a JavaScript program or a set of directives, depending on the capabilities of the endpoint. Regardless of the ultimate expression of a KRL program, some of the expressions and statements in KRL program are executed by the rules engine and others are executed by the endpoint. Understanding the execution of a KRL program depends on understanding this distinction. The most important distinction to understand is that rule actions are executed by the endpoint and everything else is executed on the rules engine.
When the Kynetx Rules Engine (KRE) produces a Javascript program, care is taken to ensure that any values bound to names on the engine are bound similarly bound to the same names in the expressed Javascript program so that execution of the Javascript on the endpoint has the same environment as existed on KRE. Closures are created to create a similar scoping of names in Javascript as existed on KRE.
Endpoints
KRL is executed by the KNS service calls to the Kynetx Rules Engine (KRE) from an endpoint. There are two main types of endpoints: those that understand Javascript and those that do not. They are described in the following sections.
An endpoint has two primary tasks:
For example, a browser extension serving as a Kynetx endpoint would raise the appropriate events for the Web domain including
pageview,submit, and so on. The browser extension also responds to directives from KRE. The most important being to execute the returned Javascript in the context of the page.As another example, an IMAP endpoint would raise events for the Mail domain, including
received,sent, etc. and respond to the directives that might include things likedelete,forward, and so on.Each endpoint, regardless of it's domain raises events and executes directives.
Endpoints that Understand Javascript
The quintessential Javascript (JS) endpoint is a browser extension. Kynetx has significant support for delivering Javascript to browsers through various endpoints. Other endpoints that understand Javascript are also possible and work as described below.
The following diagram shows the KNS operations lifecycle and the interplay between a JS endpoint and KRE:
The endpoint exists in three distinct lifecycle phases:
There are three stages in KRL execution by KRE:
These are described in detail below
Initialization
Initialization configures and initiates the endpoint by downloading a runtime appropriate to the endpoint type.
Configuration is performed by adding a script tag to the page that defines the KOBJ_config object like so:
<script type="text/javascript"> var KOBJ_config ={ "rids" : ["kntx_rulealert","kntx_rulealert_2"], "init" : {"eval_host" : "cs.kobj.net","callback_host":"log.kobj.net"}, "key_1" : "value_1", "key_2" : "value_2" }; </script>The config object must contain an array names "rids" that contains the RIDs of rulesets applicable to this page. The config object can also contain an optional object named "init" that can override the URLs of the eval and callback host. The "init" object will not be included under most circumstances.
The other components of the config object are parameters that will be passed to the ruleset when it is evaluates. These can be read and tested using the page:param function in KRL (without the namespace designation). Parameter names should be namespaced by prepending RID with a colon (:) separator like so:
var KOBJ_config ={ "rids" : ["ruleset_1","ruleset_2"], "ruleset_1:ex_param" : "3", "ruleset_2:ex_param" : "5", };Parameters must be namespaced by the ruleset ID to be visible in KRL.
After the config object as been added to the page, the evaluation is initiated by adding this tag to the page:
This loads the KRL runtime library and initiates execution.
Evaluation
The initialization process will add tags to the page that cause ruleset evaluation to commence. The process results in a custom Javascript program being returned to the endpoint. In the case of a browser endpoint, the Javascript program will run in the context of the current page.
Callback
Some rules create explicit callbacks to KNS for various activities that the user takes. These are managed by the endpoint.
Directive Endpoints
Any device or program that is connected to the Internet and understands HTTP can serve as an endpoint. As described above, endpoints have two primary tasks:
Raising an event is accomplished using the event API. By forming the appropriate URL and then using HTTP to call it, the endpoint raises the event.
The result, for endpoints that do not understand Javascript, will be a directive document. A directive document is delivered as JSON that takes the following form:
{"directives": [{"options":{<name>:<value>[,<name>:<value>]*}, "name":<directive_name>, "meta":{ "rule_name":<rule_name>, "txn_id":<txn_id>, "rid":<rid> } } ] }For each object in the directives array, the endpoint uses the directive name and options to take a particular action. The meta information contains the name of the rule that returned the directive, the ruleset ID that the rule belongs to, and a transaction ID. The transaction ID is guaranteed to be globally unique and will be the same for every directive in a given directive document.
Event and Endpoint Example
The following example shows a simple endpoint written in Perl that implements an echo server and client.
#!/usr/bin/perl -w use strict; use Getopt::Std; use LWP::Simple; use JSON::XS; use Kynetx::Raise; # global options use vars qw/ %opt /; my $opt_string = 'h?e:m:'; getopts( "$opt_string", \%opt ); # or &usage(); my $event_type = $opt{'e'} || 'hello'; my $message = $opt{'m'} || ''; my $event = Kynetx::Raise->new('echo', $event_type, 'a16x66', {'host' => '127.0.0.1'} ); my $response = $event->raise({'input' => $message}); foreach my $d (@{$response->{'directives'}}) { if ($d->{'name'} eq 'say') { print $d->{'options'}->{'something'}, "\n"; } }This simple script uses a module called
Kynetx::Raisethat takes the relevant information about the event, creates the right URL for the Kynetx event API, raises the event by calling the URL, and processes the response. You can see that it has the possibility of taking the event type from the command line with the-eswitch. If none is given, the event type defaults tohello.To function, this endpoint needs a corresponding set of rules to react to the events it raises. Here are two such rules:
rule hello_world is active { select when echo hello send_directive("say") with something = "Hello World"; } rule echo is active { select when echo message input "(.*)" setting(m) send_directive("say") with something = m; }The rule
hello_worldresponds to thehelloevent by sending the directive namedsaywith the parametersomethingset to "Hello World". The ruleechoresponds to anechoevent with a parameter calledinput. That entire value of the input is caputured and bound to the variablem. Theechorule send a directive namedsaywith the parametersomethingset to the value ofm.It's critical to note that the underlying KNS engine doesn't know anything about the event domain
echoor the event typeshelloandmessage. We could define these to be anything we wanted and the example would work the same.If the endpoint is run with no arguments the default event type, hello, is raised which results in the
hello_worldrule we defined above firing and the directive say "Hello World" being sent to the program which prints the message.Running the program with the
-eswitch like so:raises the event type message in the echo domain. KNS returns the following directive document:
{"directives": [{"options":{"something":"Hello World"}, "name":"say", "meta":{ "rule_name":"hello_world", "txn_id":"8FF45D92-7EDB-11DF-B34A-4BA9F4723EB4", "rid":"a16x66" } } ] }The perl program shown above consumes this directive document which
results in the string KRL programs the Internet! being printed in the terminal.