Skip to content

Commit 2f27da1

Browse files
committed
Merge branch 'release/v3.4.1' into main
2 parents 5f1d35e + 234aeb8 commit 2f27da1

71 files changed

Lines changed: 1938 additions & 1403 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/nuget.publish.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ on:
44
push:
55
tags:
66
- "v*"
7-
branches:
8-
- develop
7+
98
workflow_dispatch:
109

1110
permissions:

CHANGELOG.md

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,30 @@
22

33
All notable changes to this project will be documented in this file.
44

5-
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

88
## [Unreleased]
99

10+
## [3.4.1] - 2026-03-21
11+
12+
### Changed
13+
14+
- **Renamed all `Workflow` classes to `Railway`** to better reflect the railway-oriented programming pattern
15+
- `Workflow<TRequest, TSuccess, TError>` -> `Railway<TRequest, TSuccess, TError>`
16+
- `WorkflowBuilder<...>` -> `RailwayBuilder<...>`
17+
- `WorkflowBuilderFactory` -> `RailwayBuilderFactory`
18+
- `CreateWorkflow<...>()` -> `CreateRailway<...>()`
19+
- `IWorkflowStep` -> `IRailwayStep`
20+
- `IWorkflowValidation` -> `IRailwayValidation`
21+
- `IWorkflowGuard` -> `IRailwayGuard`
22+
- `AddWorkflows()` -> `AddRailways()`
23+
- `AddWorkflowSteps()` -> `AddRailwaySteps()`
24+
- All old `Workflow` names are preserved as `[Obsolete]` shims for backward compatibility
25+
- Updated all example files to use the new Railway terminology
26+
27+
## [3.4.0] - 2026-03-10
28+
1029
### Added
1130

1231
- New `IWorkflowStep` and `IWorkflowStep<TPayload, TError>` interfaces to replace `IWorkflowActivity`

Directory.Build.props

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@
88
<RepositoryUrl>https://github.com/zooper-lib/Bee</RepositoryUrl>
99
<RepositoryType>git</RepositoryType>
1010
<PackageIcon>icon.png</PackageIcon>
11-
<PackageTags>workflow;builder;pipeline;functional;either;C#</PackageTags>
11+
<PackageTags>railway;workflow;builder;pipeline;functional;either;C#</PackageTags>
1212
<PackageReadmeFile>README.md</PackageReadmeFile>
13-
<Description>A .NET library for building robust, functional workflows and processing pipelines.</Description>
13+
<Description>A .NET library for building robust, functional railways (processing pipelines) using railway-oriented programming.</Description>
1414

1515
<!-- Version information -->
16-
<Version>3.4.0</Version>
16+
<Version>3.4.1</Version>
1717

1818
<!-- Source linking -->
1919
<PublishRepositoryUrl>true</PublishRepositoryUrl>

README.md

Lines changed: 64 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,22 @@
55
[![NuGet Version](https://img.shields.io/nuget/v/Zooper.Bee.svg)](https://www.nuget.org/packages/Zooper.Bee/)
66
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
77

8-
A flexible and powerful workflow library for .NET that allows you to define complex business processes with a fluent
8+
A flexible and powerful railway-oriented programming library for .NET that allows you to define complex business processes with a fluent
99
API.
1010

1111
## Overview
1212

13-
Zooper.Bee lets you create workflows that process requests and produce either successful results or meaningful errors.
14-
The library uses a builder pattern to construct workflows with various execution patterns including sequential,
13+
Zooper.Bee lets you create railways that process requests and produce either successful results or meaningful errors.
14+
The library uses a builder pattern to construct railways with various execution patterns including sequential,
1515
conditional, parallel, and detached operations.
1616

1717
## Key Concepts
1818

19-
- **Workflow**: A sequence of operations that process a request to produce a result or error
20-
- **Request**: The input data to the workflow
21-
- **Payload**: Data that passes through and gets modified by workflow activities
22-
- **Success**: The successful result of the workflow
23-
- **Error**: The errors result if the workflow fails
19+
- **Railway**: A sequence of operations that process a request to produce a result or error
20+
- **Request**: The input data to the railway
21+
- **Payload**: Data that passes through and gets modified by railway activities
22+
- **Success**: The successful result of the railway
23+
- **Error**: The errors result if the railway fails
2424

2525
## Installation
2626

@@ -31,8 +31,8 @@ dotnet add package Zooper.Bee
3131
## Getting Started
3232

3333
```csharp
34-
// Define a simple workflow
35-
var workflow = new WorkflowBuilder<Request, Payload, SuccessResult, ErrorResult>(
34+
// Define a simple railway
35+
var railway = new RailwayBuilder<Request, Payload, SuccessResult, ErrorResult>(
3636
// Factory function that creates the initial payload from the request
3737
request => new Payload { Data = request.Data },
3838

@@ -55,8 +55,8 @@ var workflow = new WorkflowBuilder<Request, Payload, SuccessResult, ErrorResult>
5555
})
5656
.Build();
5757

58-
// Execute the workflow
59-
var result = await workflow.Execute(new Request { Data = "hello world" }, CancellationToken.None);
58+
// Execute the railway
59+
var result = await railway.Execute(new Request { Data = "hello world" }, CancellationToken.None);
6060
if (result.IsRight)
6161
{
6262
Console.WriteLine($"Success: {result.Right.ProcessedData}"); // Output: Success: HELLO WORLD
@@ -67,7 +67,7 @@ else
6767
}
6868
```
6969

70-
## Building Workflows
70+
## Building Railways
7171

7272
### Validation
7373

@@ -91,8 +91,8 @@ Validates the incoming request before processing begins.
9191

9292
### Guards
9393

94-
Guards allow you to define checks that run before a workflow begins execution. They're ideal for authentication,
95-
authorization, account validation, or any other requirement that must be satisfied before a workflow can proceed.
94+
Guards allow you to define checks that run before a railway begins execution. They're ideal for authentication,
95+
authorization, account validation, or any other requirement that must be satisfied before a railway can proceed.
9696

9797
```csharp
9898
// Asynchronous guard
@@ -112,14 +112,14 @@ authorization, account validation, or any other requirement that must be satisfi
112112

113113
#### Benefits of Guards
114114

115-
- Guards run before creating the workflow context, providing early validation
116-
- They provide a clear separation between "can this workflow run?" and the actual workflow logic
115+
- Guards run before creating the railway context, providing early validation
116+
- They provide a clear separation between "can this railway run?" and the actual railway logic
117117
- Common checks like authentication can be standardized and reused
118-
- Failures short-circuit the workflow, preventing unnecessary work
118+
- Failures short-circuit the railway, preventing unnecessary work
119119

120120
### Activities
121121

122-
Activities are the building blocks of a workflow. They process the payload and can produce either a success (with
122+
Activities are the building blocks of a railway. They process the payload and can produce either a success (with
123123
the modified payload) or an error.
124124

125125
```csharp
@@ -164,7 +164,7 @@ Activities that only execute if a condition is met.
164164
### Groups
165165

166166
Organize related activities into logical groups. Groups can have conditions and always merge their results back to the
167-
main workflow.
167+
main railway.
168168

169169
```csharp
170170
.Group(
@@ -219,7 +219,7 @@ Execute multiple groups of activities in parallel and merge the results.
219219
### Detached Execution
220220

221221
Execute activities in the background without waiting for their completion. Results from detached activities are not
222-
merged back into the main workflow.
222+
merged back into the main railway.
223223

224224
```csharp
225225
.Detach(
@@ -253,7 +253,7 @@ Execute multiple groups of detached activities in parallel without waiting for c
253253

254254
### Finally Block
255255

256-
Activities that always execute, even if the workflow fails.
256+
Activities that always execute, even if the railway fails.
257257

258258
```csharp
259259
.Finally(payload =>
@@ -285,7 +285,7 @@ Activities that always execute, even if the workflow fails.
285285

286286
### Conditional Branching
287287

288-
Use conditions to determine which path to take in a workflow.
288+
Use conditions to determine which path to take in a railway.
289289

290290
```csharp
291291
.Group(
@@ -302,53 +302,83 @@ Use conditions to determine which path to take in a workflow.
302302

303303
## Dependency Injection Integration
304304

305-
Zooper.Bee integrates seamlessly with .NET's dependency injection system. You can register all workflow components with
305+
Zooper.Bee integrates seamlessly with .NET's dependency injection system. You can register all railway components with
306306
a single extension method:
307307

308308
```csharp
309309
// In Startup.cs or Program.cs
310-
services.AddWorkflows();
310+
services.AddRailways();
311311
```
312312

313313
This will scan all assemblies and register:
314314

315-
- All workflow validations
316-
- All workflow activities
317-
- All concrete workflow classes (classes ending with "Workflow")
315+
- All railway validations
316+
- All railway activities
317+
- All concrete railway classes (classes ending with "Railway")
318318

319319
You can also register specific components:
320320

321321
```csharp
322322
// Register only validations
323-
services.AddWorkflowValidations();
323+
services.AddRailwayValidations();
324324

325325
// Register only activities
326-
services.AddWorkflowActivities();
326+
services.AddRailwayActivities();
327327

328328
// Specify which assemblies to scan
329-
services.AddWorkflows(new[] { typeof(Program).Assembly });
329+
services.AddRailways(new[] { typeof(Program).Assembly });
330330

331331
// Specify service lifetime (Singleton, Scoped, Transient)
332-
services.AddWorkflows(lifetime: ServiceLifetime.Singleton);
332+
services.AddRailways(lifetime: ServiceLifetime.Singleton);
333333
```
334334

335335
## Performance Considerations
336336

337337
- Use `Parallel` for CPU-bound operations that can benefit from parallel execution
338-
- Use `Detach` for I/O operations that don't affect the main workflow
338+
- Use `Detach` for I/O operations that don't affect the main railway
339339
- Be mindful of resource contention in parallel operations
340340
- Consider using `WithContext` to maintain state between related activities
341341

342342
## Best Practices
343343

344344
1. Keep activities small and focused on a single responsibility
345-
2. Use descriptive names for your workflow methods
345+
2. Use descriptive names for your railway methods
346346
3. Group related activities together
347347
4. Handle errors at appropriate levels
348348
5. Use `Finally` for cleanup operations
349349
6. Validate requests early to fail fast
350350
7. Use contextual state to avoid passing too many parameters
351351

352+
## Migration from Workflow to Railway
353+
354+
As of the latest version, all `Workflow` classes have been renamed to `Railway` to better reflect the railway-oriented programming pattern used by the library. The old `Workflow` names are preserved as `[Obsolete]` shims for backward compatibility.
355+
356+
### What changed
357+
358+
| Old Name | New Name |
359+
|---|---|
360+
| `Workflow<TRequest, TSuccess, TError>` | `Railway<TRequest, TSuccess, TError>` |
361+
| `WorkflowBuilder<...>` | `RailwayBuilder<...>` |
362+
| `WorkflowBuilderFactory` | `RailwayBuilderFactory` |
363+
| `CreateWorkflow<...>()` | `CreateRailway<...>()` |
364+
| `IWorkflowStep` | `IRailwayStep` |
365+
| `IWorkflowValidation` | `IRailwayValidation` |
366+
| `IWorkflowGuard` | `IRailwayGuard` |
367+
| `AddWorkflows()` | `AddRailways()` |
368+
| `AddWorkflowSteps()` | `AddRailwaySteps()` |
369+
370+
### Backward compatibility
371+
372+
All old type names and extension methods are still available but marked with `[Obsolete]`. Your existing code will continue to compile and work, but you will see deprecation warnings encouraging you to migrate to the new names.
373+
374+
### How to migrate
375+
376+
1. Replace all `Workflow<` type references with `Railway<`
377+
2. Replace `WorkflowBuilder<` with `RailwayBuilder<`
378+
3. Replace `WorkflowBuilderFactory.CreateWorkflow<` with `RailwayBuilderFactory.CreateRailway<`
379+
4. Replace DI registration calls (`AddWorkflows()` -> `AddRailways()`, etc.)
380+
5. Update any interface implementations (`IWorkflowStep` -> `IRailwayStep`, etc.)
381+
352382
## License
353383

354384
MIT License (Copyright details here)

Zooper.Bee.Example/BranchingExample.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,15 @@ public record RegistrationPayload(
3030

3131
public static async Task RunExample()
3232
{
33-
Console.WriteLine("\n=== Workflow Grouping Example ===\n");
33+
Console.WriteLine("\n=== Railway Grouping Example ===\n");
3434

3535
// Create sample requests
3636
var standardUserRequest = new RegistrationRequest("user@example.com", "Password123!", false);
3737
var vipUserRequest = new RegistrationRequest("vip@example.com", "VIPPassword123!", true);
3838
var invalidEmailRequest = new RegistrationRequest("invalid-email", "Password123!", false);
3939

40-
// Build the registration workflow
41-
var workflow = CreateRegistrationWorkflow();
40+
// Build the registration railway
41+
var workflow = CreateRegistrationRailway();
4242

4343
// Process standard user registration
4444
Console.WriteLine("Registering standard user:");
@@ -58,7 +58,7 @@ public static async Task RunExample()
5858
}
5959

6060
private static async Task ProcessRegistration(
61-
Workflow<RegistrationRequest, RegistrationSuccess, RegistrationError> workflow,
61+
Railway<RegistrationRequest, RegistrationSuccess, RegistrationError> workflow,
6262
RegistrationRequest request)
6363
{
6464
var result = await workflow.Execute(request);
@@ -82,9 +82,9 @@ private static async Task ProcessRegistration(
8282
}
8383
}
8484

85-
private static Workflow<RegistrationRequest, RegistrationSuccess, RegistrationError> CreateRegistrationWorkflow()
85+
private static Railway<RegistrationRequest, RegistrationSuccess, RegistrationError> CreateRegistrationRailway()
8686
{
87-
return new WorkflowBuilder<RegistrationRequest, RegistrationPayload, RegistrationSuccess, RegistrationError>(
87+
return new RailwayBuilder<RegistrationRequest, RegistrationPayload, RegistrationSuccess, RegistrationError>(
8888
// Create initial payload from request
8989
request => new RegistrationPayload(
9090
Guid.NewGuid(), // Generate a new unique ID

Zooper.Bee.Example/ContextLocalPayloadExample.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public record OrderConfirmation(
2121
// Error model
2222
public record OrderError(string Code, string Message);
2323

24-
// Main workflow payload model
24+
// Main railway payload model
2525
public record OrderPayload(
2626
int OrderId,
2727
string CustomerName,
@@ -40,14 +40,14 @@ public record ShippingPayload(
4040

4141
public static async Task RunExample()
4242
{
43-
Console.WriteLine("\n=== Workflow With Context Local Payload Example ===\n");
43+
Console.WriteLine("\n=== Railway With Context Local Payload Example ===\n");
4444

4545
// Create sample requests
4646
var standardOrder = new OrderRequest(2001, "Alice Johnson", 75.00m, false);
4747
var shippingOrder = new OrderRequest(2002, "Bob Smith", 120.00m, true);
4848

49-
// Build the order processing workflow
50-
var workflow = CreateOrderWorkflow();
49+
// Build the order processing railway
50+
var workflow = CreateOrderRailway();
5151

5252
// Process the standard order (no shipping)
5353
Console.WriteLine("Processing standard order (no shipping):");
@@ -61,7 +61,7 @@ public static async Task RunExample()
6161
}
6262

6363
private static async Task ProcessOrder(
64-
Workflow<OrderRequest, OrderConfirmation, OrderError> workflow,
64+
Railway<OrderRequest, OrderConfirmation, OrderError> workflow,
6565
OrderRequest request)
6666
{
6767
var result = await workflow.Execute(request);
@@ -89,9 +89,9 @@ private static async Task ProcessOrder(
8989
}
9090
}
9191

92-
private static Workflow<OrderRequest, OrderConfirmation, OrderError> CreateOrderWorkflow()
92+
private static Railway<OrderRequest, OrderConfirmation, OrderError> CreateOrderRailway()
9393
{
94-
return new WorkflowBuilder<OrderRequest, OrderPayload, OrderConfirmation, OrderError>(
94+
return new RailwayBuilder<OrderRequest, OrderPayload, OrderConfirmation, OrderError>(
9595
// Create initial payload from request
9696
request => new OrderPayload(
9797
request.OrderId,

0 commit comments

Comments
 (0)