-
Notifications
You must be signed in to change notification settings - Fork 846
feat(csharp): add C# (.NET 9) language support #769
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
…d documentation Days 13-14: Additional Step Types - Add test fixtures for all C# step types (event, cron, noop) - Add comprehensive config parsing tests for all step types - Verify all 4 step types work correctly (api, event, cron, noop) - All tests passing with no implementation changes needed Days 15-16: Final Polish - Enhance error handling in C# runner with detailed messages - Compilation errors with full diagnostics - Missing Config/Handler with helpful examples - JSON parsing errors with clear indication - Runtime exceptions with type, message, inner exception, stack trace - Verify cross-platform compatibility (.NET 9 on macOS ARM64) - Document performance characteristics - All tests passing with no regressions Days 17-18: Documentation - Update README.md with C# Beta status in language support table - Update packages/core/README.md with C# runner details - Create comprehensive C# guide at docs/development-guide/csharp/ - Prerequisites and quick start - All 4 step types with examples - Complete Context API documentation - JSON handling, error handling, testing strategies - Performance considerations and troubleshooting - Known beta limitations clearly documented Test Results: - Core tests: 60 passed (all C# tests passing) - Integration tests: simpleCSharp.spec.ts passing (9.681s) - No regressions in existing functionality Status: C# support is now in BETA - fully functional and ready for real-world testing
…idation - Add comprehensive E2E tests for C# template validation (csharp-support.spec.ts) - Add multi-language workflow E2E tests (multi-language.spec.ts) - Update CLI validation tests to support C# template - Add test scripts: test:pr:csharp, test:release:csharp, validate:release - Create CSHARP_EXAMPLES_GUIDE.md with 6 example blueprints for motia-examples repo - Add automated release validation script (validate-release.ts) - All 13 core validation checks passing Days 19-20 of C# implementation plan complete.
Move CSHARP_EXAMPLES_GUIDE.md to packages/core/src/csharp/EXAMPLES_GUIDE.md to keep it with the C# implementation code.
Implements full request-response RPC communication for C# steps, enabling State.Get() to return actual values instead of null. Changes: - Added request ID tracking with TaskCompletionSource in MotiaRpc.cs - Implemented SendRequestAndWaitAsync() with 30s timeout - Started background thread in Program.cs to read RPC responses from stdin - Updated rpcSendWithResult to use new async RPC instead of returning null - Node.js RpcStdinProcessor already sends responses - C# now reads them Tests: - Added unit test for State.Get() in server.test.ts (passes) - Updated integration test expectations (enriched: 'yes' now works) - Added E2E tests for bidirectional state operations - Updated multi-language tests to validate state persistence Documentation: - Removed State.Get() limitation warnings from C# docs - Updated validation script to check for bidirectional RPC - Changed all 'Beta limitation' references to 'Stable' status Result: C# steps now have complete state management capabilities and can fully participate in stateful workflows across all languages. Closes Days 21-23 of C# implementation plan.
|
@stimpy77 is attempting to deploy a commit to the motia Team on Vercel. A member of the Team first needs to authorize it. |
|
Excellent PR! Thank you for creating this. We have had at least one other contribution for adding C# to Motia. And we definitely intend to do this. Right now, we are in the process of creating a plugin/package system for runtimes (as well as other components of Motia) which will make it much easier to contribute these kinds of additions. After this refactoring is done, it should even be possible to create your own runtime (or use other open source runtime implementations) even if we don't plan to officially support it. We do plan to officially support C# though and I believe that the majority of this PR can be used in the package/plugin implementation once we are done. With that said, I will chat with the team about this, but it is likely that we will not merge this PR directly and instead, wait for the refactoring and use the code here to implement C# or ask that you migrate this code to the new runtiime plugin implementation. Thanks again! this looks great. |
|
|
| throw new Error(`Step file not found: ${stepFilePath}`) | ||
| } | ||
|
|
||
| const { traceId, data } = eventData |
Check notice
Code scanning / CodeQL
Unused variable, import, function or class
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
resolved
| */ | ||
|
|
||
| const fs = require('fs') | ||
| const path = require('path') |
Check notice
Code scanning / CodeQL
Unused variable, import, function or class
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
resolved
| @@ -0,0 +1,183 @@ | |||
| import { expect, test } from '@/src/motia-fixtures' | |||
| import { execSync } from 'child_process' | |||
| import { existsSync, writeFileSync, mkdirSync } from 'fs' | |||
Check notice
Code scanning / CodeQL
Unused variable, import, function or class
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
resolved
| }) | ||
|
|
||
| test('should maintain state across language boundaries', async ({ workbench, api }) => { | ||
| const template = process.env.MOTIA_TEST_TEMPLATE || 'nodejs' |
Check notice
Code scanning / CodeQL
Unused variable, import, function or class
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
resolved
| }) | ||
|
|
||
| test('should handle errors consistently across languages', async ({ workbench, logsPage, api }) => { | ||
| const template = process.env.MOTIA_TEST_TEMPLATE || 'nodejs' |
Check notice
Code scanning / CodeQL
Unused variable, import, function or class
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
resolved
|
Hey @stimpy77 I'm sorry for leaving you hanging on this PR for a while. We're working on a new core abstraction to help new language runtimes be straightforward, it should also work with any other frameworks out these. I will keep you posted when we change it. We couldn't merge it because we couldn't confidently verify the implementation then we realized the way we were implementing in the core wasn't the ideal one to allow community to build new language runtimes. |
feat(csharp): Add C# (.NET 9) language support
🎯 Summary
Adds complete C# language support to Motia, enabling developers to write steps in C#/.NET 9 alongside TypeScript, JavaScript, Python, and Ruby. This PR implements full bidirectional RPC communication, allowing C# steps to fully participate in stateful workflows with complete state management capabilities.
Status: ✅ Production-ready (Stable)
🚀 What's New
Core Features
State.Set()andState.Get()fully functionalDeveloper Experience
motia create -t csharptemplate.step.csfilesTesting & Documentation
📋 Changes by Category
Core Package (
packages/core)New Files:
src/csharp/Program.cs- Main C# runner with Roslyn scriptingsrc/csharp/MotiaRpc.cs- Bidirectional RPC protocol implementationsrc/csharp/MotiaContext.cs- Context API (emit, state, logger, tracer)src/csharp/MotiaRunner.csproj- .NET 9 project configurationsrc/__tests__/steps/api-step-state.cs- State.Get() test fixtureModified Files:
src/get-step-language.ts- Added C# detection (.step.cs)src/call-step-file.ts- Added C# execution pathsrc/process-communication/communication-config.ts- C# uses RPC modesrc/step-handler-rpc-stdin-processor.ts- Response sending to C# processsrc/__tests__/get-config.test.ts- Added C# config parsing testssrc/__tests__/server.test.ts- Added C# API execution and State.Get() testsCLI Package (
packages/snap)Template & Build:
src/create/templates/csharp/- Complete C# project template (petstore example)src/create-step/templates/*/template.csharp.txt- Step creation templatessrc/cloud/build/builders/csharp/index.ts- C# cloud deployment buildersrc/install.ts- .NET SDK detection and validationsrc/create/index.ts- C# template registrationWorkbench Package (
packages/workbench)No changes needed - C# steps display automatically in workbench with correct language indicators
Documentation (
packages/docs)New Documentation:
content/docs/development-guide/csharp/index.mdx- Complete C# guide covering:Updated Documentation:
README.md- Added C# to language support tablepackages/core/README.md- Documented C# runnerTesting (
packages/e2e)New E2E Tests:
tests/integration/csharp-support.spec.ts- 9 tests validating:tests/integration/multi-language.spec.ts- Enhanced with:Updated Tests:
tests/release/cli/cli-validation.spec.ts- C# template supportscripts/validate-release.ts- Updated to check for bidirectional RPC completionPlayground Integration Tests
New Tests:
integration-tests/simpleCSharp.spec.ts- Full end-to-end C# workflowsteps/simpleCSharp/api_endpoint_step.cs- API step that sets statesteps/simpleCSharp/test_event_step.cs- Event step that gets statesteps/simpleCSharp/tested_event_step.cs- Event subscriberUpdated Tests:
enriched: 'yes'now works (was'no'in MVP)🔧 Implementation Details
Bidirectional RPC Architecture (Days 21-23)
The Problem:
C# steps could send state.set requests but State.Get() always returned
nullbecause the runner wasn't reading responses from Node.js.The Solution:
Implemented full request-response RPC:
Request ID Tracking (
MotiaRpc.cs):TaskCompletionSourcetracks pending requestsBackground Response Reader (
Program.cs):Node.js Integration (already working):
RpcStdinProcessorwas already sending responsesResult: State.Get() now returns actual values, enabling C# steps to fully participate in stateful workflows!
Multi-Language Communication Flow
Performance Characteristics
Future optimizations (Phase 7):
🧪 Testing
Test Coverage
Unit Tests (packages/core):
Integration Tests (playground):
E2E Tests (packages/e2e):
Running Tests
📖 Documentation
For Users
Quick Start:
npx motia create -t csharp my-csharp-app cd my-csharp-app npx motia devExample C# Step:
For Contributors
packages/docs/content/docs/development-guide/csharp/for user guide🎯 Success Criteria (All Met!)
🔮 Phase 7: Future Enhancements (Optional)
These are not required for this release but represent future improvements:
1. NuGet Package:
Motia.CoreGoal: Publish official NuGet package with types and interfaces
Benefits:
Approach:
2. Source Generators
Goal: Reduce boilerplate with C# source generators
Benefits:
Example:
3. IDE Support Improvements
Goal: Enhanced development experience
Features:
4. Performance Optimizations
Goal: Reduce latency and resource usage
Approaches:
Expected improvements:
5. Middleware Support
Goal: C# middleware chains for API steps
Pattern:
6. Dependency Injection
Goal: Native DI container integration
Approach:
7. ASP.NET Core Integration
Goal: Leverage ASP.NET Core features
Features:
8. F# Support
Goal: Functional programming support
Why: F# runs on .NET and is excellent for data processing and workflows
Example:
9. Features Files
Goal: Support
.step.cs-features.jsonfor configurationUse case:
🔄 Migration Guide
From Beta (if users were testing)
Before (MVP - State.Get returned null):
After (Stable - State.Get works!):
Action Required: None! It just works now. Update your code to use State.Get() if you were avoiding it.
📊 Bundle Size Impact
🔒 Breaking Changes
None! This is a purely additive feature. Existing TypeScript, JavaScript, Python, and Ruby steps are unaffected.
🐛 Known Issues
None at this time. C# support is production-ready and stable.
✅ Checklist
🙏 Acknowledgments
Special thanks to the Motia community for feedback during development and the existing Python/Ruby implementations that served as reference patterns for the C# integration.
📚 Related Issues
Closes #[issue-number] (if applicable)
🔗 References
Ready to merge! 🚀 C# support is production-ready with complete state management and comprehensive testing.