This is an archive of an inactive wiki and cannot be modified.

This is one of the possible Use Cases.

1. Abstract

This use case describes a Rule-based User Notification (“RUN”) framework that facilitates an interaction between an external or internal Betfair “Client” and the Betfair system viewed as a rapidly changing environment. In the Betfair ‘world’, the sports events are starting, the goals are scored, the trading is suspended, prices reach certain values. The RUN framework makes use of the rule technology to wrap the Betfair web service API, manage Client subscriptions to atomic events, detect atomic events, respond to the Client, as well as assist the Client in detecting complex events.

In this use case, the rules technology is used for structuring the event detection and response patterns by using derivation rules to verify conditions and reaction rules to specify the interaction protocols between the concerned parties. In our view, when two or more rulebases based on the W3C Rule Interchange Format standard interact with each other, the actual interaction should also be specified in a comparable rule-based formalism. This use case demonstrates the interoperability between derivation and reaction rules.

2. Status

Originally proposed by: 'AlexKozlenkov' of Betfair Ltd.

This is the second revision of the use case that streamlines the events detection logic, and standardises the subscriptions and notification formats by using name/value pairs (in a slotted form) and XQuery for specifying conditions on the XML fragments returned by the web services. The use case is currently at the level of an internal prototype developed in Betfair. The description here avoids excessive detail of the concrete implementation and focuses on workflows and patterns deemed to be relevant for the W3C Rule Interchange Format WG work on use cases and requirements.

The rules are given in the open source Prova rule language format (http://www.prova.ws). Prova combines the traditional Logic Programming syntax and semantics with effective procedural attachments specified in the Java syntax, untyped and typed variables, database wrappers, communication actions, and reaction rules.

Implementation:

The use case has been implemented in Prova complemented by a special purpose Java wrapper for the Betfair API (http://bdp.betfair.com).

Frequency/importance in real world:

The publish/subscribe mechanisms are extremely important in real world scenarios. The example can be used in many scenarios involving the events on the Web. It can have many interesting extensions, including the use of semantically annotated information as opposed to purely XML-based datatypes and XQuery used here. In particular, if the API or data feeds provided RDF-based information, SPARQL could have been used for specifying the event to be detected.

3. Links to Related Use Cases

To be described

4. Relationship to OWL/RDF Compatibility

To be described

5. Examples of Rule Platforms Supporting this Use Case

The use case is directly supported by the open source Prova rule language (http://www.prova.ws) that has built in reaction rules. Other potential systems include Fair Isaac products and Drools. Mapping to purely production rules systems is possible but arguably will make the design more complicated.

6. Benefits of Interchange

This use case partitions the solution space into several interoperating parties including the vendor (Betfair) API, the rule-based middle tier managing the Events Detection and Publishing (EDP component), and the rule-based user component (Client Frontend) that submits subscription requests and has the logic for detecting complex events. All the three parties can belong to different vendors or users so the benefits of the Interchange clearly include the interoperability and cross-system logic. If the user is assured of the interoperability with an EDP rulebase, alternative solutions can be easily substituted or used in addition to the existing ones allowing the user to organize sophisticated event management on the cross-domain level.

7. Requirements on the RIF

List requirements of this use case on the RIF.

8. Breakdown

8.1. Actors and their Goals

The system currently has only one type of Actor, referred to as the “Client”. The “Client” wants to obtain timely information about specific event patterns occurring in the perceived system, currently, the Betfair product. The “Client” will specify various rules for integrating atomic events into complex events, which may include sequencing of events, timed events, as well as branches, splits and joins. Even more complex event detection mechanisms may require event inference based on, e.g., Event Calculus. The “Client” only interacts with a local User rulebase that in turn submits subscribe events to the Event Detection and Publishing (EDP) component and receives back the notify messages.

8.2. Main Sequence

The Client is interested in the following scenario.

Scenario:

  1. By using a user interface or programmatically, the Client specifies an atomic or complex event pattern (EP) that she wishes to be detected and notified about.
  2. The event pattern is stored locally as a RIF rulebase fragment.
  3. The Client activates the event pattern. The Client Frontend sends a subscribe message to the Event Detection and Publishing (EDP) component specifying the initiator (first triggering) event of the EP.

  4. The Client Frontend starts a non-blocked wait for a response from EDP.
  5. EDP records the subscription and updates its list of detectable atomic event patterns.

  6. On the next one second mark, EDP fires an event detection and response reaction rule.
  7. For each detectable event pattern matching the one sent by the user, EDP invokes the web service API wrapper and matches the response against the event pattern.
  8. For each matching pattern, TDP responds to the detected event by sending a notify message to the Client and removing the subscription.

  9. TDP removes all detectable event patterns that match the detected events.

  10. The Client Frontend receives the notify message with the concrete event that has been detected and stops waiting on one or more notifications.

  11. If there are more events in the complex event description, the Client Frontend sends one or more new subscriptions to EDP and starts waiting for responses.
  12. The EDP reacts to the subscription as per item 5.

The remainder of this Section presents the main flavours of the rules involved in specifying the various parts of the Betfair Rule-based Notification (RUN) framework. The described components include:

Web service API wrapper

The following rules show how the EDP logs into the Betfair API obtaining a corresponding API object and then uses a non-deterministic predicate to access the active event categories.

ws_betfair_init() :- 
      API = com.betfair.rules.notification.ws.API('username','password',82),
      assert(api(API)),
      x_login(),
      x_active_event(
                [],
                'for $x in $a//eventTypeItems/v2:EventType
                        where contains($x/name/text(),"Horse")
                        return <result>{$x/id}{$x/name}</result>',
                EventTypeId,EventTypeName),
      println([EventTypeId,": ",EventTypeName]),
      ...
x_login() :-
      api(API),
      API.bf_login().
x_active_event(Parms,XQuery|Values) :-
      api(API),
      API.x_active_event(Parms,XQuery|Values).

There are several concerns that have to be addressed in order to be able to wrap a web service API in this rulebase. The first rule makes use of a Java constructor to obtain a reference to a new API wrapper object. The rulebase must keep the API object as a local reference—it uses a Prolog style fact added via assert to store it (it is done only once). The code retrieves this object from the relevant fact each time it needs to ‘call’ a wrapped API. The API object responds to several methods (note the dot-notation for making method calls) including x_login and x_active_event. The latter predicate is non-deterministic, which means it effectively becomes a system built-in. It must be stressed that with the exception of assert and println, the whole fragment above can be given model-theoretic semantics. For example, the first constructor call may be interpreted as a unary predicate with the returned API object being a single binding available.

The API wrapping is completely standardised by using three types of parameters. The first parameter as we shall see below is a list of name/value pairs representing the request parameters passed to the web service call. The second parameter represents an XQuery expression to be run against the XML fragment returned by the service. The use of XQuery provides ultimate flexibility in checking conditions and returning exactly the required information from complex data structures returned by the API. The XQuery expression uses a number of simple conventions:

  1. The element <a> represents the top element of the API response.

  2. The v2 prefix denotes the Betfair types namespace: com.betfair.www.publicapi.types.v2.

  3. The results of the query are collected under the '<result>' element with each individual component of the results in a separate child element.

  4. If the XQuery returns multiple results, they become individual bindings in the predicate's extension, so the predicate becomes non-deterministic.
  5. All values returned from the XQuery are placed in a variable number of predicate parameters represented by the rest (tail) Values. For example, {$x/id} binds the variable EventTypeId. In this way, the XQuery expression may generate zero or more alternative sets of bindings corresponding to the condition that has been detected.

Event Detection and Publishing component

This component is responsible for (a) accepting and managing the user subscriptions, (b) managing the detectable events, (b) running regular event detection and response activity, (c) publishing notifications to the users.

The following fragment shows how EDP accepts a user subscription.

rcvMsg(XID,Timestamp,Protocol,Sender,request,subscribe(X)) :- 
        update(detectable(X)),
        assert(subscription(XID,Protocol,Sender,X)).

This is an Event-Condition-Action (ECA) reaction rule with only Event (inbound message) and Action sequence available. This style of ECA rules is called a push reaction rule as the event is actively pushed towards the rulebase. The inbound message has a correlation-id XID, was sent at time equal to Timestamp on Protocol from Sender with the payload matching the pattern subscribe(X). The variable X holds a complex term (record) representing the event pattern that the user is interested in detecting. This rule updates the table detectable holding all detectable event patterns, using the supplied event pattern and stores the subscription parameters in the relation subscription. The same rule can be equivalently written using a generic eca predicate like this:

eca( 
        event( rcvMsg(XID,Timestamp,Protocol,From,request,subscribe(X)) ),
        action( update(detectable(X)), assert(subscription(XID,Protocol,From,X)) )
).

The following fragment shows the top level event detection reaction rule that is activated every second as well as the derivation rule that checks for the event and an action rule that executes the actions. The fragment is somewhat simplified for the purpose of this use case description.

eca( 
         time(every(’1S’)),
         condition( detect(X)) ),
         action( respond(X) ),
         post_condition( cleanup() )
).

detect(X) :-
        detectable(X),
        detect_event(X).

detect_event([X_Api,Inputs,XQuery|Results]) :-
        X_Api(Inputs,XQuery|Results).

respond(Event) :-
        subscription(XID,Protocol,From,Event),
        update(detected(XID)),
        sendMsg(XID,Protocol,UserID,notify,event(Event)).

cleanup() :-
        detected(XID),
        retractall(detected(XID)),
        subscription(XID,Protocol,From,Event),
        retractall(detectable(Event)),
        retractall(subscription(XID|_)),
        sendMsg(XID,Protocol,From,end_of_transmission).

The ECA rule is executed by the rule engine every second. In contrast to a push reaction rule, the event detection in this case uses polling to explicitly detect the event. EDP attempts to detect all detectable event patterns . The web service wrapper predicate is invoked using a second-order logic construct that wraps the actual API call passing all paramaters and accumulaiting the returned data. The returned data is retrieved by a Java call and unified (matched) against the data supplied in the parameters of the subscription. If the unification succeeds, the event is detected and the respond rule retrieves all subscriptions interested in this event and sends a message using the same address and protocol to the user. The post-condition clause clears all event patterns for which the events have been identified and sends a special end_of_transmission message to tell the Client that all notifications have been sent.

Client Frontend component

The following fragment demonstrates how the Client Frontend interacts with the EDP and builds complex event detection on top of the atomic event detection provided by EDP. The market status to be detected first is one not equal to SUSPENDED, then this status should change to ACTIVE.

% Detect a complex event with a market going from !ACTIVE to ACTIVE 
client() :-
        edp(EDP),
        MarketId = 4877225,
        atomic_wait(XID,self,EDP,
                x_market(
                        [marketId(MarketId)],
                        'for $x in $a//market 
                                where $x/marketStatus/text()!="ACTIVE"
                                return <result>{$x/menuPath}{$x/marketStatus/text()}</result>',
                        MenuPath,MarketStatus3
                )
        ),
        atomic_wait(XID,self,EDP,
                x_market(
                        [marketId(MarketId)],
                        'for $x in $a//market 
                                where $x/marketStatus/text()="ACTIVE"
                                return <result>{$x/menuPath}{$x/marketStatus/text()}</result>',
                        MenuPath,MarketStatus4
                )
        ),
        ...

% Generic client-side waiting for atomic events
atomic_wait(XID,Protocol,Sender,EventPattern) :-
        sendMsg(XID,self,Sender,request,subscribe(EventPattern)),
        rcvMsg(XID,self,Sender,notify,event(EventPattern)).

The example shows how the Client Frontend builds a sequencing logic on top of atomic event detection. In this case, the user is interested in detecting the situations when a particular market goes from status not-ACTIVE to ACTIVE. The sendMsg predicates result in the subscribe message being sent to the EDP component. The rcvMsg predicates embed the virtual inline reaction rules directly in the body of the rules. The intended behaviour is for the implementing rule engine to store the current context away while waiting for the matching inbound message without consuming additional execution threads. Once the matching inbound message is received, the rcvMsg literal is satisfied and variables unified in a usual way. In fact, a sendMsg/rcvMsg pair may be compared to a remote version of a normal ‘local’ predicate call.

It must be emphasized that the event detection logic may take different forms including event disjunction, split/joins, timing, and more complex reasoning based, e.g., on Event Calculus.

A more intersting example shows how the Client Frontend builds a braching detection logic allowing her to detect one or more situations when a particular market selection (for example, a golf player) would have long odds (unlikely to win) and then these odds will increase by further 20%. The following (complete) code demonstrates:

        concat(
                [
                        'for $x in $a//marketPrices/runnerPrices/v2:RunnerPrices
                         let $y := $x/bestPricesToBack/v2:Price [1][ ./price>',
                        TargetPrice,
                        '] return <result>{$x/selectionId}{$y/price}</result>'
                ],
                XQ),
        atomic_multiwait(XID,self,EDP,
                x_market_prices(
                        [marketId(MarketId)],
                        XQ,
                        SelectionId,Price1
                )
        ),
        % Wait for the odds to rise by a further factor
        TargetPrice2 = Price1 * 1.2,
        concat(
                [
                        'for $x in $a//marketPrices/runnerPrices/v2:RunnerPrices
                         let $y := $x/bestPricesToBack/v2:Price [1][ ./price > ',
                        TargetPrice2,
                        '] return <result>{$x/selectionId}{$y/price}</result>'
                ],
                XQ2),
        atomic_wait(XID2,self,EDP,
                x_market_prices(
                        [marketId(MarketId)],
                        XQ2,
                        SelectionId,Price2
                )
        ),
        % Complex event detected: the price increased again.
        % The variable SelectionId contains the selection for which the Complex event was detected.
        % The variable Price2 contains the final price at the time the event was detected.
        ...
% Generic client-side waiting for multiple atomic events
atomic_multiwait(XID,Protocol,Sender,EventPattern) :-
        sendMsg(XID,self,Sender,request,subscribe(EventPattern)),
        rcvMult(XID,self,Sender,notify,event(EventPattern)).

The built-in concat predicate is used to construct an XQuery expression with embedded variables used in conditions. The built-in atomic_multiwait allows the Client to wait for one or more notifications (in this case, corresponding to many selections that may satisfy the intital criteria). The wait involved in the atomic_multiwait is automatically discharged by the end_of_transmission message from the EDP once all the notifications have been sent.

The second event detection occurs independently for each selection detected in the first step. In fact, there could be many branches that subscribe to different second atomic events. For each second detection, the Client can execute appropriate actions, such as automatically buying the stock.

8.3. Alternate Sequences

Not described at the moment.

8.3.1. (Title of Alternate Sequence)

Not described at the moment.

9. Narratives

Not described at the moment.

9.1. (Title of Narrative)

Not described at the moment.

10. Commentary

The above real-world use case demonstrates how event detection and publishing logic combining push and pull patterns and involving complex events can be structured by interoperating derivation and reaction rules. The latter provide the necessary glue between interoperating RIF rulebases. The precise nature of the message payload is largely irrelevant for this use case and may involve serialized Java objects, XML, RDF or other formats. The key to the use case is the interplay of the behavioural and inference aspects. Various derivation rules are very useful for detecting and classifying various conditions that can be found in a full realistic prototype. Derivation rules are also useful for deciding on the further protocol steps. In particular, event calculus or Prova-style virtual reactions can be used together with derivation rules to specify interesting complex events and generate the workflow logic based on rules.