Skip to content

Commit ef2e64a

Browse files
committed
update docs
1 parent e6af5b6 commit ef2e64a

3 files changed

Lines changed: 103 additions & 93 deletions

File tree

CLAUDE.md

Lines changed: 73 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -17,29 +17,37 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
1717

1818
The codebase is organized into several layers:
1919

20-
1. **Core API** ([src/intemporal/core.clj](src/intemporal/core.clj))
20+
1. **Core API** ([src/intemporal/core.cljc](src/intemporal/core.cljc))
2121
- `stub` - Creates activity stubs for use in workflows
22-
- Main workflow execution entry points
23-
- Handles activity caching, replay, and async operations
22+
- `stub-protocol` - Creates protocol stubs for use in workflows
23+
- `start-workflow`, `resume-workflow` - Workflow execution entry points
24+
- `make-workflow-engine`, `with-workflow-engine` - Engine lifecycle
25+
- `wait-for-signal`, `send-signal`, `sleep`, `async`, `join` - Workflow operations
26+
- `run-child-workflow`, `cancel-workflow` - Child workflows and cancellation
2427

25-
2. **Protocol Definitions** ([src/intemporal/protocol.clj](src/intemporal/protocol.clj))
28+
2. **Protocol Definitions** ([src/intemporal/protocol.cljc](src/intemporal/protocol.cljc))
2629
- `IStore` - Workflow persistence (history, signals, cancellation)
2730
- `IActivityExecutor` - Activity execution with timeout/retry
2831
- `IScheduler` - Timer scheduling
2932
- `IWorkflowObserver` - Event observation for monitoring/tracing
3033

3134
3. **Internal Components** (src/intemporal/internal/)
32-
- `context.clj` - Dynamic workflow context with sequence counters, pending events
33-
- `execution.clj` - Workflow execution engine, handles suspensions and retries
34-
- `runtime.clj` - Default implementations of `IActivityExecutor` and `IScheduler`
35-
- `activity.clj` - Activity registration and metadata
36-
- `error.clj` - Error types (suspensions, interruptions, rejections, cancellations)
37-
- `logging.clj` - Structured logging with MDC support
38-
- `macros.cljc` - `defn-workflow`, `stub-function`, `stub-protocol` macros
39-
40-
4. **Store Implementations** ([src/intemporal/store.clj](src/intemporal/store.clj))
35+
- `context.cljc` - Dynamic workflow context with sequence counters, pending events
36+
- `execution.clj` / `execution.cljs` - Workflow execution engine (platform-specific)
37+
- `runtime.clj` / `runtime.cljs` - Default implementations of `IActivityExecutor` and `IScheduler` (platform-specific)
38+
- `activity.cljc` - Activity registration and metadata
39+
- `error.cljc` - Error types (suspensions, interruptions, rejections, cancellations)
40+
- `logging.cljc` - Structured logging via taoensso/telemere
41+
- `macros.cljc` - `stub-protocol` macro
42+
- `fns/start_workflow.clj` / `fns/start_workflow.cljs` - Workflow start logic (platform-specific)
43+
44+
4. **Store Implementations** ([src/intemporal/store.cljc](src/intemporal/store.cljc))
4145
- `InMemoryStore` - In-memory implementation of `IStore`
42-
- Additional stores: FoundationDB (`:fdb` alias), JDBC (`:jdbc` alias)
46+
- Additional stores: FoundationDB (`store/fdb.clj`, `:fdb` alias), JDBC (`store/jdbc.clj`, `:jdbc` alias)
47+
48+
5. **Observer** ([src/intemporal/observer.cljc](src/intemporal/observer.cljc))
49+
- `noop-observer`, `make-logging-observer` - Observer factories
50+
- `observer/otel.clj` - OpenTelemetry observer implementation
4351

4452
### Key Mechanisms
4553

@@ -78,6 +86,10 @@ bin/kaocha :test --focus intemporal.tests.crash.future-cancel-test
7886

7987
# Run tests via npx
8088
npx shadow-cljs compile node
89+
90+
# Focus cljs tests
91+
bin/kaocha :test-cljs --focus cljs:intemporal.tests.crash.future-cancel-test
92+
8193
```
8294

8395
**Important**: Test namespaces use hyphens (e.g., `signal-wait-crash-test`), which map to underscored file names (`signal_wait_crash_test.clj`).
@@ -117,63 +129,78 @@ clojure -T:build jar
117129

118130
### Debug Configuration
119131

120-
The test runner ([bin/kaocha](bin/kaocha)) automatically starts a debug agent on port 5005:
132+
The test runner ([bin/kaocha](bin/kaocha)) has a commented-out debug agent on port 5005 that can be enabled:
121133
```
122134
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005
123135
```
124136

125137
### OpenTelemetry Tracing
126138

127-
The project includes OpenTelemetry instrumentation (see [deps.edn](deps.edn) lines 14-24):
139+
The project includes OpenTelemetry instrumentation (see [deps.edn](deps.edn) `:dev` alias, `_jvm-opts`):
128140
- Java agent: `./opentelemetry-javaagent.jar`
129141
- OTLP endpoint: `http://localhost:4317` (gRPC)
130142
- Service name: `intemporal`
131143
- Metrics and logs are disabled by default
144+
- Note: The OTel JVM opts use the `_jvm-opts` key (underscore prefix), so they are **not active by default** - they must be manually enabled
132145

133146
## Code Patterns
134147

135148
### Defining a Workflow
136149

150+
Workflows are regular functions that use `stub` to wrap activity calls:
151+
137152
```clojure
138-
(require '[intemporal.core :as w])
139-
(require '[intemporal.internal.macros :refer [defn-workflow]])
153+
(require '[intemporal.core :as intemporal])
140154

141-
(defn-workflow my-workflow [arg]
142-
(let [activity-stub (w/stub some-activity-fn)]
143-
(activity-stub arg)))
155+
(defn my-activity [arg]
156+
[:processed arg])
157+
158+
(defn my-workflow [arg]
159+
(let [act (intemporal/stub #'my-activity)]
160+
(act arg)))
144161
```
145162

146163
### Activities
147164

148165
Activities can be:
149-
- Regular functions: `(w/stub my-function)`
150-
- Protocol methods: `(w/stub-protocol MyProtocol {})`
166+
- Regular functions (via var): `(intemporal/stub #'my-function)`
167+
- Protocol methods: `(intemporal/stub-protocol MyProtocol)`
151168

152169
### Running Workflows
153170

154171
```clojure
155-
(require '[intemporal.store :as store])
156-
157-
(def my-store (store/make-memstore))
158-
(def executor (w/start-poller! my-store {`MyProtocol (->MyProtocolImpl)}))
159-
160-
;; Execute workflow (returns result in JVM, Promise in ClojureScript)
161-
(def result (w/with-env {:store my-store}
162-
(my-workflow args)))
172+
(require '[intemporal.core :as intemporal])
173+
174+
;; Using with-workflow-engine (ensures cleanup)
175+
(intemporal/with-workflow-engine [engine {:threads 4}]
176+
(intemporal/start-workflow engine my-workflow [arg]))
177+
178+
;; Or manually managing the engine
179+
(let [engine (intemporal/make-workflow-engine :threads 4)]
180+
(try
181+
(intemporal/start-workflow engine my-workflow [arg])
182+
(finally
183+
(intemporal/shutdown-engine engine))))
163184
```
164185

165186
## Testing Guidelines
166187

167188
### Test Organization
168189

169190
- [test/intemporal/tests/](test/intemporal/tests/) - Main test directory
170-
- `async_test.clj` - Async operation tests
171-
- `cancellation_test.clj` - Workflow cancellation
172-
- `child_workflow_test.clj` - Nested workflow tests
173-
- `error_test.clj` - Error handling and retry policies
174-
- `signal_test.clj` - Signal send/receive
175-
- `timer_test.clj` - Timer scheduling
176-
- `tracing_test.clj` - OpenTelemetry tracing
191+
- `async_test.clj` / `.cljs` - Async operation tests
192+
- `cancellation_test.clj` / `.cljs` - Workflow cancellation
193+
- `child_workflow_test.clj` / `.cljs` - Nested workflow tests
194+
- `error_test.clj` / `.cljs` - Error handling and retry policies
195+
- `signal_test.clj` / `.cljs` - Signal send/receive
196+
- `timer_test.clj` / `.cljs` - Timer scheduling
197+
- `tracing_test.clj` - OpenTelemetry tracing (JVM only)
198+
- `protocol_test.clj` - Protocol tests
199+
- `replay_check_test.clj` - Replay verification
200+
- `stub_protocol_test.cljc` - Protocol stubbing tests
201+
- `context_macros_test.cljs` - Context macros (ClojureScript only)
202+
- `utils.cljc` - Test utilities
203+
- [store/](test/intemporal/tests/store/) - Store-specific tests
177204
- [crash/](test/intemporal/tests/crash/) - Crash recovery scenarios
178205

179206
### Crash Recovery Tests
@@ -188,15 +215,18 @@ Tests in `test/intemporal/tests/crash/` verify workflow resilience:
188215

189216
### Required Dependencies (all environments)
190217
- Clojure 1.12.1+
191-
- tools.logging + logback (structured logging)
192-
- OpenTelemetry API (tracing)
218+
- taoensso/telemere (structured logging)
219+
- clj-otel-api (OpenTelemetry tracing)
193220
- macrovich (cross-platform macros)
221+
- promesa (promises, required for ClojureScript)
222+
- cheshire (JSON)
223+
- shadow-cljs
194224

195225
### Optional Dependencies (via aliases)
196226
- `:fdb` - FoundationDB client
197-
- `:jdbc` - PostgreSQL/JDBC persistence
198-
- `:cljs` - ClojureScript support (shadow-cljs)
199-
- `:dev` - Testing libraries (Kaocha, test.check, matcher-combinators, spy)
227+
- `:jdbc` - PostgreSQL/JDBC persistence (next.jdbc, PostgreSQL, HikariCP, migratus)
228+
- `:cljs` - ClojureScript support
229+
- `:dev` - Testing libraries (Kaocha, kaocha-cloverage, kaocha-junit-xml, kaocha-cljs, logback, spy, matcher-combinators, clj-async-profiler)
200230

201231
## Important Notes
202232

DEVELOPMENT.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,17 +36,17 @@ clj -A:dev:doc:cljs
3636
# Tests
3737

3838
```shell
39-
bin/kaocha test
40-
bin/kaocha test-cljs
39+
bin/kaocha :test
40+
bin/kaocha :test-cljs
4141

4242
# or run everything
4343
bin/run-coverage
4444

4545
# focusing
46-
./bin/kaocha test --focus intemporal.shutdown-restart-test
46+
./bin/kaocha :test --focus intemporal.tests.signal-test
4747

4848
# cljs focus is a bit different
49-
./bin/kaocha test-cljs --focus 'cljs:intemporal.shutdown-restart-test'
49+
./bin/kaocha :test-cljs --focus 'cljs:intemporal.tests.signal-test'
5050

5151
```
5252

README.md

Lines changed: 26 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -17,62 +17,42 @@ Two concepts apply:
1717
## Usage
1818

1919
Examples:
20-
- [demo_workflow.clj](./dev/intemporal/demo_workflow.clj)
21-
- [demo_automata.cljc](./dev/intemporal/demo_automata.cljc)
22-
- [demo_saga.cljc](./dev/intemporal/demo_saga.cljc)
20+
- [doc.cljs](./doc/intemporal/doc.cljs)
21+
- [automata.cljs](./doc/intemporal/automata.cljs)
2322

2423
> Note that when the runtime is javascript, all activities will return a promise.
25-
> Thus, the use of `promesa.core/let` and/or `intemporal.macros/env-let` is advised
24+
> Thus, the use of `promesa.core/let` is advised
2625
2726
```clojure
27+
(ns intemporal.demo
28+
(:require [intemporal.core :as intemporal]
29+
[intemporal.store :as store]))
2830

29-
(ns intemporal.demo-workflow
30-
(:require [intemporal.store :as store]
31-
[intemporal.workflow :as w]
32-
[intemporal.macros :refer [stub-function stub-protocol defn-workflow]]))
33-
34-
;;;;
35-
;; demo
36-
37-
(defn nested-fn [a]
38-
[a :nested])
39-
31+
;; Activities are regular functions
4032
(defn activity-fn [a]
41-
(let [f (stub-function nested-fn)]
42-
(conj a :activity (f :sub))))
33+
[:processed a])
4334

35+
;; Protocols can also be used as activities
4436
(defprotocol MyActivities
4537
(foo [this a]))
4638

4739
(defrecord MyActivitiesImpl []
4840
MyActivities
49-
(foo [this a] (println "record was called:" ) [a :child]))
50-
51-
(defn-workflow my-workflow [i]
52-
(let [sf (stub-function activity-fn)
53-
pr (stub-protocol MyActivities {})]
54-
(conj [:root]
55-
(sf [1])
56-
(foo pr :X))))
57-
58-
(def mstore (store/make-memstore))
59-
(def executor (w/start-poller! mstore {`MyActivities (->MyActivitiesImpl)}))
60-
61-
;; note that in cljs, this returns a promise
62-
(def res (w/with-env {:store mstore}
63-
(my-workflow 1)))
64-
65-
(defn pprint-table [table]
66-
(clojure.pprint/print-table table))
67-
68-
(defn print-tables []
69-
(let [tasks (store/list-tasks mstore)
70-
events (->> (store/list-events mstore)
71-
(sort-by :id))]
72-
(pprint-table tasks)
73-
(pprint-table events)))
74-
75-
(print-tables)
41+
(foo [this a] [a :child]))
42+
43+
;; Workflows orchestrate activities via stubs
44+
(defn my-workflow [i]
45+
(let [act (intemporal/stub #'activity-fn)
46+
pr (intemporal/stub-protocol MyActivities)]
47+
{:activity (act i)
48+
:protocol (foo pr :X)}))
49+
50+
;; Create an engine and run the workflow
51+
(intemporal/with-workflow-engine [engine {:threads 2}]
52+
(let [result (intemporal/start-workflow engine
53+
my-workflow [1]
54+
:protocols {MyActivities (->MyActivitiesImpl)})]
55+
(println result)))
7656
```
7757

7858
# TODO
@@ -85,6 +65,6 @@ Examples:
8565
- [x] Convert to `.cljc`
8666
- [x] Workers + Queues
8767
- [x] Saga pattern
88-
- [ ] Workflow cancellation
68+
- [x] Workflow cancellation
8969
- [x] OT tracing
90-
- [ ] Signals
70+
- [x] Signals

0 commit comments

Comments
 (0)