Tactical Media Broadcast Hub — initial release
Self-hosted multi-platform broadcast newsroom for activist collectives: publishing pipeline with group approval and DST-proof scheduling, TweetDeck-style column wall with hostile-content-safe rendering, live control room with Auto Director, bridged chat governance with polls and quorum, distributed sandboxed transcode workers, encrypted content-addressed archive, monthly analytics. MIT licensed. See README.md and docs/.
This commit is contained in:
commit
aa5e262f3a
880 changed files with 111042 additions and 0 deletions
41
packages/connector-runtime/src/execution-context.ts
Normal file
41
packages/connector-runtime/src/execution-context.ts
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
import { AsyncLocalStorage } from "node:async_hooks";
|
||||
import { setHttpRequestHookProvider, type HttpRequestHook } from "@tactical-media-broadcast-hub/connector-sdk";
|
||||
|
||||
/**
|
||||
* Per-execution HTTP hook carried through AsyncLocalStorage, so concurrent
|
||||
* publish activities in one process never share a "current job".
|
||||
*/
|
||||
const storage = new AsyncLocalStorage<HttpRequestHook>();
|
||||
let installed = false;
|
||||
|
||||
function install(): void {
|
||||
if (installed) return;
|
||||
setHttpRequestHookProvider(() => storage.getStore());
|
||||
installed = true;
|
||||
}
|
||||
|
||||
/** Run `fn` with `hook` observing every SDK HTTP request it makes. */
|
||||
export function runWithHttpHook<T>(hook: HttpRequestHook, fn: () => Promise<T>): Promise<T> {
|
||||
install();
|
||||
return storage.run(hook, fn);
|
||||
}
|
||||
|
||||
import type { ConnectorConnection } from "@tactical-media-broadcast-hub/core";
|
||||
export interface PublishingExecutionContext {
|
||||
workspaceId: string;
|
||||
connectionId: string;
|
||||
credentialId: string;
|
||||
credentialGeneration: string;
|
||||
signal?: AbortSignal;
|
||||
}
|
||||
const executionStorage = new AsyncLocalStorage<PublishingExecutionContext>();
|
||||
export function runWithPublishingContext<T>(context: PublishingExecutionContext, fn: () => Promise<T>): Promise<T> {
|
||||
return executionStorage.run(context, fn);
|
||||
}
|
||||
export function publishingContext(connection: ConnectorConnection): PublishingExecutionContext {
|
||||
const context = executionStorage.getStore();
|
||||
if (!context || connection.workspaceId !== context.workspaceId || connection.id !== context.connectionId || connection.credentialId.id !== context.connectionId) throw new Error("EXECUTION_CREDENTIAL_FENCE");
|
||||
context.signal?.throwIfAborted();
|
||||
return context;
|
||||
}
|
||||
export function executionSignal(): AbortSignal | undefined { return executionStorage.getStore()?.signal; }
|
||||
Loading…
Add table
Add a link
Reference in a new issue