diff --git a/.serena/memories/exporter/core.md b/.serena/memories/exporter/core.md index 65b6cbf3c6..992c796b84 100644 --- a/.serena/memories/exporter/core.md +++ b/.serena/memories/exporter/core.md @@ -50,6 +50,7 @@ on this side: the row of the job, its cancel and its result are the backend's. - `exporter.jobs` is the local cancel arm, smaller than the legacy `app.jobs`: one flag per claimed job (`register`/`mark-cancelled` returning true/nil/`cancelled?`/`release`) and one zero-arg check constructor per job (`check-cancelled`, raising `:job-cancelled`). No terminate callbacks and no shared-array signal travel through here — the abort belongs to whoever holds the render (the per-lease interval of `exporter.wasm.scope` terminates its own worker). The runner releases the registry entry on every settle; the legacy runner never did (one leaked entry per job). - `exporter.consumer.plan` is the render plan (`prepare-exports`, `count-objects`, `sanitize-file-regex`), dispatching on `exporter.renderer/wasm?` instead of the legacy `headless?`. - `exporter.consumer` is the runner: `run-export [cfg claim params]` keeps the legacy beats/watchdog/settle (first breath, render session, multipart complete or `fail-job`, temp release) but renders through the facade (`render [cfg & task]`) with one check from `exporter.jobs` shared between units of work and drivers. `cfg` is the render view; the claim names the job, `params` carries the frozen job params. The settle never rejects; only bugs of this process do. +- `exporter.tmpdir` owns the temp-file area (`:exporter/tmpdir`): the legacy shell creates its dir at namespace load, so referencing the var inside `init-key` pulls that moment into the lifecycle (fail fast on a bad `:tempdir`, ordered before the renderer that writes to it). Named for what it owns, not for the legacy namespace. - `exporter.consumer.api` is the backend management client (claim/progress/session/settle, transit bodies, multipart artifact), a faithful `^:async` port with no promesa chains and the same `fetch` def seam for hermetic tests. - `exporter.consumer.config` holds the consumer knobs (`concurrency` floored at 1, `queue-key`, `queue-name`): the runner, the worker and `exporter.main` read it, so no namespace under `exporter.*` depends on `app.consumer.*` anymore. - `exporter.consumer.worker` is the queue poller (`read-payload`, `process`, `poll-once`, `start`/`stop` with a running flag, no promesa): K connections over the `:exporter` queue, claim → `run-export` through the injected `:renderer` → settle before the next pop. The worker config carries the queue knobs plus the `:renderer` by ref; no render statics nest inside it. `stop` quits every connection and ends every loop (the legacy loops kept failing turns after the stop); boot cleans orphaned temp files first. diff --git a/exporter/src/exporter/main.cljs b/exporter/src/exporter/main.cljs index 58544b9a02..8f33367711 100644 --- a/exporter/src/exporter/main.cljs +++ b/exporter/src/exporter/main.cljs @@ -24,6 +24,7 @@ [exporter.consumer :as-alias consumer] [exporter.consumer.config :as ccfg] [exporter.consumer.worker] + [exporter.tmpdir] [exporter.utils.system :as system] [exporter.wasm :as-alias wasm] [exporter.wasm.pool])) @@ -41,12 +42,16 @@ ::wasm/pool {:max (ccfg/concurrency)} + :exporter/tmpdir + {} + :exporter/renderer - {::browser/pool (system/ref :exporter.browser/pool) - ::wasm/pool (system/ref :exporter.wasm/pool) - :base-uri (cf/get-internal-uri) - :public-uri (cf/get :public-uri) - :svgo? (contains? cf/flags :exporter-svgo)} + {::browser/pool (system/ref :exporter.browser/pool) + ::wasm/pool (system/ref :exporter.wasm/pool) + :exporter/tmpdir (system/ref :exporter/tmpdir) + :base-uri (cf/get-internal-uri) + :public-uri (cf/get :public-uri) + :svgo? (contains? cf/flags :exporter-svgo)} ::consumer/worker {:renderer (system/ref :exporter/renderer) diff --git a/exporter/src/exporter/tmpdir.cljs b/exporter/src/exporter/tmpdir.cljs new file mode 100644 index 0000000000..6e20a1be40 --- /dev/null +++ b/exporter/src/exporter/tmpdir.cljs @@ -0,0 +1,25 @@ +;; This Source Code Form is subject to the terms of the Mozilla Public +;; License, v. 2.0. If a copy of the MPL was not distributed with this +;; file, You can obtain one at http://mozilla.org/MPL/2.0/. +;; +;; Copyright (c) KALEIDOS SUBSIDIARY SL + +(ns exporter.tmpdir + "The temp-file area as a system component (`:exporter/tmpdir`). + + The legacy `app.util.shell` creates its `tmpdir` at namespace load: + config read, log line and `mkdirSync` the first time anything + requires it, in every thread including render workers and tests. + This component pulls that moment into the lifecycle: referencing the + var forces the creation during boot (fail fast on a bad `:tempdir`), + orders it before anything that writes temp files, and carries the + path in the instance for the day the temp area becomes injected + instead of global. Named for what it owns, not for the legacy + namespace it shadows." + (:require + [app.util.shell :as sh] + [exporter.utils.system :as system])) + +(defmethod system/init-key :exporter/tmpdir + [_ _] + {:tmpdir sh/tmpdir}) diff --git a/exporter/test/exporter_tests/main_test.cljs b/exporter/test/exporter_tests/main_test.cljs index 157535190d..63220513fd 100644 --- a/exporter/test/exporter_tests/main_test.cljs +++ b/exporter/test/exporter_tests/main_test.cljs @@ -52,9 +52,11 @@ (js/Promise.resolve #js {}))} :exporter/renderer {:exporter.browser/pool (system/ref :exporter.browser/pool) :exporter.wasm/pool (system/ref :exporter.wasm/pool) + :exporter/tmpdir (system/ref :exporter/tmpdir) :base-uri "http://internal/" :public-uri "http://public/" - :svgo? false}}) + :svgo? false} + :exporter/tmpdir {}}) (defn- pool-of [] @@ -121,6 +123,8 @@ (t/is (some? (pool-of))) (t/testing "the renderer boots as a render fn over the resolved pools" (t/is (fn? (:exporter/renderer @main/system)))) + (t/testing "the temp area boots before anything that writes to it" + (t/is (string? (:tmpdir (:exporter/tmpdir @main/system))))) (t/testing "the wasm pool rides the same lifecycle" (t/is (some? (:pool (wasm-pool-of)))) (t/is (= 300000 (:timeout-ms (wasm-pool-of)))))