clara.rules.durability

Support for persisting Clara sessions to an external store. Provides the ability to store and restore an entire session working memory state. The restored session is able to have additional insert, retract, query, and fire rule calls performed immediately after.

See https://github.com/cerner/clara-rules/issues/198 for more discussion on this.

Note! This is still an EXPERIMENTAL namespace. This may change non-passively without warning. Any session or rulebase serialized in one version of Clara is not guaranteed to deserialize successfully against another version of Clara.

add-accumulator

(add-accumulator node)

add-alpha-fn

(add-alpha-fn node)

add-join-filter-fn

(add-join-filter-fn node)

add-rhs-fn

(add-rhs-fn node)

add-test-fn

(add-test-fn node)

assemble-restored-session

(assemble-restored-session rulebase opts)(assemble-restored-session rulebase memory opts)

Builds a Clara session from the given rulebase and memory components. When no memory is given a new one is created with all of the defaults of eng/local-memory. Note! This function should not typically be used. It is left public to assist in ISessionSerializer durability implementations. Use clara.rules/mk-session typically to make rule sessions.

If the options are not provided, they will default to the Clara session defaults. The available options on the session (as opposed to the rulebase) are the transport and listeners.

Note! Currently this only supports the clara.rules.memory.PersistentLocalMemory implementation of memory.

cache-node

(cache-node node)

Cache the node in the node-id->node-cache. Returns the node.

clj-struct->idx

(clj-struct->idx fact)

Gets the numeric index for the given struct from the clj-struct-holder.

clj-struct-holder

A cache for writing and reading Clojure records. At write time, an IdentityHashMap can be used to keep track of repeated references to the same object instance occurring in the serialization stream. At read time, a plain ArrayList (mutable and indexed for speed) can be used to add records to when they are first seen, then look up repeated occurrences of references to the same record instance later.

clj-struct-holder-add-fact-idx!

(clj-struct-holder-add-fact-idx! fact)

Adds the fact to the clj-struct-holder with a new index. This can later be retrieved with clj-struct->idx.

clj-struct-holder-add-obj!

(clj-struct-holder-add-obj! fact)

The reverse of clj-struct-holder-add-fact-idx!. Adds the object to the clj-struct-holder at the next available index.

clj-struct-idx->obj

(clj-struct-idx->obj id)

The reverse of clj-struct->idx. Returns an object for the given index found in clj-struct-holder.

create-map-entry

(create-map-entry k v)

Helper to create map entries. This can be useful for serialization implementations on clojure.lang.MapEntry types. Using the ctor instead of clojure.lang.MapEntry/create since this method doesn’t exist prior to clj 1.8.0

deserialize-rulebase

(deserialize-rulebase session-serializer)(deserialize-rulebase session-serializer opts)

Inputs: ([session-serializer :- (s/protocol ISessionSerializer)] [session-serializer :- (s/protocol ISessionSerializer) opts :- {s/Any s/Any}]) Returns: Rulebase

Deserializes the rulebase stored via the serialize-rulebase function. This is done via the given session-serializer implementor of ISessionSerializer.

Options can be given as an optional argument. These are passed through to the session-serializer implementation. See the description of standard options an ISessionSerializer should provide in the ISessionSerializer docs. Also, see the specific ISessionSerializer implementation docs for any non-standard options supported/not supported. See ISessionSerializer docs for more on that.

deserialize-session-state

(deserialize-session-state session-serializer memory-facts-serializer)(deserialize-session-state session-serializer memory-facts-serializer opts)

Inputs: ([session-serializer :- (s/protocol ISessionSerializer) memory-facts-serializer :- (s/protocol IWorkingMemorySerializer)] [session-serializer :- (s/protocol ISessionSerializer) memory-facts-serializer :- (s/protocol IWorkingMemorySerializer) opts :- {s/Any s/Any}]) Returns: (s/protocol eng/ISession)

Deserializes the session that was stored via the serialize-session-state function. Similar to what is described there, this uses the session-serializer implementor of ISessionSerializer to deserialize the session and working memory state. The memory-facts-serializer implementor of IWorkingMemorySerializer is used to deserialize the actual facts stored in working memory.

Options can be given as an optional argument. These are passed through to the session-serializer implementation. See the description of standard options an ISessionSerializer should provide in the ISessionSerializer docs. Also, see the specific ISessionSerializer implementation docs for any non-standard options supported/not supported.

find-index

(find-index fact->idx-map fact)

Finds the fact in the fact->idx-map. The fact is assumed to be a key. Returns the value for that key, which should just be a numeric index used to track where facts are stubbed out with MemIdx’s in working memory so that they can be ‘put back’ later.

find-internal-idx

(find-internal-idx idx)

Finds the fact from mem-internal at the given index. See docs on mem-internal for more.

find-mem-idx

(find-mem-idx idx)

Finds the fact from mem-facts at the given index. See docs on mem-facts for more.

index-accum-memory

(index-accum-memory seen accum-mem)

index-activation-map

(index-activation-map internal-seen seen actmap)

index-alpha-memory

(index-alpha-memory internal-seen seen amem)

index-beta-memory

(index-beta-memory internal-seen seen bmem)

index-production-memory

(index-production-memory internal-seen seen pmem)

indexed-session-memory-state

(indexed-session-memory-state memory)

Takes the working memory from a session and strips it down to only the memory needed for serialization. Along with this, replaces all working memory facts with MemIdx place holders. The terminology being used here is to call this step ‘indexing’ the memory.

A map is returned with two keys: * :memory - The working memory representation that is the same as the given memory’s :memory, however, all facts in the memory are replaced with MemIdx placeholders. * :indexed-facts - the facts replaced with MemIdx placeholders. The facts are returned in a sequential collection. Each fact is the n’th item of the collection if the MemIdx for that fact has :idx = n. No facts returned should be identical? (i.e. multiple references to the same object instance). However, it is possible for some facts returned to be aggregations containing other facts that do appear elsewhere in the fact sequence. It is up to the implementation of the IWorkingMemorySerializer to deal with these possible, identical? object references correctly. This is generally true for most serialization mechanisms.

Note! This function should not typically be used. It is left public to assist in ISessionSerializer durability implementations. Use clara.rules/mk-session typically to make rule sessions.

Note! Currently this only supports the clara.rules.memory.PersistentLocalMemory implementation of memory.

ISessionSerializer

protocol

Provides the ability to serialize and deserialize a session. Options can be given and supported via the opts argument to both serialize and deserialize. Certain options are expected and required to be supported by any implementation of ISessionSerializer. These are referred to as the ‘standard’ options.

These include:

  • :rulebase-only? - When true indicates the rulebase is the only part of the session to serializer. The default is false for the serialize-session-state function. It is defaulted to true for the serialize-rulebase convenience function. This is useful for when many sessions are to be serialized, but all having a common rulebase. Storing the rulebase only, will likely save both space and time in these scenarios.

  • :with-rulebase? - When true the rulebase is included in the serialized state of the session.
    The default behavior is false when serializing a session via the serialize-session-state function.

  • :base-rulebase - A rulebase to attach to the session being deserialized. The assumption here is that the session was serialized without the rulebase, i.e. :with-rulebase? = false, so it needs a rulebase to be ‘attached’ back onto it to be usable.

  • :forms-per-eval - The maximum number of expressions that will be evaluated per call to eval. Larger batch sizes should see better performance compared to smaller batch sizes. Defaults to 5000, see clara.rules.compiler/forms-per-eval-default for more information.

Options for the rulebase semantics that are documented at clara.rules/mk-session include:

  • :fact-type-fn
  • :ancestors-fn
  • :activation-group-sort-fn
  • :activation-group-fn

Other options can be supported by specific implementors of ISessionSerializer.

members

deserialize

(deserialize this mem-facts opts)

Deserialize the session state associated to this instance e.g. it may be coming from a known reference to an IO stream. mem-facts is a sequential collection of the working memory facts that were serialized and deserialized by an implementation of IWorkingMemorySerializer.

serialize

(serialize this session opts)

Serialize the given session with the given options. Where the session state is stored is dependent on the implementation of this instance e.g. it may store it in a known reference to an IO stream.

IWorkingMemorySerializer

protocol

Provides the ability to serialize and deserialize the facts stored in the working memory of a session. Facts can be serialized in whatever way makes sense for a given domain. The domain of facts can vary greatly from one use-case of the rules engine to the next. So the mechanism of serializing the facts in memory can vary greatly as a result of this. Clara does not yet provide any default implementations for this, but may in the future. However, many of the handlers defined in clara.rules.durability.fressian can be reused if the consumer wishes to serialize via Fressian. See more on this in the clara.rules.durability.fressian namespace docs.

The important part of this serialization protocol is that the facts returned from deserialize-facts are in the same order as how they were given to serialize-facts.

members

deserialize-facts

(deserialize-facts this)

Returns the facts associated to this instance deserialized in the same order that they were given to serialize-facts.

serialize-facts

(serialize-facts this fact-seq)

Serialize the given fact-seq, which is an order sequence of facts from working memory of a session.
Note, as mentioned in the protocol docs, the order these are given is important and should be preserved when they are returned via deserialize-facts.

mem-facts

Useful for ISessionSerializer implementors to have a reference to the facts deserialized via IWorkingMemorySerializer that are needed to restore working memory whose locations were stubbed with a MemIdx during serialization.

mem-internal

Useful for ISessionSerializer implementors to have a reference to the facts deserialized via IWorkingMemorySerializer that are needed to restore working memory whose locations were stubbed with a InternalMemIdx during serialization. These objects are specific to the Clare engine, and as such will be serialized and deserialized along with the memory.

node-fn-cache

A cache for holding the fns used to reconstruct the nodes. Only applicable during read time, specifically this will be bound to a Map of [ ] to IFn before the rulebase is deserialized. While the rulebase is deserialized the nodes will reference this cache to repopulate their fns.

node-id->node

(node-id->node node-id)

Lookup the node for the given node-id in the node-id->node-cache cache.

node-id->node-cache

Useful for caching rulebase network nodes by id during serialization and deserialization to avoid creating multiple object instances for the same node.

opts->get-alphas-fn

(opts->get-alphas-fn rulebase opts)

rulebase->rulebase-with-opts

(rulebase->rulebase-with-opts without-opts-rulebase opts)

Intended for use in rulebase deserialization implementations where these functions were stripped off the rulebase implementation; this function takes these options and wraps them in the same manner as clara.rules/mk-session. This function should typically only be used when implementing ISessionSerializer.

seq->sorted-map

(seq->sorted-map s c)

Helper to create a sorted map from a seq given an optional comparator.

seq->sorted-set

(seq->sorted-set s c)

Helper to create a sorted set from a seq given an optional comparator.

serialize-rulebase

(serialize-rulebase session session-serializer)(serialize-rulebase session session-serializer opts)

Inputs: ([session :- (s/protocol eng/ISession) session-serializer :- (s/protocol ISessionSerializer)] [session :- (s/protocol eng/ISession) session-serializer :- (s/protocol ISessionSerializer) opts :- {s/Any s/Any}])

Serialize only the rulebase portion of the given session. The serialization is done by the given session-serializer implementor of ISessionSerializer.

Options can be given as an optional argument. These are passed through to the session-serializer implementation. See the description of standard options an ISessionSerializer should provide in the ISessionSerializer docs. Also, see the specific ISessionSerializer implementation docs for any non-standard options supported/not supported. See ISessionSerializer docs for more on that.

The rulebase is the stateless structure that controls the flow of productions, i.e. the ‘rete’ rule network. The ability to serialize only the rulebase is supported so that the rulebase can be stored and retrieved a single time for potentially many sessions containing different working memory data, for the same rules. This function is only a convenience for passing the :rulebase-only? true flag to the serialize-session-state function. See serialize-session-state for more.

serialize-session-state

(serialize-session-state session session-serializer memory-facts-serializer)(serialize-session-state session session-serializer memory-facts-serializer opts)

Inputs: ([session :- (s/protocol eng/ISession) session-serializer :- (s/protocol ISessionSerializer) memory-facts-serializer :- (s/protocol IWorkingMemorySerializer)] [session :- (s/protocol eng/ISession) session-serializer :- (s/protocol ISessionSerializer) memory-facts-serializer :- (s/protocol IWorkingMemorySerializer) opts :- {s/Any s/Any}])

Serializes the state of the given session. By default, this excludes the rulebase from being serialized alongside the working memory state of the session. The rulebase, if specified, and the working memory of the session are serialized by the session-serializer implementor of ISessionSerializer. The memory-serializer implementor of IWorkingMemorySerializer is used to serialize the actual facts stored within working memory.

Typically, the caller can use a pre-defined default session-serializer, such as clara.rules.durability.fressian/create-session-serializer.
See clara.rules.durability.fressian for more specific details regarding this, including the extra required dependency on Fressian notes found there. The memory-facts-serializer is often a custom provided implemenation since the facts stored in working memory are domain specific to the consumers’ usage of the rules. See the IWorkingMemorySerializer docs for more.

Options can be given as an optional argument. These are passed through to the session-serializer implementation. See the description of standard options an ISessionSerializer should provide in the ISessionSerializer docs. Also, see the specific ISessionSerializer implementation docs for any non-standard options supported/not supported.

sorted-comparator-name

(sorted-comparator-name s)

Sorted collections are not easily serializable since they have an opaque function object instance associated with them. To deal with that, the sorted collection can provide a ::comparator-name in the metadata that indicates a symbolic name for the function used as the comparator. With this name the function can be looked up and associated to the sorted collection again during deserialization time. * If the sorted collection has metadata ::comparator-name, then the value should be a name symbol and is returned.
* If the sorted collection has the clojure.lang.RT/DEFAULT_COMPARATOR, returns nil. * If neither of the above are true, an exception is thrown indicating that there is no way to provide a useful name for this sorted collection, so it won’t be able to be serialized.