Brazen Framework - Reactor

Reactor Core: signals, event bus, job scheduler, and coordinator kernel

이 스크립트는 직접 설치하는 용도가 아닙니다. 다른 스크립트에서 메타 지시문 // @require https://update.greasyfork.org/scripts/591444/1909485/Brazen%20Framework%20-%20Reactor.js을(를) 사용하여 포함하는 라이브러리입니다.

이 스크립트를 설치하려면 Tampermonkey, Greasemonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Userscripts와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 유저 스크립트 관리자 확장 프로그램이 필요합니다.

(이미 유저 스크립트 관리자가 설치되어 있습니다. 설치를 진행합니다!)

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

(이미 유저 스타일 관리자가 설치되어 있습니다. 설치를 진행합니다!)

작성자
brazenvoid
버전
1.0.0
생성일
2026-08-15
갱신일
2026-08-22
크기
112KB
라이선스
GPL-3.0-only

Brazen Framework — Reactor (developer guide)

Cross-tab coordination for Brazen apps: one coordinator tab (Web Locks), one event bus (Commands in, ordered Patches out), a signal graph for shared UI state, and a typed job scheduler for download resolution and config sync. IndexedDB remains the source of truth; follower tabs hold replica atoms and send Commands instead of writing queue stores directly.

Greasy Fork: TBD (not published yet) · Requires: IndexedDB Storage (kernel write-through on repositories) · Load before: Download Manager when using the Reactor pipeline · Grant on this module: none


When to use / when not to use

  • Use when your app @requires Download Manager and needs cross-tab download queues, coordinator leadership, or config/commands that must not race across tabs.
  • Use when you extend BrazenFramework and call APIs that delegate to sendCommand, isCoordinator(), or config-sync jobs.
  • Do not @require standalone for a trivial single-tab script with no Download Manager and no cross-tab shared state — the rest of the stack will not wire Reactor for you.
  • Do not duplicate leadership with custom localStorage locks or second BroadcastChannels; use the coordinator APIs below.

Quick start

Load order (after Configuration Manager and optional Tag Query Engine, before Download Manager):

// @require … Brazen Framework - Reactor.js
// @require … Brazen Framework - Download Manager.js
// @require … Brazen Framework - Framework.js

During local development, point Tampermonkey Resource override at base-scripts/BrazenReactor.js until the Greasy Fork listing exists.

Reactor bootstraps automatically when Download Manager initializes (_ensureReactor()). You normally do not construct BrazenKernel yourself unless building a new framework module that participates in the bus.

Check coordinator role from Framework or Download Manager:

if (this.isCoordinator()) {
  // this tab runs scheduler jobs and IDB write-through
}

Send a custom Command (coordinator applies locally; followers publish to the bus):

await this.sendCommand({
  type: 'custom',
  payload: { name: 'my-feature', data: { ok: true } },
})

Features

Coordinator tab (Web Locks)

One tab per script prefix holds brazen-{scriptPrefix}-coordinator. That tab:

  • Runs scheduler jobs (resolve / download / config-sync).
  • Performs IndexedDB write-through for Commands.
  • Broadcasts ordered Patches to followers.
API Where Role
isCoordinator() Framework / Download Manager Sync check
requestCoordinatorRole({ steal: true }) Framework / Download Manager Take leadership (replaces legacy “leader tab” steal)
requestCoordinatorRole({ ifAvailable: true }) Framework / Download Manager Claim only if lock is free

On pagehide, the coordinator releases the lock and aborts in-flight work. Followers apply Patches only — they do not write download queue stores.

Commands and Patches

Direction Shape Who
Command { type, payload? } Any tab → bus → coordinator handleCommand
Patch { path, version, value }[] with monotonic seq Coordinator → bus → all tabs

Common Command types used by Download Manager and Configuration Manager:

type Purpose
enqueue-download Add resolution queue row
dequeue-download Remove item from pipeline
toggle-paused Pause/resume download lane
write-setting Cross-tab setting write
config-save / config-sync Persist config + schedule sync job
custom Extensibility (pipeline-pump, config-change notifications, …)

Followers may apply optimistic local atom updates until an authoritative Patch with a higher seq arrives.

Signal graph (BrazenSignals)

Path-keyed atoms (e.g. dm.state.paused, config.settings.{key}) drive dock UI without polling IDB.

const signals = globalThis.BrazenSignals
const paused = signals.atom('dm.state.paused', false)
paused.write(true)
signals.applyPatches([{ path: 'dm.state.paused', version: 42, value: false }])

Legacy helpers createAtom, createComputed, createEffect, and batch remain on globalThis and share the same graph.

Event bus (BrazenEventBus)

One BroadcastChannel per script prefix (brazen-{scriptPrefix}). Configuration Manager creates the instance; Download Manager reuses it.

Typical app code does not call BrazenEventBus.create() directly — use sendCommand on Framework/Download Manager.

Job scheduler (BrazenScheduler + BrazenJobRegistry)

Built-in job types: resolve, download (constants JOB_TYPE_RESOLVE, JOB_TYPE_DOWNLOAD).

Descriptors support coalesce keys, merge, dependency DAG, concurrency limits, and reassess gates. Download Manager registers pipeline job types during _ensureReactor().

Loop profiler (BrazenReactorProfiler)

Always on by default — ring buffer, breakers, and incident snapshots run without setup. You do not need DevTools open during a slowdown.

When something goes wrong:

  • A fixed corner badge shows the breaker message (works during partial slowdowns; full tab freeze may still block paint).
  • A sessionStorage snapshot survives tab kill/reload (brazen:reactor:last-incident).
  • On the next page load, one automatic console.warn summarizes the previous incident; full data is on globalThis.__brazenReactor.lastIncident.
  • report() prints a cause breakdown table — which command/patch/job spawned the downstream propagate/paint/config-ui storm.
  • summary() returns a copy-paste-safe multi-line string (top causes, channels, scheduledReentrant, topPaths, redundantSnapshot) — also emitted automatically on idle-watchdog / write-storm / reentrancy breakers and stored on lastIncident.summary.

Optional when DevTools is usable:

globalThis.__brazenReactor.report()
globalThis.__brazenReactor.summary()
globalThis.__brazenReactor.dump()

Opt-out for baseline comparison only:

localStorage.setItem('brazen:reactor:profile', 'disabled')

Verbose per-mark logging (optional):

localStorage.setItem('brazen:reactor:profile', 'verbose')

Public API reference (index)

All symbols are on globalThis after the script loads.

Export Kind
BrazenReactorProfiler, __brazenReactor Profiler singleton
BrazenSignals Namespace (atom, computed, effect, batch, applyPatches, …)
BrazenEventBus Class (create, publish, subscribe, requestSnapshot, …)
BrazenJobRegistry Class
BrazenScheduler Class
BrazenKernel Class
coordinatorLockName(scriptPrefix) Function
JOB_TYPE_RESOLVE, JOB_TYPE_DOWNLOAD String constants
createAtom, createComputed, createEffect, batch, assertAcyclic, BrazenSignalCycleError, getPropagationGeneration Legacy signal helpers

Framework/Download Manager delegates (preferred in apps):

Method Role
sendCommand(command) Route Command to coordinator or bus
isCoordinator() Coordinator probe
requestCoordinatorRole(options) Claim / steal lock

Integration notes

Topic Detail
Load order Reactor → Download Manager → Framework core (match your app’s @require chain)
IDB writes Only the coordinator tab writes queue/state stores via kernel write-through; followers use Commands
Patch vs job seq Patch sequence comes from BrazenEventBus.nextSeq(); job ordering uses scheduler local seq unless overridden
Cold start Followers call requestSnapshot before applying live Patches (handled internally when bus subscribes)
Testing Manual Tampermonkey repro on affected sites; multi-tab QA per consuming app spec
Publishing One GF listing for this file (formerly five separate Reactor modules); pin version id in app @require after publish

Related framework modules