Event names are local now, in the manifests and in the code
Every module named its events the way the old bus spelled a routing key — `module.<module>.<verb>`. Design 29 says a module names an event locally and the mesh works out where it lands, so all 37 were stale against a rule already decided. On the new bus that derives into a namespace belonging to a module called "module", so no cross-module subscription in the mesh matched anything: nothing failed, nothing reacted (novox/hq 04-ISSUES/127). 36 manifests converted, and 43 files of module code with them. The code mattered as much as the manifests: the runtime builds the subject from what `emit()` is handed, so a converted manifest with unconverted code would have had the permission and the subject disagree. Three things the new check found on the way: - `photos` emitted an event its manifest never declared, which the new bus refuses outright. Declared. - `showcase` waited for an event nothing emits, so its demo could never be triggered — only `showcase` may publish under its own name. It emits both halves now. - `distribution` declared an event named after a different module. It emits `image.pushed` under its own name. An event about a *role* belongs on the seat, where the name outlives whoever holds it, but the sdk has no way to publish on a seat yet, so that stays recorded rather than declared. The audit logger's "everything" pattern is `**` rather than the old bus's `#`.
This commit is contained in:
@@ -24,10 +24,10 @@ async function pollSessions(): Promise<void> {
|
||||
const now = new Map(sessions.map((s) => [s.key, s]));
|
||||
if (playbackPrimed) {
|
||||
for (const [key, s] of now) {
|
||||
if (!active.has(key)) await emit("module.plex.playback.started", { title: s.title, user: s.user, player: s.player, kind: s.type });
|
||||
if (!active.has(key)) await emit("playback.started", { title: s.title, user: s.user, player: s.player, kind: s.type });
|
||||
}
|
||||
for (const [key, s] of active) {
|
||||
if (!now.has(key)) await emit("module.plex.playback.stopped", { title: s.title, user: s.user, player: s.player });
|
||||
if (!now.has(key)) await emit("playback.stopped", { title: s.title, user: s.user, player: s.player });
|
||||
}
|
||||
}
|
||||
active.clear();
|
||||
@@ -44,7 +44,7 @@ async function pollRecent(): Promise<void> {
|
||||
for (const item of items) {
|
||||
const id = `${item.title}@${item.addedAt ?? ""}`;
|
||||
if (!seen.has(id)) {
|
||||
if (itemsPrimed) await emit("module.plex.item.added", item);
|
||||
if (itemsPrimed) await emit("item.added", item);
|
||||
seen.add(id);
|
||||
}
|
||||
}
|
||||
@@ -53,7 +53,7 @@ async function pollRecent(): Promise<void> {
|
||||
|
||||
// A downloader finished somewhere on the mesh: rescan, so what it fetched becomes a visible item
|
||||
// rather than a file Plex has not noticed. Idempotent — a rescan too many costs a little disk I/O.
|
||||
await on("module.*.download.completed", async () => {
|
||||
await on("*.download.completed", async () => {
|
||||
await plex.refreshAll();
|
||||
});
|
||||
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
"container-runtime"
|
||||
],
|
||||
"emits": [
|
||||
"module.plex.playback.started",
|
||||
"module.plex.playback.stopped",
|
||||
"module.plex.item.added"
|
||||
"playback.started",
|
||||
"playback.stopped",
|
||||
"item.added"
|
||||
],
|
||||
"consumes": [
|
||||
"module.*.download.completed"
|
||||
"*.download.completed"
|
||||
],
|
||||
"own-secrets": {
|
||||
"broker": "/var/lib/mesh/plex/broker",
|
||||
|
||||
Reference in New Issue
Block a user