Skip to content

Add temporal integration#9

Merged
hasithaa merged 31 commits intoballerina-platform:v2from
hasithaa:v2_runtime
Feb 3, 2026
Merged

Add temporal integration#9
hasithaa merged 31 commits intoballerina-platform:v2from
hasithaa:v2_runtime

Conversation

@hasithaa
Copy link
Copy Markdown
Contributor

@hasithaa hasithaa commented Feb 1, 2026

Fixes ballerina-platform/ballerina-library#8424

  • Added SignalFutureNative class to handle signal awaiting using Temporal's CompletablePromise.
  • Introduced TemporalFutureValue class to bridge Temporal's CompletablePromise with Ballerina's wait mechanism.
  • Enhanced WorkflowRuntime to support sending events with optional signal names.
  • Updated WorkflowNative to allow sending events with inferred signal names from event data structure.
  • Created EventExtractor utility methods to infer signal names and get events record type from process functions.
  • Added EventFutureCreator to create TemporalFutureValue instances for workflow events.
  • Modified WorkflowWorkerNative to inject events record into workflow function calls.

…n features

- Add WorkflowCodeAnalyzer for validating @process and @activity function signatures.
- Introduce WorkflowCodeModifier to transform workflow process functions and register them.
- Create WorkflowCompilerPlugin to integrate the analyzer and modifier into the compilation process.
- Define WorkflowConstants for shared constants used across the plugin.
- Implement WorkflowModifierContext to hold information about process modifications.
- Develop WorkflowSourceModifier to handle AST transformations for process functions.
- Add WorkflowValidatorTask for validating function signatures based on workflow semantics.
- Create ModuleUtils for managing workflow module information.
- Enhance ProcessRegistry to track activities associated with processes.
- Implement native functions in WorkflowNative for registering processes and retrieving registered workflows.
- Add functionality to clear the registry for testing purposes.
…rgument transformation in workflow source modifier
…rgument transformation in workflow source modifier
- Introduced tests for invalid workflow process scenarios:
  - `invalid_call_activity_no_annotation`: Ensures that calling a non-activity function results in WORKFLOW_107 error.
  - `invalid_direct_activity_call`: Validates that direct calls to activity functions raise WORKFLOW_108 error.

- Updated valid process examples to use ctx->callActivity() pattern for invoking activity functions.

- Enhanced the ProcessFunctionAnalysisTask to support validation of ctx->callActivity() calls, ensuring the first argument is an activity function.

- Implemented WorkflowValidatorTask to check for direct calls to activity functions and validate callActivity usage.

- Modified WorkflowSourceModifier to remove direct activity call transformations, enforcing ctx->callActivity() usage.

- Added native implementation for executing activity functions within the workflow context, ensuring proper error handling.

- Updated utility classes to check for Context parameters in process functions and convert types appropriately.
- Implemented various workflows including error handling, multi-activity, order processing, and simple workflows.
- Created corresponding test cases to validate the functionality of each workflow.
- Introduced a configuration file for Temporal server settings.
- Added utility functions for generating unique workflow IDs.
- Updated the test server to use a different default port for better compatibility.
- Enhanced the workflow runtime to automatically start the singleton worker if not already running.
- Added SignalFutureNative class to handle signal awaiting using Temporal's CompletablePromise.
- Introduced TemporalFutureValue class to bridge Temporal's CompletablePromise with Ballerina's wait mechanism.
- Enhanced WorkflowRuntime to support sending events with optional signal names.
- Updated WorkflowNative to allow sending events with inferred signal names from event data structure.
- Created EventExtractor utility methods to infer signal names and get events record type from process functions.
- Added EventFutureCreator to create TemporalFutureValue instances for workflow events.
- Modified WorkflowWorkerNative to inject events record into workflow function calls.
@hasithaa hasithaa requested a review from rdulmina as a code owner February 1, 2026 10:04
@hasithaa hasithaa requested review from Copilot and removed request for rdulmina February 1, 2026 10:05
@hasithaa hasithaa requested a review from rdulmina February 1, 2026 10:06
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds Temporal workflow orchestration capabilities to the Ballerina workflow module, introducing durable workflow execution with signal handling, activity management, and integration testing infrastructure.

Changes:

  • Added Temporal SDK integration with native Java implementations for workflow runtime, activities, and signal handling
  • Implemented compiler plugin for validating and transforming @Process and @Activity annotated functions
  • Created comprehensive integration test infrastructure with embedded Temporal test server
  • Enhanced workflow context with future-based signal handling using Temporal's CompletablePromise
  • Added type conversion utilities and error serialization for crossing Ballerina-Java-Temporal boundaries

Reviewed changes

Copilot reviewed 105 out of 107 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
spotbugs-exclude.xml Added exclusions for singleton patterns, lazy initialization, and intentional design patterns
settings.gradle Added workflow-native-test and workflow-integration-tests modules
native/build.gradle Added Temporal SDK, gRPC, Jackson, and supporting dependencies
native/src/main/java/**/*.java Core native implementations for Temporal integration (runtime, context, signals, futures)
native-test/**/*.java Embedded Temporal test server for integration testing
compiler-plugin/**/*.java Compiler plugin for validating workflow annotations and transforming code
compiler-plugin-tests/** Test cases for compiler plugin validation
integration-tests/** Comprehensive workflow integration tests with signal handling
ballerina/** Ballerina module API, types, context client, and configuration
build.gradle Shared test server infrastructure with automatic lifecycle management
.github/** Documentation and code ownership updates

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@codecov
Copy link
Copy Markdown

codecov Bot commented Feb 1, 2026

Codecov Report

❌ Patch coverage is 54.47890% with 1057 lines in your changes missing coverage. Please review.
✅ Project coverage is 54.53%. Comparing base (64a730d) to head (1589539).
⚠️ Report is 34 commits behind head on v2.

Files with missing lines Patch % Lines
...a/stdlib/workflow/worker/WorkflowWorkerNative.java 41.56% 216 Missing and 23 partials ⚠️
...allerina/stdlib/workflow/utils/EventExtractor.java 45.20% 85 Missing and 35 partials ⚠️
...erina/stdlib/workflow/runtime/WorkflowRuntime.java 43.60% 78 Missing and 19 partials ⚠️
...tdlib/workflow/compiler/WorkflowValidatorTask.java 69.42% 56 Missing and 40 partials ⚠️
...ib/workflow/runtime/nativeimpl/WorkflowNative.java 57.86% 64 Missing and 11 partials ⚠️
...na/stdlib/workflow/utils/CorrelationExtractor.java 37.77% 46 Missing and 10 partials ⚠️
...dlib/workflow/compiler/SendEventValidatorTask.java 61.41% 26 Missing and 23 partials ⚠️
...stdlib/workflow/context/WorkflowContextNative.java 40.74% 31 Missing and 1 partial ⚠️
integration-tests/signal_workflow.bal 18.42% 31 Missing ⚠️
...a/stdlib/workflow/context/TemporalFutureValue.java 31.11% 29 Missing and 2 partials ⚠️
... and 15 more
Additional details and impacted files
@@              Coverage Diff              @@
##                 v2       #9       +/-   ##
=============================================
- Coverage     66.66%   54.53%   -12.13%     
- Complexity        0      117      +117     
=============================================
  Files             2       40       +38     
  Lines             3     2325     +2322     
  Branches          0      446      +446     
=============================================
+ Hits              2     1268     +1266     
- Misses            1      852      +851     
- Partials          0      205      +205     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

…rkflows

- Added `CorrelationExtractor` utility class to extract correlation keys from workflow input and signal data.
- Introduced `SearchAttributeRegistry` to manage registration of Temporal Search Attributes for correlation keys.
- Enhanced `EventExtractor` to retrieve input and signal record types for correlation key extraction.
- Updated `WorkflowWorkerNative` to initialize `SearchAttributeRegistry` and register correlation keys during process registration.
- Implemented upsert functionality for correlation keys as Temporal Search Attributes in `WorkflowWorkerNative`.
- Added support for UUID v7 generation in `CorrelationExtractor` for unique workflow IDs.
- Updated SpotBugs exclusions to account for uncalled private methods related to correlation support.
- Implement CRM Sync workflow with activities for validating, finding, creating, and updating contacts.
- Create HTTP service for triggering CRM sync workflows and retrieving results.
- Add mock CRM backend for simulating contact operations.
- Introduce order processing workflow with activities for checking inventory and reserving stock.
- Develop HTTP service for order processing with endpoints for placing orders and checking status.
- Implement signal-based payment confirmation workflow with future-based handling.
- Add comprehensive README documentation for both CRM Sync and Order Processing samples.
@hasithaa hasithaa changed the base branch from v2 to main February 2, 2026 03:47
@hasithaa hasithaa changed the base branch from main to v2 February 2, 2026 03:48
TypeSymbol eventsType = null;

// Check first parameter - could be Context, input, or events
if (paramIndex < params.size()) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Condition is always true


// Check remaining parameters - they can be input and/or events
// The order should be: [Context], [input], [events]
while (paramIndex < params.size()) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shall we try to remove the while loop here? IMO while loop is an overkill here

if (returnTypeOpt.isPresent()) {
TypeSymbol returnType = returnTypeOpt.get();
if (!WorkflowPluginUtils.isSubtypeOfAnydataOrError(returnType, context.semanticModel())) {
reportDiagnostic(context, functionNode, WorkflowConstants.WORKFLOW_105,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should use the return type desc location as the diagnostic location

paramIndex++;
} else if (looksLikeContextType(firstParamType)) {
// First param looks like it should be Context but isn't the right type
reportDiagnostic(context, functionNode, WorkflowConstants.WORKFLOW_100,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to use relevent param location for diagnostic. let's update the other places as well

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's create a seperate issue to track this requirment.

Comment thread ballerina/context.bal Outdated
- Updated SignalAwaitWrapper to use Java records for SignalData and ContextInfo, improving code clarity and reducing boilerplate.
- Removed the SignalFutureNative class as it was redundant with the new signal handling approach.
- Enhanced TemporalFutureValue and WorkflowContextNative to utilize new record structures.
- Simplified event handling in EventInfo and WorkflowWorkerNative by leveraging record features.
- Improved type handling in SearchAttributeRegistry and TypesUtil, adopting modern Java features for better readability.
- Cleaned up unused methods and comments across various classes to streamline the codebase.
if (!arguments.isEmpty()) {
FunctionArgumentNode firstArg = arguments.get(0);
if (firstArg instanceof PositionalArgumentNode) {
PositionalArgumentNode posArg = (PositionalArgumentNode) firstArg;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable 'posArg' can be replaced with pattern variable

String methodName = remoteCallNode.methodName().name().text();

// Check if this is a callActivity call
if (WorkflowConstants.CALL_ACTIVITY_FUNCTION.equals(methodName)) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not check for the expression type being workoflow:Context. Samples like below get the unwanted errors

    A a = new;
    _ = a->callActivity(4);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why we need to do that, that is handled by the type checker. isn't it ?

Copy link
Copy Markdown
Contributor

@rdulmina rdulmina Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No its a valid ballerina code

client class A {
    remote function callActivity(int activityFunction) {
        
    } 
}

FunctionArgumentNode firstArg = arguments.get(0);
if (firstArg instanceof PositionalArgumentNode) {
PositionalArgumentNode posArg = (PositionalArgumentNode) firstArg;
ExpressionNode expression = posArg.expression();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ExpressionNode expression = posArg.expression();
ExpressionNode activityFuncExpr = posArg.expression();

return paramNames;
}

PositionalArgumentNode posArg = (PositionalArgumentNode) paramsArg;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable 'posArg' can be replaced with pattern variable

…and multiple no-arg activities. Refactor diagnostic codes to use WorkflowDiagnostic enum and update related validation logic. Introduce new test cases for invalid no-arg activity scenarios.
* Validates @Process function signature according to Agent.md semantics.
* <ul>
* <li>Optional first parameter: workflow:Context</li>
* <li>Optional input parameter: subtype of anydata</li>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We discussed not to disallow the no corelation for now right?. Because of that input should be required not optional

@hasithaa hasithaa merged commit bb91f0f into ballerina-platform:v2 Feb 3, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants