78: Make JournalService a Hub-managed Nenjim process and integrate it into startup

This commit is contained in:
2026-09-02 16:46:51 +02:00
parent f5fc5bb3b5
commit 7b1f6d18eb
19 changed files with 858 additions and 254 deletions
+31 -20
View File
@@ -20,8 +20,9 @@
<main>
<h1>Nenjim</h1>
<p class="status"><strong>Implementation status:</strong> Journal format version 1, the immutable Java model,
internal strict parser, read-only <code>JournalService</code>, explicitly refreshed lifecycle
<code>JournalServiceManager</code>, and the first central component Registry are implemented. Contexts,
internal strict parser, read-only <code>JournalService</code> with a Hub-managed process implementation,
passive explicitly refreshed <code>JournalServiceManager</code>, and the first central component Registry
are implemented. Contexts,
resolution, classloading, discovery, runtime loading/removal, downloading, publishing, synchronization,
watching, signatures, permissions, and license filtering remain future work.</p>
@@ -96,20 +97,26 @@ PREFERRED=nenjim:com_r35157_nenjim-hubd-api=1.0.3:'Built together'</code></pre>
semantically inconsistent content fails with source name, one-based line number, and a reason. Validation is
complete before service state changes. Returned objects and collections are immutable and defensively copied.</p>
<h2>Service, ServiceManager, packages, and disk layout</h2>
<h2>Service, process, ServiceManager, packages, and disk layout</h2>
<p>A <code>Service</code> is the public domain API used by applications and other services during ordinary
operation. <code>JournalService</code> is therefore filesystem-independent and read-only: it exposes current
and historical Journal queries without lifecycle, paths, refresh, parser, or mutation operations.</p>
<p>A <code>ServiceManager</code> is the lifecycle and administrative API owned by a composition/lifecycle owner.
<code>JournalServiceManager</code> starts and stops the Journal service, reports its normalized data root,
performs explicit refresh, and exposes <code>JournalService</code> only after complete successful initial
loading. Its reference implementation reads UTF-8 runtime files chronologically and validates directory and
filename placement. It creates, overwrites, and deletes nothing.</p>
<p><code>JournalServiceImpl</code> keeps exact-text SHA-256 identity, chain state, idempotency, conflicts, forks,
and atomic ingestion internal. The public package contains only the two central interfaces; composed models,
value types, and exceptions live under <code>.model</code>, <code>.valuetypes</code>, and
<code>.exception</code>, while parser, ingestion, chain state, and filesystem loading live under
<code>.impl.ref</code> without leaking through public signatures.</p>
operation. <code>JournalService</code> is a registrable component but remains filesystem-independent and
read-only: it exposes current and historical Journal queries without lifecycle, paths, refresh, parser, or
mutation operations. Queries become available only after successful Journal process startup.</p>
<p>The Hub constructs one Journal object exposed as both <code>JournalService</code> and
<code>NenjimProcess</code>, plus one distinct passive <code>JournalServiceManager</code>. The manager reports
the normalized data root and performs explicit refresh; it has no start, stop, service accessor, component
identity, or process lifecycle. It delegates through a package-private administration view that ordinary
service consumers cannot name or derive.</p>
<p>The Journal process reads UTF-8 runtime files chronologically and validates directory and filename placement.
Its complete initial worldview is published only after every runtime file succeeds; failed startup leaves
queries unavailable and cannot be retried on the same instance. Later refresh remains explicit, idempotent,
and atomic per ingestion. Neither startup nor refresh creates, overwrites, or deletes Journal files.</p>
<p>The package-private <code>JournalServiceImpl</code> keeps exact-text SHA-256 identity, chain state,
idempotency, conflicts, forks, and ingestion internal. The public package contains only the two central
interfaces; composed models, value types, and exceptions live under <code>.model</code>,
<code>.valuetypes</code>, and <code>.exception</code>, while parser, ingestion, chain state, filesystem
loading, and the admin boundary live under <code>.impl.ref</code> without leaking through public
signatures.</p>
<pre><code>data/nenjim/journals/
└── &lt;artifact-coordinate&gt;/
├── &lt;journal-version&gt;.journal
@@ -135,11 +142,15 @@ PREFERRED=nenjim:com_r35157_nenjim-hubd-api=1.0.3:'Built together'</code></pre>
registered, and cannot start anything. The internal administration interface must remain package-private so
an ordinary service consumer cannot cast the Registry object to a mutation view.</p>
<p><code>NenjimHubImpl</code> is the global composition and runtime owner. It constructs the Registry assembly,
starts and registers the Registry first, records its successful process ID, and then constructs and registers
the hardcoded component graph in dependency order. The Ticker explicitly selects the Raydium EVE/USDT source
ID while the hardcoded source remains registered but inactive. The Hub activates only the existing explicit
five-process sequence after the Registry; it does not start every registered process. Successful process IDs
are exposed as immutable ordered point-in-time snapshots, without implying continued health.</p>
starts and registers Registry first, and records its successful process ID. It then constructs the Journal
assembly for <code>data/nenjim/journals</code>, registers <code>nenjim.journal.service</code>, starts Journal
second, and records it only after complete successful loading. Only then does the Hub construct the hardcoded
business component graph in dependency order. A Journal failure therefore stops startup before Ticker,
Evelyn, Burner, Mission Control, the online point, and the blocking wait.</p>
<p>The Ticker explicitly selects the Raydium EVE/USDT source ID while the hardcoded source remains registered but
inactive. After Registry and Journal, the Hub activates only the existing explicit five-business-process
sequence; it does not start every registered process. Successful process IDs are exposed as immutable ordered
point-in-time snapshots, without implying continued health.</p>
<p><code>com.r35157.nenjim.hubd.Main</code> remains only the outer Java bootstrap. It constructs the reference Hub
through the public <code>NenjimHub</code> interface and calls <code>start()</code> once. The Hub is neither a
component nor a process and is not registered inside its own Registry.</p>
+37 -24
View File
@@ -1,9 +1,9 @@
#<center><H1>Nenjim<br>Documentation</H1></center>
> **Dokumentstatus:** Journal-format version 1, den immutable Java-model, den interne tekstparser, det read-only
> `JournalService`, den eksplicit refresh-baserede `JournalServiceManager` og første version af det centrale
> component Registry er implementeret. Contexts, resolution, discovery, runtime loading og removal er fortsat
> fremtidig funktionalitet.
> `JournalService` med en Hub-styret procesimplementation, den passive eksplicit refresh-baserede
> `JournalServiceManager` og første version af det centrale component Registry er implementeret. Contexts,
> resolution, discovery, runtime loading og removal er fortsat fremtidig funktionalitet.
**Indholdsfortegnelse:**
<!-- TOC -->
@@ -125,16 +125,23 @@ state ændres. Alle publicerede modeller og collections er immutable og defensiv
### 2.8 JournalService, JournalServiceManager og disk-layout
En `Service` er det domæne-API, som applikationer og andre services bruger i daglig drift. `JournalService` er derfor
filesystem-uafhængigt og read-only: det kan vise coordinates, kronologiske revisionslister, latest, exact og
newest-at-or-before snapshots samt en eksakt release fra et valgt snapshot. Det eksponerer ikke start/stop,
filesystem paths, refresh, parser eller mutation.
En `Service` er det domæne-API, som applikationer og andre services bruger i daglig drift. `JournalService` er en
registrerbar Nenjim component, men API'et er fortsat filesystem-uafhængigt og read-only: det kan vise coordinates,
kronologiske revisionslister, latest, exact og newest-at-or-before snapshots samt en eksakt release fra et valgt
snapshot. Det eksponerer ikke lifecycle, filesystem paths, refresh, parser eller mutation. Queries er først
tilgængelige, når Journal-processens initiale loading er lykkedes.
En `ServiceManager` ejes af en composition/lifecycle owner og håndterer start, stop, configuration/data location,
refresh og adgang til den tilhørende Service. `JournalServiceManager` ejer den normaliserede Journal-root. Ved start
læser referenceimplementationen komplette UTF-8-filer kronologisk, validerer placement/navne og gør først sit
`JournalService` tilgængeligt, når hele initial loading er lykkedes. Refresh er explicit og idempotent; der er ingen
watcher eller background polling, og stop ændrer ikke Journal-filer.
En `ServiceManager` er et separat administrationshandle, som en composition/lifecycle owner kan beholde uden at
give almindelige service-consumers administrative rettigheder. `JournalServiceManager` er passiv og eksponerer kun
den normaliserede Journal-root og explicit refresh; den har ingen `start()`, `stop()` eller service-accessor og er
hverken component eller process. Hub'en konstruerer ét Journal-objekt, som både er `JournalService` og
`NenjimProcess`, samt en separat manager bundet til objektets package-private admin-view.
Når Hub'en starter Journal-processen, læser referenceimplementationen komplette UTF-8-filer kronologisk og
validerer placement/navne. Hele den initiale worldview publiceres først, når alle runtime-filer er accepteret; en
fejl efterlader servicen utilgængelig uden partial state og samme instans kan ikke startes igen. Refresh efter
vellykket startup er fortsat explicit, idempotent og per-ingestion atomisk; der er ingen watcher eller background
polling.
`JournalServiceImpl` vedligeholder internt kæderne og udfører atomisk ingestion med exact-text SHA-256. Identisk tekst
er idempotent; anderledes tekst med samme coordinate og Journal-version er en conflict. Parser, ingestion og mutable
@@ -156,7 +163,7 @@ data/nenjim/journals/
```
Kun `.journal` er runtime-input. `.journal.example` dokumenterer formatet og indlæses ikke. Roden skal allerede
eksistere og være læsbar; service-manageren opretter, overskriver eller sletter ikke Journal-filer.
eksistere og være læsbar; Journal-processen og dens manager opretter, overskriver eller sletter ikke Journal-filer.
## 3. Opdateringer og Sikkerhed
Det implementerede Journal-lag kan repræsentere nye sikkerhedsoplysninger som en nyere immutable revision, for
@@ -167,9 +174,9 @@ upgrade/downgrade er fremtidigt arbejde.
Betaling og AssetAZ-integration er langsigtet vision og er ikke en del af Journal-formatet eller denne implementation.
## 5. Backing Store og Fleksibilitet
Den nuværende `JournalServiceManagerImpl` læser kun det dokumenterede lokale disk-layout. Artifact downloading, IPFS retrieval,
remote Journals og andre backing stores er ikke implementeret. En `ipfs:`-værdi i `INFORMATION_URI` er metadata,
ikke en retrieval-instruks.
Den nuværende Journal-proces læser kun det dokumenterede lokale disk-layout gennem en intern filesystem-loader.
Artifact downloading, IPFS retrieval, remote Journals og andre backing stores er ikke implementeret. En
`ipfs:`-værdi i `INFORMATION_URI` er metadata, ikke en retrieval-instruks.
## 6. Standardiseret og Automatiseret Pakkehåndtering
Journalen modellerer dependency-krav og indholdsidentiteter, men downloader ikke bytes og verificerer ikke downloadet
@@ -201,12 +208,17 @@ Det kan returnere et immutable registration-order snapshot af ID'er for et compo
gennem et forventet interface. Et manglende ID giver `null`; et eksisterende ID med forkert interface er en caller
programming error. Public API'et kan ikke registrere eller fjerne componenter.
`NenjimHubImpl` repræsenterer én kørende Nenjim runtime. Hub'en konstruerer Registry-subsystemet og hele den
nuværende hardcodede component graph, ejer dependency wiring og vælger de processer, som skal startes. Et
`NenjimHubImpl` repræsenterer én kørende Nenjim runtime. Hub'en konstruerer Registry- og Journal-subsystemerne samt
hele den nuværende hardcodede component graph, ejer dependency wiring og vælger de processer, som skal startes. Et
implementation-only Registry assembly udleverer read-only service-view, process-view af det samme Registry-objekt
og en separat `NenjimRegistryServiceManager`. Manageren er kun Hub'ens passive registrationshandle: den er hverken
component eller process, har ingen `start()` eller service-accessor, registreres ikke og starter aldrig en component.
Et tilsvarende implementation-only Journal assembly udleverer read-only service-view, process-view af det samme
Journal-objekt og en separat passiv `JournalServiceManager`. Journal-manageren registreres ikke og giver kun adgang
til root og refresh gennem et package-private admin-view; almindelige `JournalService`-consumers kan ikke udlede
administrationsadgangen.
Den package-private `NenjimRegistryServiceAdmin` er managerens interne mutationsadgang. Den må ikke gøres public,
fordi almindelige consumers ellers kunne caste deres Registry-service til mutationsinterfacet og bryde det
read-only service contract. Registration starter ikke et objekt, og Registry'et forbliver internt åbent for senere
@@ -214,12 +226,13 @@ registration efter startup.
Applikationen ejer sine konkrete valg og sin activation. Tickerens initiale configuration vælger eksplicit
`assetaz.price-source.raydium-pool.eve-usdt` gennem Registry'et; den hardcodede price source er registreret, men
inaktiv. Hub'en starter Registry-processen først og registrerer den som `nenjim.registry.service`. Derefter starter
Hub'en kun den nuværende eksplicitte, dependency-safe liste: Ticker, Production Evelyn, Test Evelyn, Production IOU
Burner og Mission Control. Alarmen og øvrige tidligere udkommenterede applikationer bliver ikke automatisk
aktiveret. Efter hvert succesfuldt `start()` registrerer Hub'en process-ID'et i et immutable, ordered snapshot; et
fejlet start bliver ikke registreret, og listen lover ikke fortsat health eller liveness. Startup er fail-fast og kan
kun forsøges én gang uden generic rollback.
inaktiv. Hub'en starter Registry-processen først og registrerer den som `nenjim.registry.service`. Journal-servicen
registreres dernæst som `nenjim.journal.service`, startes som den anden proces og skal være fuldt initialiseret, før
business graph'en fortsætter. Derefter starter Hub'en kun den nuværende eksplicitte, dependency-safe liste: Ticker,
Production Evelyn, Test Evelyn, Production IOU Burner og Mission Control. Alarmen og øvrige tidligere
udkommenterede applikationer bliver ikke automatisk aktiveret. Efter hvert succesfuldt `start()` registrerer Hub'en
process-ID'et i et immutable, ordered snapshot; et fejlet start bliver ikke registreret, og listen lover ikke fortsat
health eller liveness. Startup er fail-fast og kan kun forsøges én gang uden generic rollback.
`com.r35157.nenjim.hubd.Main` er kun det yderste Java-bootstrap. `Main.main(...)` konstruerer `NenjimHubImpl` gennem
det globale `NenjimHub`-interface og kalder `start()` præcis én gang. Hub'en ejer også det eksisterende online point
+6 -5
View File
@@ -1,14 +1,15 @@
# Tekniske termer
> **Dokumentstatus:** Journal-format version 1 og de tilhørende Java-typer, den interne parser, query-service,
> lifecycle-manager og første version af det centrale component Registry er implementeret. Resolver-, Context-,
> Hub-styret Journal-proces, passive service-managers og første version af det centrale component Registry er
> implementeret. Resolver-, Context-,
> classloader-, discovery-, runtime-loading-, retrieval- og publishing-termer beskriver kun fremtidig vision, når
> det er angivet.
| Term | Beskrivelse |
|------|-------------|
| Service | Det offentlige domæne-API, som applikationer og andre services bruger i daglig drift. Det eksponerer almindelige domæneoperationer, men ikke lifecycle, configuration, data-source administration, refresh, parser eller mutation af intern viden. En konkret serviceimplementation kan samtidig være en `NenjimProcess`, uden at lifecycle føjes til service-interfacet. |
| ServiceManager | Det offentlige lifecycle- eller administrations-API, som en composition/lifecycle owner bruger. De konkrete operationer følger serviceområdet: JournalServiceManager har start, stop, data location, refresh og adgang til JournalService, mens Registry service manageren kun er et passivt registrationshandle. Det er ikke det daglige domain/query-API for almindelige consumers. |
| ServiceManager | Et separat, passivt administrations-API, som en composition/lifecycle owner beholder uden at give almindelige service-consumers administrative rettigheder. Journal-manageren eksponerer root og refresh, mens Registry-manageren eksponerer registration. En manager er ikke det daglige domain/query-API, er hverken component eller process og ejer ikke startup. |
| Nenjim component | En færdigkonstrueret Nenjim-byggeklods, som er klar til brug. `NenjimComponent` er en ren marker uden ID eller lifecycle state. Service, applikation, algoritme og adapter beskriver roller, mens process beskriver en uafhængig lifecycle-klassifikation. |
| Applikation | En user-facing eller orchestration-rolle. Rollen gør ikke i sig selv en component til en process; en aktiv applikationsimplementation kan separat implementere `NenjimProcess`. |
| NenjimProcess | Det canonical `com.r35157.nenjim.process.NenjimProcess` component interface for noget, som Hub'en kan starte og tracke. Det eksponerer kun `start()` og lover ikke stop, restart, health, Context eller dependency lookup. |
@@ -37,9 +38,9 @@
| BLACKLIST | En hård artifact-policy: matchende releases må ikke vælges. |
| DISCOURAGED | Et negativt artifact-policy-hint: matchende releases bør undgås, men er fortsat selectable. |
| RECOMMENDED | Et positivt hint til én eksakt release, der findes i samme snapshot. Højeste version er kun en fremtidig fallback, ikke en ubetinget selection-regel. |
| JournalService | Filesystem-uafhængigt, read-only Service-API for current og historical Journal-queries. Det eksponerer ingen lifecycle-, path-, refresh-, parser- eller mutationsoperationer. |
| JournalServiceManager | Lifecycle- og administrations-API for JournalService. Det ejer den normaliserede data root, udfører komplet initial loading ved start, stopper servicen, udfører explicit refresh og udleverer JournalService efter vellykket initialisering. |
| Journal referenceimplementation | `JournalServiceImpl`, `JournalServiceManagerImpl`, `JournalTextParser`, intern ingestion, chain state og filesystem-loading under `com.r35157.nenjim.service.journal.impl.ref`; implementation details lækker ikke gennem public signatures. |
| JournalService | Registrerbart, filesystem-uafhængigt og read-only Service-API for current og historical Journal-queries. Det eksponerer ingen lifecycle-, path-, refresh-, parser- eller mutationsoperationer, og queries er gated indtil vellykket proces-startup. |
| JournalServiceManager | Passivt, uregistreret administrationshandle for én Journal-service med kun normalized data root og explicit refresh. Hub'en beholder det; det har ingen start, stop, service-accessor eller query-operationer. |
| Journal referenceimplementation | Ét package-private `JournalServiceImpl`-objekt er både `JournalService` og `NenjimProcess`; en separat `JournalServiceManagerImpl`, intern admin-view, parser, ingestion, chain state og filesystem-loader ligger under `com.r35157.nenjim.service.journal.impl.ref` uden at lække gennem public signatures. |
| Context | Fremtidig beskrivelse af ønskede/resolverede artifactvalg og isoleret runtime; ikke implementeret af Journal-laget eller første Registry-version. |
| Resolver | Fremtidig komponent for dependency graph og release-selection; Journal-laget repræsenterer reglerne, men vælger ikke en graf. |