Updating facts

When a new collection is created or the definition is modifed (by the addition of facts for instance), the Reporting plugin will rebuild the entire collection.

If there is no current row (a current set of facts) for an object, one will be created. If there is a row and the new row would be identical to the existing one, then no update will occur.

Getting facts

Whenever the Reporting plugin needs to update or get facts for an object, it calls services to allow one or more plugins to calculate the facts.

  • "std:reporting:collection:*:get_facts_for_object", a wildcard service called for all collections
  • "std:reporting:collection:COLLECTION_NAME:get_facts_for_object", where COLLECTION_NAME is the collection name
  • "std:reporting:collection_category:CATEGORY:get_facts_for_object", for each of the collection categories as CATEGORY

The services are called with three arguments,

  • object, the StoreObject of the object who’s facts are being updated,
  • row, a database row object. Your service implementation should set the current values for its facts in the row
  • collection, the Collection object

The collection object is included for wildcard and category services to access properties of the collection, and is generally omitted from service implementations.

Multiple plugins can implement the get_facts_for_object service for a collection, but shouldn’t set any facts for which they do not themselves define.

For example, a very simple get_facts_for_object that gets one fact:

P.implementService("std:reporting:collection:books:get_facts_for_object",
    function(object, row) { // omit the final collection argument
        row.title = object.title;
    }
);

After the last get_facts_for_object for the collection is called, the row is committed and the facts stored in the Database.

Collection update rules

If a fact is dependent on the inclusion of the Object as an attribute in another object, it is possible to specify this relationship and trigger an update and get_facts_for_object

This is done with the std:reporting:gather_collection_update_rules service, which has one argument, the rule() function.

rule() takes three arguments, the collection name, the Type that influences our object as defined in the schema requirements, and the specific Attribute that we are monitoring (also defined in the schema requirements).

For example, using the example of a Library, we may have an attribute on a Book that specifies a person is currently loaning the book. If we have a “people” collection that has a fact for how many books are currently being loaned, we would need to update this number for our person when they are added to the LoanedBy attribute on the Book object:

P.implementService("std:reporting:gather_collection_update_rules", function(rule) {
    rule("people", T.Book, A.LoanedBy);
});

Whenever the LoanedBy attribute is changed, the Reporting plugin will run get_facts_for_object for any object that is removed or added to the attribute.

Invalidating facts

Whenever an action is taken that can change the value of any of the facts in the collection for the object, that row must be invalidated and new facts collected.

Any updates/saves to the Object will automatically force an update for the object being changed in all of the collections it is a member of. Likewise any changes to attributes that are covered in the gather_collection_update_rules will force an update.

For other cases, for instance where the data is dependent on something in a plugin database, the Reporting plugin implements a service named std:reporting:update_required which takes two arguments: the name of the collection and an array of Ref’s that may have updated facts and thus need updating.

For example:

O.service("std:reporting:update_required", "books", [book.ref]);