F88.Camunda.Orchestrator.Library 3.0.0

dotnet add package F88.Camunda.Orchestrator.Library --version 3.0.0
                    
NuGet\Install-Package F88.Camunda.Orchestrator.Library -Version 3.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="F88.Camunda.Orchestrator.Library" Version="3.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="F88.Camunda.Orchestrator.Library" Version="3.0.0" />
                    
Directory.Packages.props
<PackageReference Include="F88.Camunda.Orchestrator.Library" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add F88.Camunda.Orchestrator.Library --version 3.0.0
                    
#r "nuget: F88.Camunda.Orchestrator.Library, 3.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package F88.Camunda.Orchestrator.Library@3.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=F88.Camunda.Orchestrator.Library&version=3.0.0
                    
Install as a Cake Addin
#tool nuget:?package=F88.Camunda.Orchestrator.Library&version=3.0.0
                    
Install as a Cake Tool

Hướng dẫn sử dụng Orchestrator.Library DLL

📦 Các cách import DLL vào project khác

1. Sử dụng trực tiếp file DLL

Bước 1: Copy DLL files

Copy các file sau từ bin/Release/net8.0/ vào project đích:

  • Orchestrator.Library.dll
  • Orchestrator.Library.deps.json (nếu cần)
Bước 2: Thêm reference trong project file (.csproj)
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
  </PropertyGroup>
  
  
  <ItemGroup>
    <Reference Include="Orchestrator.Library">
      <HintPath>lib\Orchestrator.Library.dll</HintPath>
    </Reference>
  </ItemGroup>
  
  
  <ItemGroup>
    <ProjectReference Include="..\Orchestrator.Library\Orchestrator.Library.csproj" />
  </ItemGroup>
</Project>
Bước 3: Thêm using statements
using Orchestrator.Library.Services;
using Orchestrator.Library.Workers;
using Orchestrator.Library.Models;
using Orchestrator.Library.Exceptions;

2. Sử dụng NuGet Package (Khuyến nghị)

Bước 1: Tạo NuGet Package
dotnet pack --configuration Release
Bước 2: Thêm NuGet Package
dotnet add package Orchestrator.Library --version 1.0.0

Hoặc thêm vào .csproj:

<ItemGroup>
  <PackageReference Include="Orchestrator.Library" Version="1.0.0" />
</ItemGroup>

3. Sử dụng ProjectReference (Trong cùng solution)

<ItemGroup>
  <ProjectReference Include="..\Orchestrator.Library\Orchestrator.Library.csproj" />
</ItemGroup>

🔧 Setup trong Project đích

1. Web Application (.NET 6+)

// Program.cs
using Orchestrator.Library.Services;
using Orchestrator.Library.Models;

var builder = WebApplication.CreateBuilder();

// Đăng ký ZeebeService
builder.Services.AddZeebeService(provider =>
{
    var configuration = provider.GetRequiredService<IConfiguration>();
    var zeebeUrl = configuration["Zeebe:GatewayAddress"] ?? "localhost:26500";
    
    return ZeebeClient.Builder()
                     .UseGatewayAddress(zeebeUrl)
                     .UsePlainText()
                     .Build();
});

// Đăng ký Kafka configuration
builder.Services.Configure<BaseConfigKafka>(builder.Configuration.GetSection("Kafka"));

// Đăng ký KafkaMessageService
builder.Services.AddSingleton<IKafkaMessageService, KafkaMessageService>();

// Đăng ký workers
builder.Services.AddWorker<MyWorker, MyJobProcessor, MyJobData>();

var app = builder.Build();
app.Run();

2. Console Application

// Program.cs
using Orchestrator.Library.Services;
using Microsoft.Extensions.Hosting;

var host = Host.CreateDefaultBuilder()
    .ConfigureServices((context, services) =>
    {
        // Đăng ký ZeebeService
        services.AddZeebeService(provider =>
        {
            var configuration = provider.GetRequiredService<IConfiguration>();
            var zeebeUrl = configuration["Zeebe:GatewayAddress"] ?? "localhost:26500";
            
            return ZeebeClient.Builder()
                             .UseGatewayAddress(zeebeUrl)
                             .UsePlainText()
                             .Build();
        });

        // Đăng ký Kafka configuration
        services.Configure<BaseConfigKafka>(context.Configuration.GetSection("Kafka"));

        // Đăng ký KafkaMessageService
        services.AddSingleton<IKafkaMessageService, KafkaMessageService>();

        // Đăng ký workers
        services.AddWorker<MyWorker, MyJobProcessor, MyJobData>();

        // Đăng ký hosted services
        services.AddHostedService<MyWorkerHostedService>();
    })
    .Build();

host.Run();

📋 Dependencies cần thiết

NuGet Packages cần thêm vào project đích:

<ItemGroup>
  
  <PackageReference Include="Zeebe.Client" Version="8.3.0" />
  
  
  <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
  <PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
  <PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
  <PackageReference Include="Microsoft.Extensions.Options" Version="8.0.0" />
  
  
  <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
  
  
  <PackageReference Include="Confluent.Kafka" Version="2.3.0" />
</ItemGroup>

🏭 Tạo Worker và Processor

1. Tạo Job Data Model

// MyJobData.cs
namespace MyProject.Models;

public class MyJobData
{
    public string Message { get; set; } = string.Empty;
    public int Priority { get; set; }
    public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
}

2. Tạo Job Processor

// MyJobProcessor.cs
using Orchestrator.Library.Services;
using Orchestrator.Library.Workers;
using Orchestrator.Library.Exceptions;
using MyProject.Models;

namespace MyProject.Workers;

public class MyJobProcessor : IJobProcessor<MyJobData>
{
    private readonly IZeebeService _zeebeService;
    private readonly ILogger<MyJobProcessor> _logger;

    public MyJobProcessor(IZeebeService zeebeService, ILogger<MyJobProcessor> logger)
    {
        _zeebeService = zeebeService;
        _logger = logger;
    }

    public async Task ProcessJobAsync(IJobClient jobClient, IJob job, MyJobData data, CancellationToken stoppingToken)
    {
        try
        {
            _logger.LogInformation("Processing job. JobKey: {JobKey}, Message: {Message}", 
                job.Key, data.Message);

            // Xử lý business logic
            var result = await ProcessBusinessLogic(data);

            // Complete job
            await _zeebeService.CompleteJobAsync(jobClient, job.Key, result);

            // Publish message
            await _zeebeService.PublishMessageAsync(
                "job-completed",
                $"job-{job.Key}",
                new { JobKey = job.Key, Result = result }
            );

            _logger.LogInformation("Job completed successfully. JobKey: {JobKey}", job.Key);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error processing job. JobKey: {JobKey}", job.Key);
            await _zeebeService.ThrowErrorAsync(jobClient, job.Key, "PROCESSING_ERROR", ex.Message);
        }
    }

    private async Task<object> ProcessBusinessLogic(MyJobData data)
    {
        // Implement your business logic here
        await Task.Delay(1000); // Simulate processing
        
        return new { 
            Success = true, 
            ProcessedMessage = data.Message.ToUpper(),
            ProcessedAt = DateTime.UtcNow 
        };
    }
}

3. Tạo Worker

// MyWorker.cs
using Orchestrator.Library.Workers;
using Orchestrator.Library.Services;
using MyProject.Models;

namespace MyProject.Workers;

public class MyWorker : EnhancedGenericWorker<MyJobData>
{
    public MyWorker(
        IZeebeClient zeebeClient,
        ILogger<MyWorker> logger,
        IOptions<BaseConfigKafka> configKafka,
        IJobProcessor<MyJobData> jobProcessor,
        IZeebeService zeebeService,
        IKafkaMessageService? kafkaMessageService = null) 
        : base(zeebeClient, logger, "my-job-type", configKafka, jobProcessor, kafkaMessageService, zeebeService)
    {
    }
}

4. Tạo Hosted Service

// MyWorkerHostedService.cs
using Microsoft.Extensions.Hosting;
using MyProject.Workers;

namespace MyProject.Services;

public class MyWorkerHostedService : BackgroundService
{
    private readonly IServiceProvider _serviceProvider;
    private readonly ILogger<MyWorkerHostedService> _logger;

    public MyWorkerHostedService(IServiceProvider serviceProvider, ILogger<MyWorkerHostedService> logger)
    {
        _serviceProvider = serviceProvider;
        _logger = logger;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation("Starting My Worker Hosted Service");

        while (!stoppingToken.IsCancellationRequested)
        {
            try
            {
                using var scope = _serviceProvider.CreateScope();
                var worker = scope.ServiceProvider.GetRequiredService<MyWorker>();
                
                // Worker sẽ tự động xử lý jobs
                await Task.Delay(1000, stoppingToken);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error in worker hosted service");
                await Task.Delay(5000, stoppingToken); // Wait before retry
            }
        }
    }
}

⚙️ Configuration

appsettings.json

{
  "Zeebe": {
    "GatewayAddress": "localhost:26500"
  },
  "Kafka": {
    "BootstrapServers": "localhost:9092",
    "GroupId": "my-worker-group"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning",
      "Orchestrator.Library": "Debug",
      "MyProject": "Debug"
    }
  }
}

🧪 Testing

Unit Test Example

// MyJobProcessorTests.cs
using Moq;
using Orchestrator.Library.Services;
using MyProject.Workers;
using MyProject.Models;

namespace MyProject.Tests;

[TestClass]
public class MyJobProcessorTests
{
    [TestMethod]
    public async Task ProcessJobAsync_ShouldCompleteJobSuccessfully()
    {
        // Arrange
        var mockZeebeService = new Mock<IZeebeService>();
        var mockLogger = new Mock<ILogger<MyJobProcessor>>();
        var processor = new MyJobProcessor(mockZeebeService.Object, mockLogger.Object);
        
        var jobClient = new Mock<IJobClient>();
        var job = new Mock<IJob>();
        job.Setup(j => j.Key).Returns(123);
        
        var data = new MyJobData { Message = "test message", Priority = 1 };

        // Act
        await processor.ProcessJobAsync(jobClient.Object, job.Object, data, CancellationToken.None);

        // Assert
        mockZeebeService.Verify(x => x.CompleteJobAsync(
            jobClient.Object, 
            job.Object.Key, 
            It.IsAny<object>()), 
            Times.Once);
    }
}

🚀 Deployment

1. Build Release Version

dotnet build --configuration Release

2. Publish Self-Contained (Nếu cần)

dotnet publish --configuration Release --self-contained true --runtime win-x64

3. Docker (Nếu sử dụng)

FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
WORKDIR /app
EXPOSE 80

FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY ["MyProject.csproj", "./"]
RUN dotnet restore "MyProject.csproj"
COPY . .
RUN dotnet build "MyProject.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "MyProject.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "MyProject.dll"]

🔍 Troubleshooting

Lỗi thường gặp:

  1. "Could not load file or assembly 'Orchestrator.Library'"

    • Kiểm tra file DLL có tồn tại không
    • Kiểm tra target framework có tương thích không
  2. "No service for type 'IZeebeService' has been registered"

    • Đảm bảo đã gọi services.AddZeebeService()
    • Kiểm tra using statements
  3. "Zeebe client connection failed"

    • Kiểm tra Zeebe server có đang chạy không
    • Kiểm tra connection string trong configuration

Debug Tips:

// Enable detailed logging
services.AddLogging(builder =>
{
    builder.AddConsole();
    builder.SetMinimumLevel(LogLevel.Debug);
});

// Log service registrations
services.AddZeebeService(provider => CreateZeebeClient(provider), options =>
{
    options.EnableDetailedLogging = true;
});
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
3.0.0 273 9/16/2025
2.0.0 273 9/16/2025
1.0.0 275 9/16/2025

Version 3.0.0 - Performance Optimized:
     - NEW: Complete Task.Run wrapper for all consumer loops to prevent main thread blocking
     - NEW: Dual-level Task.Run optimization (consumer loop + message processing)
     - NEW: Enhanced error isolation and parallel message processing
     - IMPROVED: Maximum throughput with non-blocking consumer architecture
     - IMPROVED: Better resource utilization and scalability
     - IMPROVED: Consumer stability and reliability
     - FIXED: Potential consumer hanging issues in high-load scenarios
     
     Version 2.0.0 - Enhanced Framework:
     - NEW: BaseJobProcessor with template method pattern for common workflow
     - NEW: HttpJobProcessor for specialized HTTP request handling
     - NEW: KafkaJobProcessor for Kafka message publishing patterns
     - NEW: JobContext wrapper with rich job information and utilities
     - NEW: WorkerConfiguration and WorkerFactory for streamlined setup
     - NEW: EnhancedGenericWorker with automatic retry and error handling
     - IMPROVED: Configuration-driven approach for workers and processors
     - IMPROVED: Enhanced error handling with ECode mapping
     - BREAKING: Simplified processor interfaces - legacy support available
     - Examples and comprehensive documentation included