Event System¶
GObjects communicate only with events that carry a JSON key-value payload
(kw). There is no direct method call. Every interaction goes through the
event dispatcher of the finite state machine.
Source code: src/gobj.js,
src/command_parser.js,
src/stats_parser.js
gobj_send_event()¶
Sends an event to dst and runs the action of the current state immediately.
gobj_send_event(dst, event, kw, src)Parameters
| Key | Type | Description |
|---|---|---|
dst | GObj | The destination gobj. |
event | string | The event name. The GClass must declare it in the state that is active. |
kw | object | The JSON payload of the event. |
src | GObj | The gobj that sends the event. |
Returns
The value that the action function returns. It returns -1 when the event is
not defined in the current state.
Notes
Delivery is synchronous. When the call returns, the action ran to the end,
together with every cascade that the action started. To send an event that must
run after the current action returns, use gobj_post_event().
An event that the current state does not declare is an error, and the framework logs it. Do not add an empty action to make the message quiet. The message shows a bad state machine, or a sender that emits in the wrong situation.
gobj_post_event()¶
Puts an event in a queue for delivery on the next turn of the browser task
queue. It is gobj_send_event() with the delivery
delayed.
gobj_post_event(dst, event, kw, src)Parameters
| Key | Type | Description |
|---|---|---|
dst | GObj | The destination gobj. |
event | string | The event name. The GClass of dst must declare it. |
kw | object | The JSON payload of the event. |
src | GObj | The gobj that posts the message. |
Returns
Returns 0 when the message goes into the queue. Returns -1 when the
framework refuses it, and logs the cause: dst is not a gobj, dst is under
destruction, the event name is empty, the GClass does not declare the event, or
the queue holds MAX_POSTED_EVENTS (10000) messages already. The queue is not
a work queue, and the limit protects that rule.
Notes
Use it to leave the stack that you stand on. gobj_publish_event()
dispatches synchronously, so the action of a subscriber runs inside the stack of
the publisher. To destroy or to stop that publisher there dismantles what is
still in an iteration. Post the event instead, and do the work on the next turn.
The queue drains with setTimeout(…, 0), which is a macrotask. It does not
drain with queueMicrotask(). A microtask runs before the browser paints or
handles an input, so a chain of posted events holds the page. A macrotask gives
the browser its turn between one event and the next.
Delivery is a snapshot per turn. The messages that are in the queue when a drain begins are the messages that the drain delivers. An event that an action posts while the drain runs waits for the next turn. A chain of messages that each post the next one advances one step per turn, and the browser keeps its turns.
gobj_destroy() takes the gobj out of the
queue, and the two halves are different. As destination the framework drops
the message. As source the framework only clears the pointer, because the
destination still wants its event. That event arrives with src set to null,
which every action must accept.
Do not use a C_TIMER of one millisecond for this. A deferral is not a
time. Written as a time it costs a timer, a child gobj with its own start and
stop, and the name of the event: every continuation arrives as EV_TIMEOUT, so
the machine trace says “timeout” instead of what occurs. Use a timer when
there is a real time to measure: a schedule, an inactivity window, or a backoff.
The C function takes three parameters, because there the gobj that posts is also the destination and the source. The JS function takes four, and the destination and the source are independent.
gobj_posted_events_size()¶
Gives the quantity of posted events that wait for delivery.
gobj_posted_events_size()Returns
The quantity of messages in the queue, as a number.
Notes
Use it in a test to show that a queue is empty, or in a diagnostic. Application code must not make a decision from this value, because the value changes on every turn of the browser task queue.
gobj_deliver_posted_events()¶
Delivers the messages that are in the queue. One turn, one snapshot.
gobj_deliver_posted_events()Returns
The quantity of messages that the function delivered. It does not count the messages of a gobj that went into destruction after the message went into the queue.
Notes
gobj_post_event() schedules this function automatically, so application code
does not call it. Call it in a test, to deliver a queue immediately and to
keep the test synchronous.
The function takes a snapshot of the queue, and it replaces the queue with an empty one before the first delivery. If the actions post new messages, the function schedules one more turn.
gobj_publish_event()¶
Sends an event to every gobj that has a subscription to it.
gobj_publish_event(publisher, event, kw)Parameters
| Key | Type | Description |
|---|---|---|
publisher | GObj | The gobj that publishes the event. |
event | string | The event name. The GClass must declare it as an output event. |
kw | object | The JSON payload of the event. |
Returns
The sum of the values that the actions of the subscribers returned. It is not
the quantity of subscribers. To count the subscribers, use
gobj_find_subscriptions().
Notes
Dispatch is synchronous, and it goes to one subscriber after the other.
Never stop or destroy the tree of the publisher inside the action of a
subscriber. Use gobj_post_event(), or set a flag and do
the work from a timeout action.
When a subscriber is optional, mark the event with EVF_NO_WARN_SUBS in the
event table. If you do not, the framework logs “Publish event WITHOUT
subscribers” on every call.
gobj_subscribe_event()¶
Makes a subscription of subscriber to an event of publisher.
gobj_subscribe_event(publisher, event, kw, subscriber)Parameters
| Key | Type | Description |
|---|---|---|
publisher | GObj | The gobj that publishes. |
event | string | The event name. Use null to subscribe to every output event. |
kw | object | The filter and the configuration of the subscription. Use {} to accept every payload. |
subscriber | GObj | The gobj that receives the event. |
Returns
The subscription, as a JSON object.
Notes
A partial object in kw subscribes only to the events with a payload that
matches those keys.
The kw accepts four configuration keys: __config__, __global__,
__local__ and __filter__. See Subscription options.
Each GClass takes one of two subscription models, and writes the block in
mt_create. A child gobj uses its parent when the subscriber
attribute is empty. A service gobj subscribes only when the attribute holds
a gobj.
gobj_unsubscribe_event()¶
Deletes a subscription.
gobj_unsubscribe_event(publisher, event, kw, subscriber)Parameters
| Key | Type | Description |
|---|---|---|
publisher | GObj | The gobj that publishes. |
event | string | The event name of the subscription. |
kw | object | The filter that the subscription used. |
subscriber | GObj | The gobj that receives the event. |
Returns
Returns 0 on success, or -1 when there is no subscription that matches.
gobj_unsubscribe_list()¶
Deletes every subscription of a list.
gobj_unsubscribe_list(gobj, dl_subs, force)Parameters
| Key | Type | Description |
|---|---|---|
gobj | GObj | The gobj that owns the operation. |
dl_subs | array | The list of subscriptions, from gobj_find_subscriptions(). |
force | boolean | When it is true, the function also deletes the hard subscriptions. |
Returns
Returns 0.
gobj_find_subscriptions()¶
Finds the subscriptions that a publisher holds.
gobj_find_subscriptions(publisher, event, kw, subscriber)Parameters
| Key | Type | Description |
|---|---|---|
publisher | GObj | The gobj that publishes. |
event | string | The event name to match. Use null to match every event. |
kw | object | The filter to match. Use {} to match every subscription. |
subscriber | GObj | The subscriber to match. Use null to match every subscriber. |
Returns
A list of the subscriptions that match.
gobj_find_subscribings()¶
Finds the subscriptions that a subscriber holds. It is the opposite direction of
gobj_find_subscriptions().
gobj_find_subscribings(subscriber, event, kw, publisher)Parameters
| Key | Type | Description |
|---|---|---|
subscriber | GObj | The gobj that receives the events. |
event | string | The event name to match. Use null to match every event. |
kw | object | The filter to match. |
publisher | GObj | The publisher to match. Use null to match every publisher. |
Returns
A list of the subscriptions that match.
gobj_list_subscriptions()¶
Gives the subscriptions of a gobj in a form that a human reads.
gobj_list_subscriptions(gobj2view)Parameters
| Key | Type | Description |
|---|---|---|
gobj2view | GObj | The gobj to examine. |
Returns
A list of JSON objects. Each object names the publisher, the subscriber and the event.
Subscription options¶
The kw of gobj_subscribe_event() accepts four
keys that change the delivery. Every other key is a filter on the payload.
| Key | Description |
|---|---|
__config__ | The options of the subscription. Put the two booleans below inside this object. |
__config__.__hard_subscription__ | Keeps the subscription when a stop deletes the others. |
__config__.__own_event__ | Stops the publication when the action of this subscriber returns a negative value, and gives that value to the publisher. The subscriber owns the event. |
__global__ | A JSON object that the framework adds to the payload delivered to this subscriber. |
__local__ | A JSON object. The framework removes its keys from the payload delivered to this subscriber. The values are not used. |
__filter__ | A JSON object that the payload must match. The framework does not deliver the event when the payload does not match. |
Which payload a subscriber gets. Since gobj-js 7.25.8 the rule is the
same as in the C runtime (gobj_publish_event()):
A subscription with a non-empty
__global__or__local__gets a twin of the payload: a new top-level object, with the nested values shared.__global__goes in as a copy. The keys that one subscription adds or removes reach only its own subscriber.Every other subscriber gets the same object as the publisher. A subscriber that changes the payload it got must change a copy of its own.
C_IEVENT_CLIdoes this before it writes its ievent stack.__filter__andmt_publication_filtersee the payload of the publisher, not the payload of an earlier subscription.
Up to gobj-js 7.25.7 every subscriber got the same object, and __global__
and __local__ changed it. So one subscription changed the payload of every
subscriber after it, and of the publisher.
gobj_subscribe_event(publisher, "EV_X", {__global__: {tag: "a"}}, subscriber_a);
gobj_subscribe_event(publisher, "EV_X", {__local__: {secret: 0}}, subscriber_b);
gobj_subscribe_event(publisher, "EV_X", {__filter__: {v: 1}}, subscriber_c);
gobj_publish_event(publisher, "EV_X", {v: 1, secret: "s"});
// subscriber_a gets {v: 1, secret: "s", tag: "a"}
// subscriber_b gets {v: 1}
// subscriber_c gets {v: 1, secret: "s"}, the object of the publisher
// the object of the publisher stays {v: 1, secret: "s"}Commands and stats¶
gobj_command()¶
Runs a command of a gobj.
gobj_command(gobj, command, kw, src)Parameters
| Key | Type | Description |
|---|---|---|
gobj | GObj | The gobj that holds the command. |
command | string | The command name, as the command table declares it. |
kw | object | The parameters of the command. |
src | GObj | The gobj that asks for the command. |
Returns
The response, as a JSON object with the keys result, comment, schema and
data. Build it with build_command_response().
Notes
The command goes to the gclass’s own mt_command_parser method when it has
one, and else, when the gclass has a command table (SDATACM), to the global
parser of gobj_start_up(). A gclass with
neither answers -1 “<gobj>: command table not available”. See
Commands and statistics.
For a yuno of C_YUNO (as gui_agent and gui_treedb create it), whose
mt_command_parser answers get-global-trace:
let r = gobj_command(gobj_yuno(), "get-global-trace", {}, gobj);
// r: {result: 0, comment: "", schema: {}, data: ["machine"]} (the global levels that are set)gobj_stats()¶
Reads the statistics of a gobj.
gobj_stats(gobj, stats, kw, src)Parameters
| Key | Type | Description |
|---|---|---|
gobj | GObj | The gobj to examine. |
stats | string | The name of the statistic. An empty string asks for every statistic. |
kw | object | The options of the operation. |
src | GObj | The gobj that asks. |
Returns
The response, as a JSON object. Build it with
build_stats_response().
command_parser()¶
An empty stub, exported to fill the global_command_parser_fn slot of
gobj_start_up(). It reads no command table,
types no parameter and returns undefined: it is NOT a parser of commands as
the C kernel’s command_parser() is. A gclass that answers
its commands gives its own mt_command_parser method (see
Commands and statistics).
command_parser(gobj, command, kw, src)Returns
undefined.
gobj_command(gobj, "help", {}, src);
// a gclass with a command table and no mt_command_parser, started with
// command_parser as global_command_parser_fn: undefined, the command did nothingstats_parser()¶
An empty stub, exported to fill the global_stats_parser_fn slot of
gobj_start_up(). It reads no statistic and
returns undefined. gobj_stats() asks the gclass’s own
mt_stats method first, and this global parser only for a gclass without
one; with no global parser it answers -1 “<gobj>, stats parser not
available”.
stats_parser(gobj, stats, kw, src)Returns
undefined.
gobj_stats(gobj, "", {}, src);
// a gclass with no mt_stats, started with stats_parser as global_stats_parser_fn: undefinedbuild_command_response()¶
Builds the JSON response of a command.
build_command_response(gobj, result, comment, schema, data)Parameters
| Key | Type | Description |
|---|---|---|
gobj | GObj | The gobj that answers. |
result | number | 0 on success, a negative number on failure. |
comment | string | A message for the operator. |
schema | object | The description of the columns of data. Use null when there is none. |
data | object | The payload of the response. |
Returns
A JSON object with the four keys.
build_stats_response()¶
Builds the JSON response of a statistics request. It takes the same parameters
as build_command_response().
build_stats_response(gobj, result, comment, schema, data)Returns
A JSON object with the four keys.