Commit f03edf5
authored
Kotlin SDK API Proposal (#104)
* Kotlin proposal stub
* Kotlin SDK proposal: API and implementation docs
API document (sdk-api.md):
- Kotlin idioms: Duration, null safety, coroutines
- Stub-less activity/workflow invocation using method references
- String-based activity execution for cross-language interop
- KWorkflowHandle<T> and KTypedWorkflowHandle<T, R> for typed operations
- SignalWithStart and UpdateWithStart operations
- KotlinPlugin for enabling coroutine support
- K-prefix naming convention for public types
- Complete migration guide from Java SDK
Implementation document (sdk-implementation.md):
- Unified worker architecture with pluggable WorkflowImplementationFactory
- KotlinCoroutineDispatcher for deterministic execution
- Reified generics for type-safe activity execution
- Return type handling for DataConverter (typeOf<R>())
- Detailed open questions with context and recommendations
Proposal overview (sdk-proposal.md):
- Updated to reflect coroutines as key idiom
- Links to API and implementation docs
* Kotlin SDK: Add cancellation documentation
- Add Cancellation section to API doc covering cooperative cancellation,
parallel execution, detached scopes with NonCancellable, and withTimeout
- Resolve Open Question #2: Kotlin built-in cancellation replaces CancellationScope
- Update complete example with cleanup activities and cancellation handling
* Kotlin SDK: Fix parameter order and rename condition to awaitCondition
- Rename KWorkflow.condition to KWorkflow.awaitCondition for clarity
- Fix parameter order to be consistent: (method/name, options, args...)
- Add implementation plan and detailed phase documents
* Kotlin SDK: Fix client API parameter order (options before args)
* Kotlin SDK: Fix signalWithStart parameter order
* Kotlin SDK: Fix client API parameter order in phase-2.4
* Delete outdated docs
* Add KWorkflowClient, KWorkerFactory, and KChildWorkflowHandle to API
- Add KWorkflowClient with DSL constructor and suspend functions for
startWorkflow, executeWorkflow, signalWithStart, updateWithStart
- Add KWorkerFactory that automatically enables KotlinPlugin
- Add KChildWorkflowHandle<T, R> for child workflow interaction (signal,
cancel, result) via startChildWorkflow and getChildWorkflowHandle
- Update implementation-plan.md with Phase 1 completion status
- Reorganize Phase 2 to include new client and worker APIs
- Remove api-implementation-discrepancies.md (was untracked)
* nexus images
* Add Java SDK API Parity section to design document
Documents the analysis of Java vs Kotlin SDK API differences:
- APIs not needed in Kotlin (delay, cancellation scopes, sync primitives, wrap)
- Cancellation support integration with Kotlin coroutines
- Remaining gaps organized by priority (search attributes, memo, cron APIs)
- KActivityInfo missing fields
* Update docs to reflect Phase 2 completion and retry implementation
- Mark Phase 2 as complete in implementation-plan.md
- Add KWorkflow.retry() to implemented APIs
- Update sdk-api.md to mark retry as implemented
* Update documentation to reflect current implementation status
- Mark KUpdateHandle as implemented in implementation-plan.md
- Update sdk-api.md Java SDK API Parity section with accurate status
- Most "High Priority" and "Medium Priority" gaps are now implemented
- Reorganize into "Implemented APIs" and "Remaining Gaps" sections
- Clarify KWorkerFactory vs unified architecture in sdk-implementation.md
- Remove duplicate phases section from sdk-proposal.md
* Update docs: KWorker moved to main module
- Update implementation-plan.md to reflect KWorker is now part of
temporal-kotlin worker package (not testing-only)
- KWorkerFactory.newWorker() now returns KWorker
- Mark Phase 2 commits (4-6) as complete in test framework plan
* Update implementation plan with updateWithStart and mocking completion
- Mark updateWithStart as complete with details on implemented methods
- Mark mocking support (3.2) as complete
* Update SDK API doc with updateWithStart design
Documents the implemented updateWithStart API:
- KWithStartWorkflowOperation class
- KUpdateWithStartOptions data class
- withStartWorkflowOperation factory methods
- startUpdateWithStart and executeUpdateWithStart methods
* Document dynamic handler registration APIs in Kotlin SDK
- Add Dynamic Handler Registration section with usage examples
- Add implemented APIs table for all handler registration methods
- Remove dynamic handler registration from Remaining Gaps (now implemented)
- Remove updateWithStart from Remaining Gaps (was implemented earlier)
* Refactor sdk-api.md into hierarchical documentation structure
Break down the large sdk-api.md (3,479 lines) into a navigable hierarchy:
- README.md: Main entry point with navigation
- kotlin-idioms.md: Duration, null safety, property syntax
- migration.md: Java SDK migration guide
- api-parity.md: Java SDK comparison and gaps
- workflows/: Workflow definition, signals/queries/updates, child workflows,
timers, cancellation, continue-as-new
- activities/: Definition, implementation, local activities, KActivity API
- client/: KWorkflowClient, workflow handles, signalWithStart, updateWithStart
- worker/: KWorkerFactory, KWorker setup
- configuration/: KOptions, data conversion, interceptors
- implementation/: Moved internal design docs (sdk-proposal, sdk-implementation,
implementation-plan, test-framework-*, suspend-activities-design)
All internal links verified and updated.
* Remove legacy getHeartbeatDetails(): Payloads? from KActivityInfo
The type-safe version on KActivityContext is the preferred API:
fun <T> getHeartbeatDetails(detailsClass: Class<T>): T?
inline fun <reified T> KActivityContext.getHeartbeatDetails(): T?
* Remove suspendHeartbeat API, keep only heartbeat()
Heartbeat is a short non-blocking operation, so a single heartbeat()
API is sufficient for both sync and suspend activities.
* Document Activity API design decisions in api-parity.md
- Single heartbeat() API for both sync and suspend activities
- Support for both sync and suspend activity methods
* Fix Null Safety section example in kotlin-idioms.md
Replace unrelated KActivity usage example with getHeartbeatDetails()
which demonstrates nullable return type and elvis operator.
* Remove @KWorkflowImpl parallel interface pattern from proposal
Java clients can call Kotlin suspend workflows using untyped stubs,
making the parallel interface pattern unnecessary. Updated docs to
show the simpler approach with Java interop via untyped stubs.
* Use typed activity call in workflow definition example
* Use typed activity call in README Quick Start example
* Use typed activity calls in timers-parallel.md examples
* Rename Next Steps to Related, add linear Next navigation
- Renamed "Next Steps" sections to "Related" across all docs
- Added "Next: <topic>" links for linear document traversal
- Reading order follows README structure: Idioms → Config → Workflows → Activities → Client → Worker → Migration → API Parity
* Add Start Review link to README as entry point for linear navigation
* Expand kotlin-idioms.md with suspend functions, concurrency, cancellation, timeouts
Added sections for:
- Suspend functions (workflow and activity methods)
- Coroutines and concurrency (async, awaitAll, coroutineScope)
- Cancellation patterns (CancellationException, NonCancellable)
- Timeouts (withTimeout, withTimeoutOrNull)
- Mapping tables showing Kotlin patterns to Temporal/Java equivalents
* Improve kotlin-idioms.md flow and content
- Add opening summary table of Java→Kotlin mappings
- Streamline code examples (less verbose)
- Improve table descriptions (Purpose instead of Temporal Equivalent)
- Add Data Classes section for DTOs with @serializable
- Remove redundant Property Syntax section (already in Suspend Functions)
- Clean up Null Safety section (remove unrelated type mappings)
* Replace directory links with README.md links
All links to directories now point to README.md files:
- ./configuration/ → ./configuration/README.md
- ../workflows/ → ../workflows/README.md
- etc.
* Remove implementation links from design review documents
Implementation details are internal and not part of the API design review.
* Add activity definition and implementation to Quick Start example
- Added GreetingActivities interface with @ActivityInterface
- Added GreetingActivitiesImpl class
- Added worker.registerActivitiesImplementations() call
* Remove Complete Example reference from README
* Remove Complete Example section from workflows/README.md
* Remove implementation note from koptions.md
* Remove implementation note from activities/definition.md
* Refactor interceptor API to use suspend functions consistently
- Change KWorkflowOutboundCallsInterceptor to use suspend functions
instead of returning Deferred (more idiomatic Kotlin)
- Remove newTimer() - use async { delay() } instead
- Replace executeChildWorkflow with startChildWorkflow returning handle
- Update getChildWorkflowHandle to use method reference for type inference
- Remove metrics, tracing, auth interceptor examples (keep logging only)
- Add duration and error logging to LoggingWorkflowInterceptor
- Add executeUpdate to LoggingWorkflowInterceptor
- Add Kotlin calling Java workflows section to definition.md
- Fix child-workflows.md intro to not forward-reference activities
* Remove getChildWorkflowHandle - use external workflow handle instead
Java SDK doesn't have getChildWorkflowHandle, only newExternalWorkflowStub
for signaling external workflows. Removed from Kotlin SDK docs to match.
* Add runId to KChildWorkflowHandle
* Change KChildWorkflowHandle to use suspend getExecution()
Replace firstExecutionRunId and runId properties with suspend fun
getExecution() that returns WorkflowExecution. Matches Java SDK's
ChildWorkflowStub.getExecution() pattern - suspends until child starts.
* Simplify KChildWorkflowHandle: use suspend fun runId() instead of getExecution()
* Remove contextPropagators from KContinueAsNewOptions
* Use Kotlin properties instead of getter methods in API
Replace getter methods with idiomatic Kotlin properties:
- KWorkflow.getInfo() → KWorkflow.info
- KActivity.getContext() → KActivity.context
- KActivity.getInfo() → KActivity.info
- Other getter patterns → property access
Update api-parity.md table to show property-based API.
* Fix client documentation consistency
- Use KWorkflowOptions instead of WorkflowOptions in workflow-handle.md
- Change KWithStartWorkflowOperation.getResult() to suspend fun result()
* Remove stale interceptor references from registration example
* Simplify activity implementation - remove @KActivityImpl
- Activity interfaces can have both suspend and non-suspend methods
- Worker handles both automatically
- Java interop uses string-based activity names (like workflows)
- Remove parallel interface pattern and @KActivityImpl annotation
* Fix heartbeatDetails API - use reified generic and consistent naming
- Rename getHeartbeatDetails() to heartbeatDetails<T>()
- Use reified generic for type-safe deserialization
- Usage: context.heartbeatDetails<Int>() ?: 0
* Move KActivity API from local-activities.md to implementation.md
* Show suspend method support in local activities example
* Remove 'When to Use Local Activities' - assumes Temporal knowledge
* Document KActivity.context availability for local activities
- KActivity.context available for both regular and local activities
- heartbeat() is no-op for local activities
- heartbeatDetails() returns null for local activities
- taskToken and doNotCompleteOnReturn() throw for local activities
- Add isLocal property to KActivityInfo
* Add KActivity.context limitations table to local-activities.md
* Make SignalWithStart and UpdateWithStart consistent
Both now use KWithStartWorkflowOperation:
- withStartWorkflowOperation() creates the start operation
- signalWithStart(startOp, signal, arg) sends signal
- executeUpdateWithStart(startOp, update, options, arg) executes update
- startUpdateWithStart(startOp, update, options, arg) starts update async
Simplified KUpdateWithStartOptions - removed startWorkflowOperation field
* Change KWithStartWorkflowOperation from class to interface
* Simplify with-start API and use KSuspendFunction consistently
- withStartWorkflowOperation now returns KTypedWorkflowHandle directly
(handle is not usable until signalWithStart/updateWithStart is called)
- signalWithStart returns void instead of handle
- Remove separate KWithStartWorkflowOperation interface
- Use KSuspendFunction for workflow methods, signals, and updates
- Keep KFunction for queries (queries are not suspend)
* Clean up worker setup documentation
- Remove maxWorkflowThreadCount example (not needed for coroutines)
- Remove redundant Complete Worker Example section
* Use idiomatic Kotlin naming in API parity doc
- Use property syntax instead of get* methods for KWorkflow APIs:
- getTypedSearchAttributes() → typedSearchAttributes
- getMemo() → memo
- getLastCompletionResult<T>() → lastCompletionResult<T>()
- getVersion() → version()
- Add KActivityInfo properties (previously listed as gaps):
- workflowType
- currentAttemptScheduledTimestamp
- retryOptions
* Update Kotlin SDK spec based on gap validation analysis
- Update dynamic handler signatures to use KEncodedValues
- Change query methods to suspend functions
- Update signal types to KFunction
- Add resultClass param to getUpdateHandle
- Document additional properties and constraints
- Note architectural change: handle interfaces → classes
* Add testing documentation and navigation fixes
- Add testing.md with KTestWorkflowEnvironment, time skipping, mocking
- Add external-workflows.md for signal/cancel external workflows
- Fix navigation links throughout documentation
- Update various docs based on gap analysis
* Kotlin SDK API Proposal
This proposal defines the public API for the Temporal Kotlin SDK, providing
an idiomatic Kotlin experience using coroutines and suspend functions.
Key features:
- Coroutine-based workflows with suspend functions
- Type-safe activity and workflow execution via method references
- Native Kotlin Duration support
- KOptions data classes for configuration
- Full interoperability with Java SDK
Documentation includes:
- Workflow definition, signals, queries, updates
- Activity execution (regular and local)
- Child and external workflow patterns
- Client API with typed handles
- Worker setup and interceptors
- Testing utilities
- Migration guide from Java SDK
* Expand migration guide with comprehensive API mapping
* Expand migration guide with comprehensive API mapping
* Add interfaceless workflow/activity proposal as open question
Add "Decision Needed" sections to activity and workflow definition
docs proposing Python SDK-style interfaceless definitions where
activities and workflows can be defined directly on implementation
classes without requiring separate interfaces.
* Add open questions document and cross-link discussions
- Create open-questions.md to centralize API design decisions
- Add link to open questions in main README reference section
- Link activity and workflow definition docs to full discussion
* Add Claude instructions with open questions guidance
Document the process for adding API design questions that need
discussion before implementation, including format for the central
open-questions.md and inline sections in proposal docs.
* Add KArgs type-safe activity arguments as open question
Propose using typed KArgs classes instead of varargs for compile-time
type safety when invoking activities with multiple arguments.
* Add 0-arg versions and child workflow/client examples to KArgs proposal
Include examples for activities, child workflows, and client workflow
execution with 0, 1, and multiple arguments.
* Add three options for type-safe activity/workflow arguments
- Option A: Keep current varargs (no type safety)
- Option B: Direct overloads (0-7 arguments, no wrapper)
- Option C: KArgs wrapper classes (fewer overloads)
Include comparison table showing trade-offs between options.
* Add data classes vs builder+DSL open question
* Update Kotlin SDK proposal with API refinements and open questions
- Add open questions document covering interfaceless workflows/activities,
type-safe activity arguments, and data classes vs builder+DSL pattern
- Refine API documentation with Kotlin idioms (suspend functions, properties)
- Add testing documentation and implementation design docs
- Expand migration guide with comprehensive API mapping
- Various documentation fixes and improvements
* Document that default parameter values are not allowed
* Rename KActivityContext to KActivityExecutionContext, remove logger
* Remove heartbeatDetails from KActivityInfo (use KActivityExecutionContext instead)
* Fix KLocalActivityOptions to match Java LocalActivityOptions
- Remove priority (not in Java)
- Add scheduleToStartTimeout
- Add doNotIncludeArgumentsIntoMarker
* Update Kotlin SDK API docs based on PR review decisions
Key changes:
- Add KWorkflow.delay() with optional KTimerOptions
- Rename typedSearchAttributes to searchAttributes throughout
- Rename getWorkflowHandle() to workflowHandle() with result type overload
- Add KWorkflowClient.connect(options) pattern
- Update handle type hierarchy: KWorkflowHandleUntyped -> KWorkflowHandle<T> -> KWorkflowHandleWithResult<T, R>
- Add KStartUpdateOptions/KUpdateOptions with waitForStage required
- Add KWorkflowExecutionInfo base class for listWorkflows()
- Add KWorkflowClientInterceptor for client-side interception
- Clarify cancellation docs re: standard Kotlin behavior
- Recommend factory.run() pattern over start()
* Remove .idea and .claude directories from tracking
Add .gitignore to prevent IDE and tool-specific files from being committed.
* Remove CLAUDE.md from tracking
* Add enhanced nested DSL ergonomics suggestion to open-questions
* Update API proposal based on PR review round 2
- Q1: Allow default parameters for 0-1 argument case (align with Python/.NET/Ruby)
- Q5: Follow Python/.NET pattern for worker options (pass workflows/activities at construction)
- Q6: Heartbeat infallible, cancellation via coroutine or CompletableFuture
- Q7: Only show annotations when customizing names (consistency cleanup)
- Q8: Add KWorkflow.delay() with and without summary parameter
- Q9: Rename KotlinPlugin to KotlinJavaWorkerPlugin
* Address PR review round 2 comments
- Q3: Use KArgs approach for type-safe activity/workflow arguments
- Q11: Heartbeat throws CancellationException on cancellation (prevents slot eating)
- Q12: Unified KClient matching Python/.NET pattern (workflows, schedules, async completion)
- R1-Q5: Use KWorkflow.version() method instead of getter-style
Key changes:
- Rename KWorkflowClient to KClient throughout
- Add schedule and async activity completion APIs to KClient
- Update heartbeat to throw on cancellation, add TODO for cancellationFuture
- Mark KArgs (Option C) as decided in open-questions.md
* Address PR review comments Q20-Q24
- Use KActivityContext.current() pattern instead of KActivity (Q20)
- Remove KActivity.logger()/KWorkflow.logger(), use MDC with standard logging (Q21)
- Keep single-argument heartbeat, rename to lastHeartbeatDetails<T>() (Q22)
- Document event loop implementation on top of Java SDK (Q24)
Updated files:
- activities/implementation.md
- activities/local-activities.md
- workflows/definition.md
- configuration/interceptors.md
- migration.md
- implementation/implementation-plan.md
* Add run() method to KWorker API
Following Python SDK pattern, KWorker now has:
- run() - recommended, blocks until shutdown, propagates fatal errors
- start()/shutdown() - for advanced manual control scenarios
Updated examples to use run() as the primary pattern.
---------
Co-authored-by: Maxim Fateev <1463622+mfateev@users.noreply.github.com>1 parent dbf0908 commit f03edf5
44 files changed
Lines changed: 12255 additions & 0 deletions
File tree
- kotlin
- activities
- client
- configuration
- implementation
- worker
- workflows
- nexus/images
- tasks
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
0 commit comments