Skip to content

Feature tickerplant - #125

Open
ascottDI wants to merge 5 commits into
mainfrom
feature-tickerplant
Open

Feature tickerplant#125
ascottDI wants to merge 5 commits into
mainfrom
feature-tickerplant

Conversation

@ascottDI

Copy link
Copy Markdown
Contributor

di.tickerplant

Ships together with di.tplog. This module depends on the new di.tplog (injected-log init and
1-arg check); its test suite exercises the two against each other, so the two modules should be
reviewed and merged as a pair.

Summary

Adds di.tickerplant, the core tick-capture process for the modular TorQ world: it receives updates
from feeds, stamps them, writes them to a tickerplant log for recovery, and publishes them to
subscribers, rolling the log at end of day. It is the modular replacement for TorQ's
code/processes/tickerplant.q.

It orchestrates three hard dependencies — di.pubsub (subscribe/publish), di.eodtime (roll timing)
and di.tplog (log check/repair) — with an injected logger and timer.

Motivation

TorQ's tickerplant.q hand-rolls the whole capture loop — .z.* handling, the .u publish/subscribe
machinery, log writing and rolling, and end-of-day scheduling — in one process file. The modular
framework already provides those pieces as standalone modules (di.pubsub, di.eodtime, di.tplog,
di.timer), so this extraction re-expresses the tickerplant as an orchestration layer over them:
capture, stamp, log, publish, roll — delegating pub/sub, roll timing and log recovery to the modules
that own them.

Design

Root tables and the upd contract

The captured tables live at root, not in .z.m: a tickerplant owns its tables, feeds insert into
them, and di.pubsub reads them by name, so they cannot be module-local. This is the one deliberate
root-state exception; all other mutable state is module-local. di.torq wires the process's root
upd to tickerplant.upd so feeds publish to it.

Capture modes

  • Batch (default) — upd inserts into the root table; a timer job publishes the accumulated rows
    every batchperiod and clears them.
  • Zero-latencyupd publishes each update immediately and does not buffer.

Both modes stamp the update (prepending a data timestamp unless one is already present) and log every
message.

End of day

The roll fires when the current time passes di.eodtime's next roll timestamp, checked on every upd
and every timer tick. endofday flushes the buffer, notifies subscribers, rolls the log to the next
day, and refreshes the roll time and data-timestamp offset from di.eodtime.

Use of di.tplog

di.tplog is used only for check/repair on recovery: when openlog finds a pre-existing log it runs
it through tplog.check, repairing a corrupt one. The tickerplant opens for append and rolls the
log itself, rather than using di.tplog's open/roll, because those replay the log through upd
which a tickerplant must not do to its own log. (This module was updated to the new di.tplog
contract: it now calls tplog.init during its own init, and tplog.check is 1-arg.)

No di.handlers dependency

Subscriber-disconnect cleanup is handled by di.pubsub's own .z.pc, so this module takes no handler
dependency. di.pubsub should migrate to di.handlers so .z.* is not assigned outside the central
registry — tracked separately, out of scope here.

Dependencies

Dependency Kind Description
di.pubsub hard (use) subscribe / publish / roll notifications
di.eodtime hard (use) trading date, roll scheduling, data-timestamp offset
di.tplog hard (use) log check/repair on recovery
log injected `info`warn`error dict of {[ctx;msg]} functions
timer injected di.timer's exports (must expose addjob)

Hard deps are declared in deps.q; the injected log and timer are validated by di.depcheck's
core-contract check, not declared there. init validates every dependency strictly and signals
immediately if any is missing or malformed.

Public API

Function Signature Description
init [deps] Wire log + timer, init the dep modules, materialise the schemas as root tables (`g# on sym), open today's log, and schedule the batch/roll timer job. Idempotent.
upd [table;data] Feed entry point: stamp, then buffer+log (batch) or publish+log (zero-latency).
subscribe [tables;filters] Register a subscriber (delegates to di.pubsub).
endofday [] Flush, notify subscribers, roll the log, advance the end-of-day state.
getcounts [] `i`j`d — messages published, messages logged, trading date.
gettables [] The tables this tickerplant captures.
version Module version ("0.1.0").

upd validates its arguments and routes failures through a log-then-signal helper. getapimeta[]
exposes the callable API for central registration with di.api; the framework plumbing (init,
getapimeta, version) is intentionally excluded.

init also accepts optional config keys: batch (1b), batchperiod (timespan), logdir (string,
"" disables logging), logname (prefix, default "tp"), subtables (symbol list), and the
di.eodtime keys (rolltimezone / datatimezone / rolltimeoffset) forwarded verbatim.

Testing

test.csv / test.q (k4unit), 18 checks, run against the real di.pubsub, di.eodtime,
di.tplog and di.timer — no dependencies are mocked. The timer is used without init (so no live
.z.ts; its job is exercised through endofday), and a capturing logger is shared across the modules
so their output is assertable.

Coverage: the metadata/version contract; strict init dependency validation (a fail row per guard);
init materialising the root tables and scheduling the timer job; batch and zero-latency upd;
endofday flushing and rolling; upd input validation; and the two di.tplog integration points — a
tickerplant-written log replaying through di.tplog, and rolling into a corrupt log repairing it via
tplog.check.

k4unit:use`di.k4unit
k4unit.moduletest`di.tickerplant

Because two tests replay/repair through di.tplog, the suite passes once di.tplog and
di.tickerplant are present together (as they merge) — it is not runnable against an older di.tplog.

Files

di/tickerplant/init.q          entry point, version read, export list
di/tickerplant/tickerplant.q   implementation
di/tickerplant/tickerplant.md  module documentation
di/tickerplant/VERSION         module version (single source of truth)
di/tickerplant/deps.q          dependency manifest (di.pubsub, di.eodtime, di.tplog)
di/tickerplant/test.csv        k4unit tests (18)
di/tickerplant/test.q          test fixtures and helpers

The module version lives in a plain-text VERSION file, read in init.q (version:trim first read0\:::VERSION) and exported for di.depcheck, matching the convention used by di.servers, di.clienttrackinganddi.tplog`.

Comment thread di/tickerplant/tickerplant.q
Comment thread di/tickerplant/tickerplant.q
Comment thread di/tickerplant/tickerplant.q
@DI-Software-Engineering

Copy link
Copy Markdown

DIReview Summary

1 critical | 2 warning(s) | 0 suggestion(s)

⚠️ Spec check skipped — tracker lookup failed (NO_REF_FOUND). Standards axis only.

Comment thread di/tickerplant/tickerplant.q
Comment thread di/tickerplant/tickerplant.q
Comment thread di/tickerplant/test.q
@DI-Software-Engineering

Copy link
Copy Markdown

DIReview Summary

0 critical | 3 warning(s) | 0 suggestion(s)

⚠️ Spec check skipped — tracker lookup failed (NO_REF_FOUND). Standards axis only.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants