diff --git a/.memory/alignment_checking/README.md b/.memory/alignment_checking/README.md index 716d627..eba7469 100644 --- a/.memory/alignment_checking/README.md +++ b/.memory/alignment_checking/README.md @@ -22,7 +22,7 @@ Python is the reference style (code-first, minimal prose). All languages should - `—` = missing, intentional (language doesn't need this) - `TODO` = missing, should add - `DEL` = present, should remove or merge -- `Py#` / `TS#` / `Go#` = section order in file (should monotonically increase if order is aligned) +- `Py#` / `TS#` / `Rb#` / `Go#` = section order in file (should monotonically increase if order is aligned) ## Implementation Status @@ -30,6 +30,8 @@ Python is the reference style (code-first, minimal prose). All languages should **Go:** ✅ COMPLETE (2026-03-17) — All Go reference files created and aligned. +**Ruby:** ⏳ IN PROGRESS (2026-03-16) — Ruby columns added to all alignment tracking files. Ruby reference files not yet created. + ## Files Each file in this directory tracks alignment for a corresponding reference file: diff --git a/.memory/alignment_checking/advanced-features.md b/.memory/alignment_checking/advanced-features.md index 532976f..c54d6fd 100644 --- a/.memory/alignment_checking/advanced-features.md +++ b/.memory/alignment_checking/advanced-features.md @@ -2,22 +2,24 @@ ## Section Inventory -| Section | Core | Python | Py# | TypeScript | TS# | Go | -|---------|------|--------|-----|------------|-----|-----| -| Schedules | — | ✓ | 1 | ✓ | 1 | | -| Async Activity Completion | — | ✓ | 2 | ✓ | 2 | | -| Sandbox Customization | — | ✓ | 3 | — | — | | -| Gevent Compatibility Warning | — | ✓ | 4 | — | — | | -| Worker Tuning | — | ✓ | 5 | ✓ | 3 | | -| Workflow Init Decorator | — | ✓ | 6 | — | — | | -| Workflow Failure Exception Types | — | ✓ | 7 | — | — | | -| Continue-as-New | — | — | — | — | — | | -| Workflow Updates | — | — | — | — | — | | -| Nexus Operations | — | — | — | — | — | | -| Activity Cancellation and Heartbeating | — | — | — | — | — | | -| Sinks | — | — | — | ✓ | 4 | | -| CancellationScope Patterns | — | — | — | — | — | | -| Best Practices | — | — | — | — | — | | +| Section | Core | Python | Py# | TypeScript | TS# | Ruby | Rb# | Go | +|---------|------|--------|-----|------------|-----|------|-----|-----| +| Schedules | — | ✓ | 1 | ✓ | 1 | TODO | 1 | | +| Async Activity Completion | — | ✓ | 2 | ✓ | 2 | TODO | 2 | | +| Sandbox Customization | — | ✓ | 3 | — | — | — | — | | +| Gevent Compatibility Warning | — | ✓ | 4 | — | — | — | — | | +| Worker Tuning | — | ✓ | 5 | ✓ | 3 | TODO | 3 | | +| Workflow Init Decorator | — | ✓ | 6 | — | — | — | — | | +| Workflow Failure Exception Types | — | ✓ | 7 | — | — | TODO | 4 | | +| Continue-as-New | — | — | — | — | — | — | — | | +| Workflow Updates | — | — | — | — | — | — | — | | +| Nexus Operations | — | — | — | — | — | — | — | | +| Activity Cancellation and Heartbeating | — | — | — | — | — | — | — | | +| Sinks | — | — | — | ✓ | 4 | — | — | | +| Activity Concurrency and Executors | — | — | — | — | — | TODO | 5 | | +| Rails Integration | — | — | — | — | — | TODO | 6 | | +| CancellationScope Patterns | — | — | — | — | — | — | — | | +| Best Practices | — | — | — | — | — | — | — | | ## Style Compliance @@ -25,25 +27,43 @@ |----------|--------|-------| | Python | ✓ reference | 7 sections | | TypeScript | ✓ aligned | 4 sections (removed duplicates) | +| Ruby | — | Not started | | Go | ✓ aligned | 4 sections — Schedules, Async Completion, Worker Tuning, Sessions | ## Status -**Go-specific notes:** -- Schedules: `client.ScheduleClient` — same concept as Python/TS -- Async Activity Completion: `activity.GetInfo(ctx).TaskToken` + `client.CompleteActivity` / `client.CompleteActivityByID` -- Worker Tuning: `worker.Options` — `MaxConcurrentActivityExecutionSize`, `MaxConcurrentWorkflowTaskExecutionSize`, `MaxConcurrentActivityTaskPollers` -- Sessions: Go-specific feature — `workflow.CreateSession(ctx, options)` pins activities to a specific worker. Useful for file processing where activities need local state. **Intentionally missing (`—`):** - Core column: advanced features are implementation-specific -- Sandbox Customization: Python-specific; Go has no sandbox +- Sandbox Customization: Python-specific; Ruby/Go have no sandbox - Gevent Compatibility Warning: Python-specific -- Workflow Init Decorator: Python-specific -- Workflow Failure Exception Types: Python-specific +- Workflow Init Decorator: Python-specific (`@workflow.init`); Ruby uses `initialize` naturally; Go N/A - Sinks: TS-specific feature -- Sessions: Go-specific (not in Python/TS) +- Workflow Failure Exception Types: Python has `workflow_failure_exception_types`; Ruby has similar `workflow_failure_exception_type` class method — should include; Go: Python-specific +- Sessions: Go-specific (not in Python/TS/Ruby) - Interceptors: Decided not to include for any language (all SDKs have them, but too advanced for current scope) +**Ruby notes:** +- Schedules: `Temporalio::Client::ScheduleHandle` — same API pattern as other SDKs +- Async Activity Completion: `Temporalio::Client::AsyncActivityHandle` for completing activities from external processes +- Worker Tuning: `max_concurrent_workflow_tasks`, `max_concurrent_activities`, resource-based auto-tuning +- Workflow Failure Exception Types: `workflow_failure_exception_type` on workflow class or `workflow_failure_exception_types` on worker +- Activity Concurrency and Executors: Ruby-specific — `Temporalio::Worker::ActivityExecutor::ThreadPool`, fiber-based execution, `max_concurrent_activities` +- Rails Integration: Ruby-specific — ActiveRecord concerns, lazy/eager loading, Zeitwerk compatibility + +**Go notes:** +- Schedules: `client.ScheduleClient` — same concept as Python/TS +- Async Activity Completion: `activity.GetInfo(ctx).TaskToken` + `client.CompleteActivity` / `client.CompleteActivityByID` +- Worker Tuning: `worker.Options` — `MaxConcurrentActivityExecutionSize`, `MaxConcurrentWorkflowTaskExecutionSize`, `MaxConcurrentActivityTaskPollers` +- Sessions: Go-specific feature — `workflow.CreateSession(ctx, options)` pins activities to a specific worker. Useful for file processing where activities need local state. + +**Sections needing review (empty cells):** +- Ruby column: all TODO — Ruby reference files not yet created + **Order alignment:** N/A — Files have different structures by design -**Style alignment:** ✅ Complete (Python, TypeScript) +**Style alignment:** ✅ Complete (Python, TypeScript, Go) +- Python: 7 sections (Schedules, Async Activity Completion, Sandbox Customization, Gevent Warning, Worker Tuning, Workflow Init, Failure Exception Types) +- TypeScript: 4 sections (Schedules, Async Activity Completion, Worker Tuning, Sinks) +- Go: 4 sections (Schedules, Async Completion, Worker Tuning, Sessions) +- Ruby: ~6 sections planned (Schedules, Async Activity Completion, Worker Tuning, Failure Exception Types, Activity Concurrency/Executors, Rails Integration) +- Removed duplicates from TS (Continue-as-New, Workflow Updates, CancellationScope Patterns, Nexus Operations, Activity Cancellation, Best Practices — all covered elsewhere) diff --git a/.memory/alignment_checking/data-handling.md b/.memory/alignment_checking/data-handling.md index 441e825..f9f566d 100644 --- a/.memory/alignment_checking/data-handling.md +++ b/.memory/alignment_checking/data-handling.md @@ -2,20 +2,22 @@ ## Section Inventory -| Section | Core | Python | Py# | TypeScript | TS# | Go | Go# | -|---------|------|--------|-----|------------|-----|-----|-----| -| Overview | — | ✓ | 1 | ✓ | 1 | ✓ | 1 | -| Default Data Converter | — | ✓ | 2 | ✓ | 2 | ✓ | 2 | -| Pydantic Integration | — | ✓ | 3 | — | — | — | — | -| Custom Data Converter | — | ✓ | 4 | ✓ | 3 | ✓ | 3 | -| Composition of Payload Converters | — | — | — | ✓ | 4 | ✓ | 4 | -| Protobuf Support | — | — | — | ✓ | 5 | ✓ | 5 | -| Payload Encryption | — | ✓ | 5 | ✓ | 6 | ✓ | 6 | -| Search Attributes | — | ✓ | 6 | ✓ | 7 | ✓ | 7 | -| Workflow Memo | — | ✓ | 7 | ✓ | 8 | ✓ | 8 | -| Large Payloads | — | — | — | — | — | — | — | -| Deterministic APIs for Values | — | ✓ | 8 | — | — | — | — | -| Best Practices | — | ✓ | 9 | ✓ | 9 | ✓ | 9 | +| Section | Core | Python | Py# | TypeScript | TS# | Ruby | Rb# | Go | Go# | +|---------|------|--------|-----|------------|-----|------|-----|-----|-----| +| Overview | — | ✓ | 1 | ✓ | 1 | TODO | 1 | ✓ | 1 | +| Default Data Converter | — | ✓ | 2 | ✓ | 2 | TODO | 2 | ✓ | 2 | +| Pydantic Integration | — | ✓ | 3 | — | — | — | — | — | — | +| ActiveModel Integration | — | — | — | — | — | TODO | 3 | — | — | +| Custom Data Converter | — | ✓ | 4 | ✓ | 3 | TODO | 4 | ✓ | 3 | +| Composition of Payload Converters | — | — | — | ✓ | 4 | — | — | ✓ | 4 | +| Converter Hints | — | — | — | — | — | TODO | 5 | — | — | +| Protobuf Support | — | — | — | ✓ | 5 | — | — | ✓ | 5 | +| Payload Encryption | — | ✓ | 5 | ✓ | 6 | TODO | 6 | ✓ | 6 | +| Search Attributes | — | ✓ | 6 | ✓ | 7 | TODO | 7 | ✓ | 7 | +| Workflow Memo | — | ✓ | 7 | ✓ | 8 | TODO | 8 | ✓ | 8 | +| Large Payloads | — | — | — | — | — | — | — | — | — | +| Deterministic APIs for Values | — | ✓ | 8 | — | — | TODO | 9 | — | — | +| Best Practices | — | ✓ | 9 | ✓ | 9 | TODO | 10 | ✓ | 9 | ## Style Compliance @@ -23,10 +25,20 @@ |----------|--------|-------| | Python | ✓ reference | — | | TypeScript | ✓ aligned | — | +| Ruby | — | Not started | | Go | ✓ aligned | JSON default, protobuf native, converter.CompositeDataConverter | ## Status +**Ruby notes:** +- Default converter: nil, bytes, Protobuf, then JSON (using Ruby's `JSON` module with `create_additions: true`) +- Symbol keys become string keys on deserialization +- JSON Additions supported but not cross-language compatible +- ActiveModel: needs `ActiveModelJSONSupport` mixin for proper serialization +- Converter Hints: unique to Ruby — `workflow_arg_hint MyClass`, `workflow_result_hint MyClass` — needed because Ruby lacks type hints +- Search Attributes: `Temporalio::SearchAttributes::Key.new('name', type)`, `Temporalio::Workflow.upsert_search_attributes` +- Deterministic APIs: `Temporalio::Workflow.random` (SecureRandom replacement), `Temporalio::Workflow.now` (Time.now replacement), `Temporalio::Workflow.uuid` (UUID generation) + **Go-specific notes:** - Default Data Converter: Go uses `converter.NewCompositeDataConverter()` with JSON as default — chain: NilPayloadConverter, ByteSlicePayloadConverter, ProtoPayloadConverter, ProtoJSONPayloadConverter, JSONPayloadConverter - Custom Data Converter: implement `converter.DataConverter` interface @@ -39,10 +51,14 @@ **Intentionally missing (`—`):** - Core column: data handling is implementation-specific -- Pydantic Integration: Python-specific -- Deterministic APIs for Values: Python-specific; Go covers in determinism.md Safe Builtin Alternatives +- Pydantic Integration: Python-specific (TS uses plain JSON/types) +- ActiveModel Integration: Ruby-specific (equivalent of Pydantic) +- Composition of Payload Converters: TS/Go-specific section +- Converter Hints: Ruby-specific (`workflow_arg_hint`, `workflow_result_hint` — needed because Ruby lacks type annotations) +- Protobuf Support: TS/Go-specific section (Ruby/Python handle protobufs via default converter) +- Deterministic APIs for Values: Python has `workflow.uuid4()`, `workflow.random()`; Ruby has `Temporalio::Workflow.random/now/uuid`; Go covers in determinism.md - Large Payloads: Moved to core/patterns.md and core/gotchas.md -**Order alignment:** ✅ ALIGNED — Go sections follow same order as Python/TypeScript +**Order alignment:** ✅ ALIGNED — Ruby follows Python order with Ruby-specific additions (ActiveModel, Converter Hints) -**Style alignment:** ✅ Complete (Python, TypeScript) +**Style alignment:** ✅ Complete (Python, TypeScript, Go). Ruby: ~10 sections planned. diff --git a/.memory/alignment_checking/determinism-protection.md b/.memory/alignment_checking/determinism-protection.md index c0ef0f0..ef2805d 100644 --- a/.memory/alignment_checking/determinism-protection.md +++ b/.memory/alignment_checking/determinism-protection.md @@ -2,24 +2,28 @@ ## Section Inventory -| Section | Core | Python | Py# | TypeScript | TS# | Go | Go# | -|---------|------|--------|-----|------------|-----|-----|-----| -| Overview | — | ✓ | 1 | ✓ | 1 | ✓ | 1 | -| How the Sandbox Works | — | ✓ | 2 | — | — | — | — | -| Import Blocking | — | — | — | ✓ | 2 | — | — | -| Forbidden Operations | — | ✓ | 3 | — | — | — | — | -| Function Replacement | — | — | — | ✓ | 3 | — | — | -| workflowcheck Static Analysis | — | — | — | — | — | ✓ | 2 | -| Determinism Rules | — | — | — | — | — | ✓ | 3 | -| Pass-Through Pattern | — | ✓ | 4 | — | — | — | — | -| Importing Activities | — | ✓ | 5 | — | — | — | — | -| Disabling the Sandbox | — | ✓ | 6 | — | — | — | — | -| Customizing Invalid Module Members | — | ✓ | 7 | — | — | — | — | -| Import Notification Policy | — | ✓ | 8 | — | — | — | — | -| Disable Lazy sys.modules Passthrough | — | ✓ | 9 | — | — | — | — | -| File Organization | — | ✓ | 10 | — | — | — | — | -| Common Issues | — | ✓ | 11 | — | — | — | — | -| Best Practices | — | ✓ | 12 | — | — | ✓ | 4 | +| Section | Core | Python | Py# | TypeScript | TS# | Ruby | Rb# | Go | Go# | +|---------|------|--------|-----|------------|-----|------|-----|-----|-----| +| Overview | — | ✓ | 1 | ✓ | 1 | TODO | 1 | ✓ | 1 | +| How the Sandbox Works | — | ✓ | 2 | — | — | — | — | — | — | +| How Illegal Call Tracing Works | — | — | — | — | — | TODO | 2 | — | — | +| Import Blocking | — | — | — | ✓ | 2 | — | — | — | — | +| Forbidden Operations | — | ✓ | 3 | — | — | TODO | 3 | — | — | +| Function Replacement | — | — | — | ✓ | 3 | — | — | — | — | +| Durable Fiber Scheduler | — | — | — | — | — | TODO | 4 | — | — | +| workflowcheck Static Analysis | — | — | — | — | — | — | — | ✓ | 2 | +| Determinism Rules | — | — | — | — | — | — | — | ✓ | 3 | +| Pass-Through Pattern | — | ✓ | 4 | — | — | — | — | — | — | +| Importing Activities | — | ✓ | 5 | — | — | — | — | — | — | +| Disabling the Sandbox | — | ✓ | 6 | — | — | — | — | — | — | +| Disabling Illegal Call Tracing | — | — | — | — | — | TODO | 5 | — | — | +| Customizing Invalid Module Members | — | ✓ | 7 | — | — | — | — | — | — | +| Customizing Illegal Calls | — | — | — | — | — | TODO | 6 | — | — | +| Import Notification Policy | — | ✓ | 8 | — | — | — | — | — | — | +| Disable Lazy sys.modules Passthrough | — | ✓ | 9 | — | — | — | — | — | — | +| File Organization | — | ✓ | 10 | — | — | — | — | — | — | +| Common Issues | — | ✓ | 11 | — | — | TODO | 7 | — | — | +| Best Practices | — | ✓ | 12 | — | — | TODO | 8 | ✓ | 4 | ## Style Compliance @@ -27,10 +31,21 @@ |----------|--------|-------| | Python | ✓ reference | Comprehensive (12 sections) | | TypeScript | ✓ aligned | Minimal (3 sections) — V8 is automatic | +| Ruby | — | Not started | | Go | ✓ aligned | Minimal (4 sections) — no runtime sandbox, convention + static analysis | ## Status +**Ruby notes:** +- Ruby's approach is fundamentally different from Python (sandbox) and TS (V8): uses TracePoint for illegal call tracing + custom Fiber::Scheduler for durable fibers +- "How Illegal Call Tracing Works": TracePoint catches illegal calls on workflow thread, configurable via `illegal_workflow_calls` worker param +- "Durable Fiber Scheduler": Custom Fiber::Scheduler makes fibers deterministic; `Kernel.sleep`, `Mutex` etc. are disabled by default +- "Disabling Illegal Call Tracing": `Temporalio::Workflow::Unsafe.illegal_call_tracing_disabled` block +- "Customizing Illegal Calls": `illegal_workflow_calls` parameter on worker, `Temporalio::Worker.default_illegal_workflow_calls` +- `durable_scheduler_disabled` (implies `illegal_call_tracing_disabled`), `io_enabled` for IO wait +- Python's Import/Module sections don't apply (Ruby doesn't have module-level sandbox) +- Ruby estimated ~8 sections (moderate — more than TS's 3, less than Python's 12) + **Go-specific notes:** - Go has NO runtime sandbox (unlike Python's import-restricting sandbox or TS's V8 isolate) - Determinism enforcement is purely by developer convention + optional static analysis @@ -51,4 +66,5 @@ **Style alignment:** ⚠️ Very different structures (intentional, different protection mechanisms) - Python: Comprehensive (12 sections) — complex sandbox with many customization options - TypeScript: Minimal (3 sections) — V8 sandbox is mostly automatic +- Ruby: Moderate (~8 sections) — TracePoint + Fiber Scheduler with customization options - Go: Minimal (4 sections) — no sandbox, convention-based with static analysis tool diff --git a/.memory/alignment_checking/determinism.md b/.memory/alignment_checking/determinism.md index e70299a..2c1b413 100644 --- a/.memory/alignment_checking/determinism.md +++ b/.memory/alignment_checking/determinism.md @@ -2,19 +2,19 @@ ## Section Inventory -| Section | Core | Core# | Python | Py# | TypeScript | TS# | Go | Go# | -|---------|------|-------|--------|-----|------------|-----|-----|-----| -| Overview | ✓ | 1 | ✓ | 1 | ✓ | 1 | ✓ | 1 | -| Why Determinism Matters | ✓ | 2 | ✓ | 2 | ✓ | 2 | ✓ | 2 | -| Sources of Non-Determinism | ✓ | 3 | — | — | — | — | — | — | -| Central Concept: Activities | ✓ | 4 | — | — | — | — | — | — | -| SDK Protection / Sandbox | ✓ | 5 | ✓ | 6 | ✓ | 3 | — | — | -| Forbidden Operations | — | — | ✓ | 3 | ✓ | 4 | ✓ | 3 | -| Safe Builtin Alternatives | — | — | ✓ | 4 | — | — | ✓ | 4 | -| Detecting Non-Determinism | ✓ | 6 | — | — | — | — | — | — | -| Recovery from Non-Determinism | ✓ | 7 | — | — | — | — | — | — | -| Testing Replay Compatibility | — | — | ✓ | 5 | ✓ | 5 | ✓ | 5 | -| Best Practices | ✓ | 8 | ✓ | 7 | ✓ | 6 | ✓ | 6 | +| Section | Core | Core# | Python | Py# | TypeScript | TS# | Ruby | Rb# | Go | Go# | +|---------|------|-------|--------|-----|------------|-----|------|-----|-----|-----| +| Overview | ✓ | 1 | ✓ | 1 | ✓ | 1 | TODO | 1 | ✓ | 1 | +| Why Determinism Matters | ✓ | 2 | ✓ | 2 | ✓ | 2 | TODO | 2 | ✓ | 2 | +| Sources of Non-Determinism | ✓ | 3 | — | — | — | — | — | — | — | — | +| Central Concept: Activities | ✓ | 4 | — | — | — | — | — | — | — | — | +| SDK Protection / Sandbox | ✓ | 5 | ✓ | 6 | ✓ | 3 | TODO | 3 | — | — | +| Forbidden Operations | — | — | ✓ | 3 | ✓ | 4 | TODO | 4 | ✓ | 3 | +| Safe Builtin Alternatives | — | — | ✓ | 4 | — | — | TODO | 5 | ✓ | 4 | +| Detecting Non-Determinism | ✓ | 6 | — | — | — | — | — | — | — | — | +| Recovery from Non-Determinism | ✓ | 7 | — | — | — | — | — | — | — | — | +| Testing Replay Compatibility | — | — | ✓ | 5 | ✓ | 5 | TODO | 6 | ✓ | 5 | +| Best Practices | ✓ | 8 | ✓ | 7 | ✓ | 6 | TODO | 7 | ✓ | 6 | ## Style Compliance @@ -23,10 +23,18 @@ | Core | ✓ reference | Deep conceptual content | | Python | ✓ aligned | Practical focus | | TypeScript | ✓ aligned | Practical focus, V8 sandbox | +| Ruby | — | Not started | | Go | ✓ aligned | Practical focus, no sandbox, workflowcheck tool, workflow.* replacements | ## Status +**Ruby notes:** +- Ruby's determinism protection uses Illegal Call Tracing (TracePoint) + Durable Fiber Scheduler — distinct from Python sandbox and TS V8 sandbox +- Ruby's TracePoint catches illegal calls like `sleep`, `Time.now`, `Thread.new` at runtime +- Ruby has safe alternatives: `Temporalio::Workflow.sleep`, `Temporalio::Workflow.now`, `Temporalio::Workflow.random`, `Temporalio::Workflow.logger` +- Safe Builtin Alternatives section is appropriate for Ruby (similar to Python's table, but with Ruby-specific mappings) +- Forbidden Operations section should list Ruby-specific illegal calls (e.g., `Kernel.sleep`, `Time.now` without args, `Thread.new`, `IO` operations) + **Go-specific notes:** - SDK Protection: Go merged this into Overview (cross-references `determinism-protection.md` instead of having separate section). Marked `—` in table. - Testing Replay: Go cross-references `testing.md` rather than inlining code (matching Python style) @@ -39,16 +47,17 @@ - Sources of Non-Determinism: Core-only (conceptual categories) - Central Concept: Activities: Core-only (conceptual) - Forbidden Operations: Language-specific (Core covers in Sources) -- Safe Builtin Alternatives: Python has table, Go will have table, TS doesn't need (V8 sandbox handles automatically) +- Safe Builtin Alternatives: Python/Ruby/Go have tables; TS doesn't need (V8 sandbox handles automatically) - Detecting Non-Determinism: Core-only - Recovery from Non-Determinism: Core-only - Testing Replay Compatibility: Language-specific (Core covers in Detecting) **Order alignment:** N/A — different structures by design -**Style alignment:** ✓ Well aligned (Python, TypeScript) +**Style alignment:** ✓ Well aligned (Python, TypeScript, Go) - Core: Deep conceptual content (replay mechanism, commands/events, recovery) - Python: Practical focus (forbidden operations, safe alternatives table, sandbox) - TypeScript: Practical focus (V8 sandbox, forbidden operations) -- Go will follow Python pattern: forbidden operations + safe alternatives table + workflowcheck +- Ruby: Practical focus (TracePoint + Fiber Scheduler, forbidden calls, safe alternatives table) — ~7 sections +- Go: Practical focus (forbidden operations, safe alternatives table, workflowcheck) - Good division: Core explains "why", languages explain "how" diff --git a/.memory/alignment_checking/error-handling.md b/.memory/alignment_checking/error-handling.md index 6b4a8f2..25b8172 100644 --- a/.memory/alignment_checking/error-handling.md +++ b/.memory/alignment_checking/error-handling.md @@ -2,19 +2,19 @@ ## Section Inventory -| Section | Core | Python | Py# | TypeScript | TS# | Go | Go# | -|---------|------|--------|-----|------------|-----|-----|-----| -| Overview | — | ✓ | 1 | ✓ | 1 | ✓ | 1 | -| Application Errors/Failures | — | ✓ | 2 | ✓ | 2 | ✓ | 2 | -| Non-Retryable Errors | — | ✓ | 3 | — | — | ✓ | 3 | -| Activity Errors | — | — | — | ✓ | 3 | — | — | -| Handling Activity Errors in Workflows | — | ✓ | 4 | ✓ | 4 | ✓ | 4 | -| Retry Configuration | — | ✓ | 5 | ✓ | 5 | ✓ | 5 | -| Timeout Configuration | — | ✓ | 6 | ✓ | 6 | ✓ | 6 | -| Workflow Failure | — | ✓ | 7 | ✓ | 7 | ✓ | 7 | -| Cancellation Handling in Activities | — | — | — | — | — | — | — | -| Idempotency Patterns | — | — | — | — | — | — | — | -| Best Practices | — | ✓ | 8 | ✓ | 9 | ✓ | 8 | +| Section | Core | Python | Py# | TypeScript | TS# | Ruby | Rb# | Go | Go# | +|---------|------|--------|-----|------------|-----|------|-----|-----|-----| +| Overview | — | ✓ | 1 | ✓ | 1 | TODO | 1 | ✓ | 1 | +| Application Errors/Failures | — | ✓ | 2 | ✓ | 2 | TODO | 2 | ✓ | 2 | +| Non-Retryable Errors | — | ✓ | 3 | — | — | TODO | 3 | ✓ | 3 | +| Activity Errors | — | — | — | ✓ | 3 | — | — | — | — | +| Handling Activity Errors in Workflows | — | ✓ | 4 | ✓ | 4 | TODO | 4 | ✓ | 4 | +| Retry Configuration | — | ✓ | 5 | ✓ | 5 | TODO | 5 | ✓ | 5 | +| Timeout Configuration | — | ✓ | 6 | ✓ | 6 | TODO | 6 | ✓ | 6 | +| Workflow Failure | — | ✓ | 7 | ✓ | 7 | TODO | 7 | ✓ | 7 | +| Cancellation Handling in Activities | — | — | — | — | — | — | — | — | — | +| Idempotency Patterns | — | — | — | — | — | — | — | — | — | +| Best Practices | — | ✓ | 8 | ✓ | 9 | TODO | 8 | ✓ | 8 | ## Style Compliance @@ -22,10 +22,20 @@ |----------|--------|-------| | Python | ✓ reference | — | | TypeScript | ✓ aligned | Uses `log`, has retry defaults note | +| Ruby | — | Not started | | Go | ✓ aligned | Go-style error handling (errors.As, error returns, no exceptions) | ## Status +**Ruby notes:** +- `Temporalio::Error::ApplicationError` with `non_retryable:` parameter +- Any non-`ApplicationError` exception in a workflow causes workflow task failure (retried), NOT workflow failure +- Activity exceptions auto-converted to `ApplicationError` +- `Temporalio::RetryPolicy.new(max_interval:, initial_interval:, backoff_coefficient:, max_attempts:, non_retryable_error_types:)` +- Timeouts: `start_to_close_timeout`, `schedule_to_close_timeout`, `schedule_to_start_timeout` (same as other SDKs) +- `workflow_failure_exception_types` on Worker or `workflow_failure_exception_type` on Workflow class +- `next_retry_delay:` parameter on `ApplicationError` to override retry interval + **Go-specific notes:** - Go uses error returns (not exceptions) — `if err != nil` pattern - Application Errors: `temporal.NewApplicationError("msg", "type", details...)` and `temporal.NewNonRetryableApplicationError("msg", "type", cause, details...)` @@ -39,6 +49,6 @@ - Core column: error handling is implementation-specific - Activity Errors: TS-specific section (Go covers in Handling Activity Errors) -**Order alignment:** ✓ Aligned — Go# monotonically increases +**Order alignment:** ✓ Aligned — Ruby and Go# monotonically increase -**Style alignment:** ✅ Complete (Python, TypeScript) +**Style alignment:** ✅ Complete (Python, TypeScript, Go). Ruby: ~8 sections planned. diff --git a/.memory/alignment_checking/gotchas.md b/.memory/alignment_checking/gotchas.md index e83465f..72cadc8 100644 --- a/.memory/alignment_checking/gotchas.md +++ b/.memory/alignment_checking/gotchas.md @@ -2,26 +2,27 @@ ## Section Inventory -| Section | Core | Core# | Python | Py# | TypeScript | TS# | Go | Go# | -|---------|------|-------|--------|-----|------------|-----|-----|-----| -| Idempotency / Non-Idempotent Activities | ✓ | 1 | — | — | — | — | — | — | -| Replay Safety / Side Effects & Non-Determinism | ✓ | 2 | — | — | — | — | — | — | -| Multiple Workers with Different Code | ✓ | 3 | — | — | — | — | — | — | -| Retry Policies / Failing Activities Too Quickly | ✓ | 4 | — | — | — | — | — | — | -| Query Handlers / Query Handler Mistakes | ✓ | 5 | — | — | — | — | — | — | -| File Organization | ✓ | 6 | ✓ | 1 | — | — | — | — | -| Activity Imports | — | — | — | — | ✓ | 1 | — | — | -| Bundling Issues | — | — | — | — | ✓ | 2 | — | — | -| Async vs Sync Activities | — | — | ✓ | 2 | — | — | — | — | -| Goroutines and Concurrency | — | — | — | — | — | — | ✓ | 1 | -| Non-Deterministic Operations | — | — | — | — | — | — | ✓ | 2 | -| Error Handling | ✓ | 8 | — | — | — | — | — | — | -| Wrong Retry Classification | ✓ | 8 | ✓ | 3 | ✓ | 3 | ✓ | 3 | -| Heartbeating | — | — | ✓ | 5 | ✓ | 5 | ✓ | 4 | -| Cancellation | ✓ | 10 | ✓ | 4 | ✓ | 4 | ✓ | 5 | -| Testing | ✓ | 7 | ✓ | 6 | ✓ | 6 | ✓ | 6 | -| Timers and Sleep | — | — | ✓ | 7 | ✓ | 7 | ✓ | 7 | -| Payload Size Limits | ✓ | 9 | — | — | — | — | — | — | +| Section | Core | Core# | Python | Py# | TypeScript | TS# | Ruby | Rb# | Go | Go# | +|---------|------|-------|--------|-----|------------|-----|------|-----|-----|-----| +| Idempotency / Non-Idempotent Activities | ✓ | 1 | — | — | — | — | — | — | — | — | +| Replay Safety / Side Effects & Non-Determinism | ✓ | 2 | — | — | — | — | — | — | — | — | +| Multiple Workers with Different Code | ✓ | 3 | — | — | — | — | — | — | — | — | +| Retry Policies / Failing Activities Too Quickly | ✓ | 4 | — | — | — | — | — | — | — | — | +| Query Handlers / Query Handler Mistakes | ✓ | 5 | — | — | — | — | — | — | — | — | +| File Organization | ✓ | 6 | ✓ | 1 | — | — | TODO | 1 | — | — | +| Activity Imports | — | — | — | — | ✓ | 1 | — | — | — | — | +| Bundling Issues | — | — | — | — | ✓ | 2 | — | — | — | — | +| Async vs Sync Activities | — | — | ✓ | 2 | — | — | — | — | — | — | +| Goroutines and Concurrency | — | — | — | — | — | — | — | — | ✓ | 1 | +| Non-Deterministic Operations | — | — | — | — | — | — | — | — | ✓ | 2 | +| Error Handling | ✓ | 8 | — | — | — | — | — | — | — | — | +| Wrong Retry Classification | ✓ | 8 | ✓ | 3 | ✓ | 3 | TODO | 2 | ✓ | 3 | +| Heartbeating | — | — | ✓ | 5 | ✓ | 5 | TODO | 4 | ✓ | 4 | +| Cancellation | ✓ | 10 | ✓ | 4 | ✓ | 4 | TODO | 3 | ✓ | 5 | +| Testing | ✓ | 7 | ✓ | 6 | ✓ | 6 | TODO | 5 | ✓ | 6 | +| Timers and Sleep | — | — | ✓ | 7 | ✓ | 7 | TODO | 6 | ✓ | 7 | +| Payload Size Limits | ✓ | 9 | — | — | — | — | — | — | — | — | +| Illegal Call Tracing Gotchas | — | — | — | — | — | — | TODO | 7 | — | — | ## Style Compliance @@ -30,10 +31,20 @@ | Core | ✓ reference | Conceptual gotchas | | Python | ✓ aligned | Language-specific gotchas | | TypeScript | ✓ aligned | Language-specific gotchas | +| Ruby | — | Not started | | Go | ✓ aligned | Language-specific gotchas — goroutines, channels, selectors, map range | ## Status +**Ruby notes:** +- File Organization: Ruby class-per-file convention, `require_relative` for activities in workflows +- Wrong Retry Classification: `non_retryable: true` on `ApplicationError`, `non_retryable_error_types` in retry policy +- Cancellation: `Temporalio::Cancellation` tokens, detached cancellation for cleanup, `Error.canceled?` helper +- Heartbeating: `Temporalio::Activity::Context.current.heartbeat(details)`, heartbeat_details on retry +- Testing: common testing gotchas with `WorkflowExecutor::ThreadPool`, `activity_name` for mocking +- Timers and Sleep: `Temporalio::Workflow.sleep` vs `Kernel.sleep` (illegal), duration in seconds (Float) +- Illegal Call Tracing Gotchas: Ruby-specific — third-party gems triggering illegal calls, using `Unsafe.illegal_call_tracing_disabled` for safe workarounds, `durable_scheduler_disabled` for IO + **Go-specific notes:** - Goroutines and Concurrency: MUST use `workflow.Go()` not native `go`, `workflow.Channel` not native channels, `workflow.Selector` not native `select` - Non-Deterministic Operations: map range iteration, `time.Now()`/`time.Sleep()`, `math/rand`, accessing `os.Stdin`/`os.Stdout`/`os.Stderr`, anonymous functions as local activities (non-deterministic name — use named functions instead) @@ -45,7 +56,7 @@ **Decided to keep as-is:** - Multiple Workers with Different Code: Core-only (conceptual explanation sufficient) -- Heartbeating: Py/TS/Go-only (language-specific code examples, no Core conceptual section needed) +- Heartbeating: Py/TS/Ruby/Go-only (language-specific code examples, no Core conceptual section needed) **Intentionally missing (`—`):** - Idempotency, Replay Safety, Query Handlers, Error Handling, Retry Policies, Payload Size Limits: Core-only (conceptual) @@ -53,11 +64,12 @@ - File Organization: Core + Python; TS covers similar in Activity Imports; Go has simpler package model - Activity Imports: TS-specific (bundling/sandbox concerns) - Bundling Issues: TS-specific (workflow bundling) -- Async vs Sync Activities: Python-specific +- Async vs Sync Activities: Python-specific (Ruby activities run in executors but this is less of a gotcha) +- Illegal Call Tracing Gotchas: Ruby-specific **Order alignment:** N/A — Core has conceptual sections, language files have implementation-specific sections -**Style alignment:** ✅ Complete (Python, TypeScript) +**Style alignment:** ✅ Complete (Python, TypeScript, Go). Ruby: ~7 sections planned. - Core: 10 conceptual sections with symptoms/fixes - TypeScript: 7 sections (Activity Imports, Bundling, Cancellation, Heartbeating, Testing, Timers, Wrong Retry Classification) - Python: 7 sections (File Organization, Async vs Sync, Wrong Retry Classification, Cancellation, Heartbeating, Testing, Timers and Sleep) diff --git a/.memory/alignment_checking/language.md b/.memory/alignment_checking/language.md index 2ab9ecc..f07d35d 100644 --- a/.memory/alignment_checking/language.md +++ b/.memory/alignment_checking/language.md @@ -4,18 +4,18 @@ Tracks alignment for `python.md`, `typescript.md`, `go.md`, etc. ## Section Inventory -| Section | Core | Python | Py# | TypeScript | TS# | Go | Go# | -|---------|------|--------|-----|------------|-----|-----|-----| -| Overview | — | ✓ | 1 | ✓ | 1 | ✓ | 1 | -| How Temporal Works: History Replay | — | — | — | — | — | — | — | -| Understanding Replay | — | — | — | ✓ | 2 | — | — | -| Quick Start / Quick Demo | — | ✓ | 2 | ✓ | 3 | ✓ | 2 | -| Key Concepts | — | ✓ | 3 | ✓ | 4 | ✓ | 3 | -| File Organization Best Practice | — | ✓ | 4 | ✓ | 5 | ✓ | 4 | -| Determinism Rules | — | — | — | ✓ | 6 | — | — | -| Common Pitfalls | — | ✓ | 5 | ✓ | 7 | ✓ | 5 | -| Writing Tests | — | ✓ | 6 | ✓ | 8 | ✓ | 6 | -| Additional Resources | — | ✓ | 7 | ✓ | 9 | ✓ | 7 | +| Section | Core | Python | Py# | TypeScript | TS# | Ruby | Rb# | Go | Go# | +|---------|------|--------|-----|------------|-----|------|-----|-----|-----| +| Overview | — | ✓ | 1 | ✓ | 1 | TODO | 1 | ✓ | 1 | +| How Temporal Works: History Replay | — | — | — | — | — | — | — | — | — | +| Understanding Replay | — | — | — | ✓ | 2 | — | — | — | — | +| Quick Start / Quick Demo | — | ✓ | 2 | ✓ | 3 | TODO | 2 | ✓ | 2 | +| Key Concepts | — | ✓ | 3 | ✓ | 4 | TODO | 3 | ✓ | 3 | +| File Organization Best Practice | — | ✓ | 4 | ✓ | 5 | TODO | 4 | ✓ | 4 | +| Determinism Rules | — | — | — | ✓ | 6 | — | — | — | — | +| Common Pitfalls | — | ✓ | 5 | ✓ | 7 | TODO | 5 | ✓ | 5 | +| Writing Tests | — | ✓ | 6 | ✓ | 8 | TODO | 6 | ✓ | 6 | +| Additional Resources | — | ✓ | 7 | ✓ | 9 | TODO | 7 | ✓ | 7 | ## Style Compliance @@ -23,10 +23,20 @@ Tracks alignment for `python.md`, `typescript.md`, `go.md`, etc. |----------|--------|-------| | Python | ✓ reference | — | | TypeScript | ✓ aligned | Has Understanding Replay, Determinism Rules | +| Ruby | — | Not started | | Go | ✓ aligned | Function-based (no decorators), workflowcheck, struct activities | ## Status +**Ruby notes:** +- Overview: gem installation (`gem 'temporalio'`), Ruby 3.3+, macOS/Linux only +- Quick Start: Full tutorial with activity class, workflow class, worker, client (4 files like Python/TS) +- Key Concepts: Workflows as classes (`< Temporalio::Workflow::Definition`), Activities as classes (`< Temporalio::Activity::Definition`), `Temporalio::Workflow.execute_activity`, determinism via Illegal Call Tracing +- File Organization: Ruby class-based approach (one class per file convention) +- Common Pitfalls: Using `sleep` instead of `Temporalio::Workflow.sleep`, using `Time.now` instead of `Temporalio::Workflow.now`, non-deterministic gems in workflows +- Writing Tests: minitest with `Temporalio::Testing::WorkflowEnvironment` +- Additional Resources: ruby.temporal.io API docs, samples-ruby repo, Temporal 101 Ruby course + **Section content notes:** - Writing Tests: all languages should be a brief link to `references//testing.md`, NOT inline code examples @@ -44,9 +54,9 @@ Tracks alignment for `python.md`, `typescript.md`, `go.md`, etc. - Determinism Rules — TS has separate section; Python/Go have subsection in Key Concepts - Understanding Replay — TS-specific; Python/Go reference core -**Order alignment:** ✓ Aligned — All languages have similar structure (Overview, Quick Start, Key Concepts, File Organization, Common Pitfalls, Writing Tests, Additional Resources) +**Order alignment:** ✓ Aligned — Ruby follows Python order (no Understanding Replay or Determinism Rules sections) -**Style alignment:** ✅ Complete (Python, TypeScript) +**Style alignment:** ✅ Complete (Python, TypeScript, Go). Ruby: ~7 sections planned. - Removed "How Temporal Works" from TS (now brief "Understanding Replay" referencing core) - Added "File Organization Best Practice" to TS - Python Quick Demo and TypeScript Quick Start now match (full tutorial with 4 files, run instructions, expected output) diff --git a/.memory/alignment_checking/observability.md b/.memory/alignment_checking/observability.md index 3d56a89..7926e38 100644 --- a/.memory/alignment_checking/observability.md +++ b/.memory/alignment_checking/observability.md @@ -2,16 +2,16 @@ ## Section Inventory -| Section | Core | Python | Py# | TypeScript | TS# | Go | Go# | -|---------|------|--------|-----|------------|-----|-----|-----| -| Overview | — | ✓ | 1 | ✓ | 1 | ✓ | 1 | -| Logging / Replay-Aware Logging | — | ✓ | 2 | ✓ | 2 | ✓ | 2 | -| Customizing the Logger | — | ✓ | 2 | ✓ | 3 | ✓ | 3 | -| OpenTelemetry Integration | — | — | — | — | — | — | — | -| Metrics | — | ✓ | 3 | ✓ | 4 | ✓ | 4 | -| Search Attributes (Visibility) | — | ✓ | 4 | — | — | ✓ | 5 | -| Debugging with Event History | — | — | — | — | — | — | — | -| Best Practices | — | ✓ | 5 | ✓ | 5 | ✓ | 6 | +| Section | Core | Python | Py# | TypeScript | TS# | Ruby | Rb# | Go | Go# | +|---------|------|--------|-----|------------|-----|------|-----|-----|-----| +| Overview | — | ✓ | 1 | ✓ | 1 | TODO | 1 | ✓ | 1 | +| Logging / Replay-Aware Logging | — | ✓ | 2 | ✓ | 2 | TODO | 2 | ✓ | 2 | +| Customizing the Logger | — | ✓ | 2 | ✓ | 3 | — | — | ✓ | 3 | +| OpenTelemetry Integration | — | — | — | — | — | — | — | — | — | +| Metrics | — | ✓ | 3 | ✓ | 4 | TODO | 3 | ✓ | 4 | +| Search Attributes (Visibility) | — | ✓ | 4 | — | — | — | — | ✓ | 5 | +| Debugging with Event History | — | — | — | — | — | — | — | — | — | +| Best Practices | — | ✓ | 5 | ✓ | 5 | TODO | 4 | ✓ | 6 | ## Style Compliance @@ -19,10 +19,18 @@ |----------|--------|-------| | Python | ✓ reference | — | | TypeScript | ✓ aligned | Removed verbose sections | +| Ruby | — | Not started | | Go | ✓ aligned | workflow.GetLogger, slog integration, Tally/Prometheus metrics | ## Status +**Ruby notes:** +- Logging: `Temporalio::Workflow.logger` is replay-aware; `Temporalio::Activity::Context.current.logger` for activities +- Metrics: `Temporalio::Runtime::MetricsOptions` with Prometheus (`PrometheusMetricsOptions`) or custom `MetricBuffer` +- OpenTelemetry: `Temporalio::Contrib::OpenTelemetry::TracingInterceptor` — mentioned inline, not separate section (matching Python/TS style) +- Ruby has Unsafe.replaying? for side-effect guards: `unless Temporalio::Workflow::Unsafe.replaying?` +- Customizing the Logger: Ruby's `Temporalio::Workflow.logger` is straightforward; mention inline in Logging section (no separate section) + **Go-specific notes:** - Logging: `workflow.GetLogger(ctx)` for replay-safe workflow logging; `activity.GetLogger(ctx)` for activity logging - Customizing: Go 1.21+ supports `log.NewStructuredLogger(slog.New(...))` via `client.Options.Logger`; also supports custom `log.Logger` interface @@ -35,6 +43,6 @@ - OpenTelemetry / Debugging: Removed as too detailed - Search Attributes: Python/Go include; TS keeps in data-handling.md -**Order alignment:** ✓ Aligned — Go# monotonically increases +**Order alignment:** ✓ Aligned — Ruby follows Python order (compact, 4 sections) -**Style alignment:** ✅ Complete (Python, TypeScript) +**Style alignment:** ✅ Complete (Python, TypeScript, Go). Ruby should follow same concise structure. diff --git a/.memory/alignment_checking/patterns.md b/.memory/alignment_checking/patterns.md index 9485753..5224ea7 100644 --- a/.memory/alignment_checking/patterns.md +++ b/.memory/alignment_checking/patterns.md @@ -2,35 +2,37 @@ ## Section Inventory -| Section | Core | Python | Py# | TypeScript | TS# | Go | Go# | -|---------|------|--------|-----|------------|-----|-----|-----| -| Signals | ✓ | ✓ | 1 | ✓ | 1 | ✓ | 1 | -| Dynamic Signal Handlers | — | ✓ | 2 | ✓ | 2 | — | — | -| Queries | ✓ | ✓ | 3 | ✓ | 3 | ✓ | 2 | -| Dynamic Query Handlers | — | ✓ | 4 | ✓ | 4 | — | — | -| Updates | ✓ | ✓ | 5 | ✓ | 5 | ✓ | 3 | -| Child Workflows | ✓ | ✓ | 6 | ✓ | 6 | ✓ | 4 | -| Child Workflow Options | — | — | — | ✓ | 7 | ✓ | 4s | -| Handles to External Workflows | — | ✓ | 7 | ✓ | 8 | ✓ | 5 | -| Parallel Execution | ✓ | ✓ | 8 | ✓ | 9 | ✓ | 6 | -| Deterministic Asyncio Alternatives | — | ✓ | 9 | — | — | — | — | -| Selector Pattern | — | — | — | — | — | ✓ | 7 | -| Continue-as-New | ✓ | ✓ | 10 | ✓ | 10 | ✓ | 8 | -| Cancellation Handling (asyncio) | — | ✓ | 12 | — | — | — | — | -| Cancellation Scopes | — | — | — | ✓ | 12 | — | — | -| Cancellation Handling | — | — | — | — | — | ✓ | 9 | -| Saga Pattern | ✓ | ✓ | 11 | ✓ | 11 | ✓ | 10 | -| Triggers | — | — | — | ✓ | 13 | — | — | -| Wait Condition with Timeout | — | ✓ | 13 | ✓ | 14 | ✓ | 11 | -| Waiting for All Handlers to Finish | — | ✓ | 14 | ✓ | 15 | ✓ | 12 | -| Activity Heartbeat Details | ✓ | ✓ | 15 | ✓ | 16 | ✓ | 13 | -| Timers | ✓ | ✓ | 16 | ✓ | 17 | ✓ | 14 | -| Large Data Handling | ✓ | — | — | — | — | — | — | -| Local Activities | ✓ | ✓ | 17 | ✓ | 18 | ✓ | 15 | -| Entity Workflow Pattern | ✓ | — | — | — | — | — | — | -| Polling Patterns | ✓ | — | — | — | — | — | — | -| Idempotency Patterns | ✓ | — | — | — | — | — | — | -| Using Pydantic Models | — | ✓ | 18 | — | — | — | — | +| Section | Core | Python | Py# | TypeScript | TS# | Ruby | Rb# | Go | Go# | +|---------|------|--------|-----|------------|-----|------|-----|-----|-----| +| Signals | ✓ | ✓ | 1 | ✓ | 1 | TODO | 1 | ✓ | 1 | +| Dynamic Signal Handlers | — | ✓ | 2 | ✓ | 2 | TODO | 2 | — | — | +| Queries | ✓ | ✓ | 3 | ✓ | 3 | TODO | 3 | ✓ | 2 | +| Dynamic Query Handlers | — | ✓ | 4 | ✓ | 4 | TODO | 4 | — | — | +| Updates | ✓ | ✓ | 5 | ✓ | 5 | TODO | 5 | ✓ | 3 | +| Child Workflows | ✓ | ✓ | 6 | ✓ | 6 | TODO | 6 | ✓ | 4 | +| Child Workflow Options | — | — | — | ✓ | 7 | TODO | 7 | ✓ | 4s | +| Handles to External Workflows | — | ✓ | 7 | ✓ | 8 | TODO | 8 | ✓ | 5 | +| Parallel Execution | ✓ | ✓ | 8 | ✓ | 9 | TODO | 9 | ✓ | 6 | +| Deterministic Asyncio Alternatives | — | ✓ | 9 | — | — | — | — | — | — | +| Selector Pattern | — | — | — | — | — | — | — | ✓ | 7 | +| Continue-as-New | ✓ | ✓ | 10 | ✓ | 10 | TODO | 10 | ✓ | 8 | +| Cancellation Handling (asyncio) | — | ✓ | 12 | — | — | — | — | — | — | +| Cancellation Scopes | — | — | — | ✓ | 12 | — | — | — | — | +| Cancellation (Token-based) | — | — | — | — | — | TODO | 12 | — | — | +| Cancellation Handling | — | — | — | — | — | — | — | ✓ | 9 | +| Saga Pattern | ✓ | ✓ | 11 | ✓ | 11 | TODO | 11 | ✓ | 10 | +| Triggers | — | — | — | ✓ | 13 | — | — | — | — | +| Wait Condition with Timeout | — | ✓ | 13 | ✓ | 14 | TODO | 13 | ✓ | 11 | +| Waiting for All Handlers to Finish | — | ✓ | 14 | ✓ | 15 | TODO | 14 | ✓ | 12 | +| Activity Heartbeat Details | ✓ | ✓ | 15 | ✓ | 16 | TODO | 15 | ✓ | 13 | +| Timers | ✓ | ✓ | 16 | ✓ | 17 | TODO | 16 | ✓ | 14 | +| Large Data Handling | ✓ | — | — | — | — | — | — | — | — | +| Local Activities | ✓ | ✓ | 17 | ✓ | 18 | TODO | 17 | ✓ | 15 | +| Entity Workflow Pattern | ✓ | — | — | — | — | — | — | — | — | +| Polling Patterns | ✓ | — | — | — | — | — | — | — | — | +| Idempotency Patterns | ✓ | — | — | — | — | — | — | — | — | +| Using Pydantic Models | — | ✓ | 18 | — | — | — | — | — | — | +| Using ActiveModel | — | — | — | — | — | TODO | 18 | — | — | ## Style Compliance @@ -38,10 +40,21 @@ |----------|--------|-------| | Python | ✓ reference | — | | TypeScript | ✓ aligned | Uses `log`, CancellationScope idiom | +| Ruby | — | Not started | | Go | ✓ aligned | Channel-based signals, SetQueryHandler, SetUpdateHandler, Selector, compensation slice saga | ## Status +**Ruby notes:** +- Ruby uses `workflow_signal`, `workflow_query`, `workflow_update` class methods (not decorators) +- Entry point is `def execute` — no annotation needed (unlike Python's `@workflow.run`) +- Dynamic handlers use `dynamic: true` parameter +- Parallel execution uses `Temporalio::Workflow::Future.all_of` (not Promise.all or asyncio.gather) +- Continue-as-New raises `Temporalio::Workflow::ContinueAsNewError` (not a function call) +- Cancellation uses token-based `Temporalio::Cancellation` objects, similar to .NET — not scope-based (TS) or exception-based (Python) +- Child Workflow Options: Ruby has `parent_close_policy`, `cancellation_type` as params on `execute_child_workflow`/`start_child_workflow` +- `workflow_query_attr_reader` shorthand can be mentioned in Queries section + **Cross-language notes:** - **Updates — Validator constraints:** All languages (core, Python, TS, Go) now document that validators must NOT mutate state or block (read-only, like query handlers). Added in PR #38 review. - Cancellation Handling reordered before Saga in Go (Go# 9→10) so `NewDisconnectedContext` is introduced before Saga uses it @@ -77,11 +90,16 @@ - Cancellation Handling vs Cancellation Scopes: different idioms per language - Triggers: TS-specific pattern - Entity Workflow Pattern: conceptual in core, implementation left to user +- Deterministic Asyncio Alternatives: Python-specific (TS/Ruby don't have this issue) +- Cancellation (Token-based): Ruby-specific (uses `Temporalio::Cancellation` token objects) +- Cancellation Scopes: TS-specific (uses `CancellationScope`) +- Triggers: TS-specific pattern - Using Pydantic Models: Python-specific +- Using ActiveModel: Ruby-specific (equivalent of Pydantic) -**Order alignment:** ✓ Aligned — TS# and Go# monotonically increase +**Order alignment:** ✓ Aligned — TS#, Rb#, and Go# monotonically increase -**Style alignment:** ✅ All issues fixed (Python, TypeScript, Go) +**Style alignment:** ✅ All issues fixed (Python, TypeScript, Go). Ruby: ~18 sections planned. - ✅ **Queries:** TS now has "Important: must NOT modify state" note - ✅ **Updates:** All languages now have "validators must NOT mutate state or block" note - ✅ **Saga Pattern:** TS now has idempotency note, comments about saving compensation BEFORE activity diff --git a/.memory/alignment_checking/testing.md b/.memory/alignment_checking/testing.md index 500f07a..c4b7a4b 100644 --- a/.memory/alignment_checking/testing.md +++ b/.memory/alignment_checking/testing.md @@ -2,17 +2,17 @@ ## Section Inventory -| Section | Core | Python | Py# | TypeScript | TS# | Go | Go# | -|---------|------|--------|-----|------------|-----|-----|-----| -| Overview | — | ✓ | 1 | ✓ | 1 | ✓ | 1 | -| Test Environment Setup | — | ✓ | 2 | ✓ | 2 | ✓ | 2 | -| Time Skipping | — | — | — | — | — | — | — | -| Activity Mocking | — | ✓ | 3 | ✓ | 3 | ✓ | 3 | -| Testing Signals and Queries | — | ✓ | 4 | ✓ | 4 | ✓ | 4 | -| Testing Failure Cases | — | ✓ | 5 | ✓ | 5 | ✓ | 5 | -| Replay Testing | — | ✓ | 6 | ✓ | 6 | ✓ | 6 | -| Activity Testing | — | ✓ | 7 | ✓ | 7 | ✓ | 7 | -| Best Practices | — | ✓ | 8 | ✓ | 8 | ✓ | 8 | +| Section | Core | Python | Py# | TypeScript | TS# | Ruby | Rb# | Go | Go# | +|---------|------|--------|-----|------------|-----|------|-----|-----|-----| +| Overview | — | ✓ | 1 | ✓ | 1 | TODO | 1 | ✓ | 1 | +| Test Environment Setup | — | ✓ | 2 | ✓ | 2 | TODO | 2 | ✓ | 2 | +| Time Skipping | — | — | — | — | — | — | — | — | — | +| Activity Mocking | — | ✓ | 3 | ✓ | 3 | TODO | 3 | ✓ | 3 | +| Testing Signals and Queries | — | ✓ | 4 | ✓ | 4 | TODO | 4 | ✓ | 4 | +| Testing Failure Cases | — | ✓ | 5 | ✓ | 5 | TODO | 5 | ✓ | 5 | +| Replay Testing | — | ✓ | 6 | ✓ | 6 | TODO | 6 | ✓ | 6 | +| Activity Testing | — | ✓ | 7 | ✓ | 7 | TODO | 7 | ✓ | 7 | +| Best Practices | — | ✓ | 8 | ✓ | 8 | TODO | 8 | ✓ | 8 | ## Style Compliance @@ -20,10 +20,19 @@ |----------|--------|-------| | Python | ✓ reference | — | | TypeScript | ✓ aligned | Added failure/activity testing | +| Ruby | — | Not started | | Go | ✓ aligned | testsuite package, testify, mock activities, TestWorkflowEnvironment | ## Status +**Ruby notes:** +- Test Environment: `Temporalio::Testing::WorkflowEnvironment.start_local` (same dev server as other SDKs) +- Activity Mocking: Write fake activity classes with `activity_name :RealActivityName` to override +- Activity Testing: `Temporalio::Testing::ActivityEnvironment` for isolated activity tests +- Replay Testing: `Temporalio::Worker::WorkflowReplayer` with `replay_workflow`/`replay_workflows` +- Compatible with any test framework (minitest commonly used in samples) +- Ruby uses `Temporalio::Worker::WorkflowExecutor::ThreadPool.default` for test workers + **Go-specific notes:** - Test Environment: `testsuite.WorkflowTestSuite` + `testsuite.TestWorkflowEnvironment` from `go.temporal.io/sdk/testsuite` - Uses testify library (`suite.Suite`, `assert`, `mock`) @@ -39,6 +48,6 @@ - Core column: no core testing.md exists (implementation-specific) - Time Skipping: mentioned inline (built into test environment) -**Order alignment:** ✅ Aligned — Go sections match Python/TypeScript order +**Order alignment:** ✅ Aligned — Ruby and Go sections match Python/TypeScript order -**Style alignment:** ✅ Complete (Python, TypeScript) +**Style alignment:** ✅ Complete (Python, TypeScript, Go). Ruby should follow same 8-section structure. diff --git a/.memory/alignment_checking/versioning.md b/.memory/alignment_checking/versioning.md index 3df1f60..9f3c15c 100644 --- a/.memory/alignment_checking/versioning.md +++ b/.memory/alignment_checking/versioning.md @@ -2,17 +2,17 @@ ## Section Inventory -| Section | Core | Core# | Python | Py# | TypeScript | TS# | Go | Go# | -|---------|------|-------|--------|-----|------------|-----|-----|-----| -| Overview | ✓ | 1 | — | — | — | — | — | — | -| Why Versioning is Needed | ✓ | 2 | — | — | — | — | — | — | -| Patching API / GetVersion API | ✓ | 3 | ✓ | 1 | ✓ | 1 | ✓ | 1 | -| Workflow Type Versioning | ✓ | 4 | ✓ | 2 | ✓ | 2 | ✓ | 2 | -| Worker Versioning | ✓ | 5 | ✓ | 3 | ✓ | 3 | ✓ | 3 | -| Choosing a Strategy | ✓ | 6 | — | — | — | — | — | — | -| Best Practices | ✓ | 7 | ✓ | 4 | ✓ | 4 | ✓ | 4 | -| Finding Workflows by Version | ✓ | 8 | — | — | — | — | — | — | -| Common Mistakes | ✓ | 9 | — | — | — | — | — | — | +| Section | Core | Core# | Python | Py# | TypeScript | TS# | Ruby | Rb# | Go | Go# | +|---------|------|-------|--------|-----|------------|-----|------|-----|-----|-----| +| Overview | ✓ | 1 | — | — | — | — | — | — | — | — | +| Why Versioning is Needed | ✓ | 2 | — | — | — | — | — | — | — | — | +| Patching API / GetVersion API | ✓ | 3 | ✓ | 1 | ✓ | 1 | TODO | 1 | ✓ | 1 | +| Workflow Type Versioning | ✓ | 4 | ✓ | 2 | ✓ | 2 | TODO | 2 | ✓ | 2 | +| Worker Versioning | ✓ | 5 | ✓ | 3 | ✓ | 3 | TODO | 3 | ✓ | 3 | +| Choosing a Strategy | ✓ | 6 | — | — | — | — | — | — | — | — | +| Best Practices | ✓ | 7 | ✓ | 4 | ✓ | 4 | TODO | 4 | ✓ | 4 | +| Finding Workflows by Version | ✓ | 8 | — | — | — | — | — | — | — | — | +| Common Mistakes | ✓ | 9 | — | — | — | — | — | — | — | — | ## Style Compliance @@ -21,10 +21,16 @@ | Core | ✓ reference | Conceptual content | | Python | ✓ aligned | Code only, refs core | | TypeScript | ✓ aligned | Code only, refs core | +| Ruby | — | Not started | | Go | ✓ aligned | Uses `workflow.GetVersion` (not patching); code only, refs core | ## Status +**Ruby notes:** +- Patching: `Temporalio::Workflow.patched('my-patch')` and `Temporalio::Workflow.deprecate_patch('my-patch')` +- Workflow Type Versioning: Standard class duplication pattern (e.g., `MyWorkflowV2 < Temporalio::Workflow::Definition`) +- Worker Versioning: Supported in Ruby SDK v0.5.0+ with `versioning_behavior:` on workflow definition + **Go-specific notes:** - Go uses `workflow.GetVersion(ctx, changeID, minSupported, maxSupported)` — returns a `Version` (int) - Different from Python/TS `patched()`/`deprecatePatch()` — Go uses a version number approach @@ -43,4 +49,4 @@ **Order alignment:** ✓ Aligned — languages focus on code: Patching/GetVersion API, Type Versioning, Worker Versioning, Best Practices -**Style alignment:** ✅ Complete (Python, TypeScript) +**Style alignment:** ✅ Complete (Python, TypeScript, Go). Ruby: ~4 sections planned. diff --git a/.memory/correctness_checking/README.md b/.memory/correctness_checking/README.md index 98f0cac..1e18b41 100644 --- a/.memory/correctness_checking/README.md +++ b/.memory/correctness_checking/README.md @@ -9,27 +9,27 @@ Track verification of factual statements and code examples in reference files fo Each file in this directory tracks correctness for a corresponding reference file. Within each file, sections are organized by language (e.g., `## TypeScript`, `## Python`). -**Supported languages:** TypeScript, Python, Go +**Supported languages:** TypeScript, Python, Ruby, Go **Adding a new language:** Add a new `## {Language}` section to each relevant file with a Tracking table and Detailed Notes. ## Summary -| File | TypeScript | Python | Go | -|------|------------|--------|-----| -| patterns.md | ✅ | partial | ✅ | -| testing.md | ✅ | partial | ✅ | -| language.md | ✅ | partial | ✅ | -| versioning.md | ✅ | partial | ✅ | -| advanced-features.md | ✅ | partial | ✅ | -| data-handling.md | ✅ | partial | ✅ | -| determinism-protection.md | ✅ | partial | ✅ | -| determinism.md | ✅ | partial | ✅ | -| error-handling.md | ✅ | partial | ✅ | -| gotchas.md | ✅ | partial | ✅ | -| observability.md | ✅ | partial | ✅ | -| ai-patterns.md | — | partial | — | -| sync-vs-async.md | — | ✅ | — | +| File | TypeScript | Python | Ruby | Go | +|------|------------|--------|------|-----| +| patterns.md | ✅ | partial | partial | ✅ | +| testing.md | ✅ | partial | unchecked | ✅ | +| language.md | ✅ | partial | partial | ✅ | +| versioning.md | ✅ | partial | unchecked | ✅ | +| advanced-features.md | ✅ | partial | unchecked | ✅ | +| data-handling.md | ✅ | partial | unchecked | ✅ | +| determinism-protection.md | ✅ | partial | ✅ | ✅ | +| determinism.md | ✅ | partial | ✅ | ✅ | +| error-handling.md | ✅ | partial | unchecked | ✅ | +| gotchas.md | ✅ | partial | ✅ | ✅ | +| observability.md | ✅ | partial | ✅ | ✅ | +| ai-patterns.md | — | partial | — | — | +| sync-vs-async.md | — | ✅ | — | — | **Legend:** ✅ = all sections verified, partial = some sections need fixes, unchecked = not yet verified, — = N/A diff --git a/.memory/correctness_checking/language.md b/.memory/correctness_checking/language.md index 7707133..c803a5d 100644 --- a/.memory/correctness_checking/language.md +++ b/.memory/correctness_checking/language.md @@ -223,6 +223,45 @@ Correctness verification for `references/{language}/{language}.md` (e.g., typesc --- +## Ruby + +**File:** `references/ruby/ruby.md` (relative to skill root) + +### Tracking + +| # | Section | Status | Fix Applied | Sources | +|---|---------|--------|-------------|---------| +| 1 | Overview | all good | | sdk-ruby README | +| 2 | Quick Demo | FIXED | Added 'default' namespace to Client.connect | sdk-ruby README | +| 3 | Key Concepts | all good | | sdk-ruby README | +| 4 | File Organization | all good | | N/A | +| 5 | Common Pitfalls | all good | | N/A | +| 6 | Writing Tests | all good | | cross-reference | +| 7 | Additional Resources | all good | | cross-reference | + +### Detailed Notes + +#### 2. Quick Demo +**Status:** needs fixes + +**Issue:** `Temporalio::Client.connect('localhost:7233')` is missing the namespace argument. The SDK README and all official examples include namespace as the second positional argument. + +**Before:** +```ruby +client = Temporalio::Client.connect('localhost:7233') +``` + +**After:** +```ruby +client = Temporalio::Client.connect('localhost:7233', 'default') +``` + +This appears twice in ruby.md (worker.rb and execute_workflow.rb examples). + +**Source:** sdk-ruby README: `Temporalio::Client.connect('localhost:7233', 'my-namespace')` + +--- + ## Go diff --git a/.memory/correctness_checking/patterns.md b/.memory/correctness_checking/patterns.md index 1500eba..348d2ba 100644 --- a/.memory/correctness_checking/patterns.md +++ b/.memory/correctness_checking/patterns.md @@ -553,6 +553,73 @@ import { proxyLocalActivities } from '@temporalio/workflow'; --- +## Ruby + +**File:** `references/ruby/patterns.md` (relative to skill root) + +### Tracking + +| # | Section | Status | Fix Applied | Sources | +|---|---------|--------|-------------|---------| +| 1 | Signals | all good | | temporal-docs, sdk-ruby README | +| 2 | Dynamic Signal Handlers | all good | | temporal-docs message-passing | +| 3 | Queries | all good | | sdk-ruby README (workflow_query_attr_reader) | +| 4 | Dynamic Query Handlers | all good | | temporal-docs message-passing | +| 5 | Updates | all good | | temporal-docs message-passing | +| 6 | Child Workflows | all good | | temporal-docs child-workflows, ruby.temporal.io | +| 7 | Child Workflow Options | all good | | ruby.temporal.io start_child_workflow API | +| 8 | Handles to External Workflows | FIXED | Fixed signal call to use class method ref | temporal-docs message-passing | +| 9 | Parallel Execution | all good | | temporal blog (crash-proof fibers), Slack | +| 10 | Continue-as-New | all good | | temporal-docs continue-as-new | +| 11 | Saga Pattern | all good | | standard pattern, matches Python | +| 12 | Cancellation (Token-based) | all good | | sdk-ruby README (Fiber Scheduling and Cancellation) | +| 13 | Wait Condition with Timeout | all good | | sdk-ruby README (Timers and Conditions) | +| 14 | Waiting for All Handlers to Finish | FIXED | Added ? suffix to all_handlers_finished | ruby.temporal.io API reference | +| 15 | Activity Heartbeat Details | all good | | temporal-docs failure-detection, sdk-ruby README | +| 16 | Timers | all good | | sdk-ruby README | +| 17 | Local Activities | all good | | ruby.temporal.io execute_local_activity API | +| 18 | Using ActiveModel | all good | | cross-reference to data-handling.md | + +### Detailed Notes + +#### 8. Handles to External Workflows +**Status:** needs fixes + +**Issue:** Signal call on external handle uses wrong syntax. Currently passes workflow class and symbol separately. + +**Before:** +```ruby +handle.signal(TargetWorkflow, :data_ready, data_payload) +``` + +**After:** +```ruby +handle.signal(TargetWorkflow.data_ready, data_payload) +``` + +**Source:** temporal-docs message-passing docs show `handle.signal(WorkflowA.some_signal, 'some signal arg')` — the signal method takes a signal definition (class method generated by `workflow_signal`) as the first argument, not the workflow class. + +--- + +#### 14. Waiting for All Handlers to Finish +**Status:** needs fixes + +**Issue:** Method name missing Ruby boolean `?` suffix. The API reference at ruby.temporal.io lists it as `all_handlers_finished?`. + +**Before:** +```ruby +Temporalio::Workflow.wait_condition { Temporalio::Workflow.all_handlers_finished } +``` + +**After:** +```ruby +Temporalio::Workflow.wait_condition { Temporalio::Workflow.all_handlers_finished? } +``` + +**Source:** ruby.temporal.io Temporalio::Workflow class method summary + +--- + ## Go