Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions EnterpriseIntegrationPlatform/EnterpriseIntegrationPlatform.sln
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Admin.Web", "src\Admin.Web\
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AI.RagKnowledge", "src\AI.RagKnowledge\AI.RagKnowledge.csproj", "{6074BF1F-98BF-42BB-90C0-ABA48EF8F35C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TutorialLabs", "tests\TutorialLabs\TutorialLabs.csproj", "{F7FBDC14-6ED2-46AC-B348-2427C14F0158}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Processing.RequestReply", "src\Processing.RequestReply\Processing.RequestReply.csproj", "{F8DD5966-EE52-4ADA-BE4F-D23636F424F8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Connectors", "src\Connectors\Connectors.csproj", "{7998C735-EB8F-4DBE-BB32-978E9A465433}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -709,6 +715,42 @@ Global
{6074BF1F-98BF-42BB-90C0-ABA48EF8F35C}.Release|x64.Build.0 = Release|Any CPU
{6074BF1F-98BF-42BB-90C0-ABA48EF8F35C}.Release|x86.ActiveCfg = Release|Any CPU
{6074BF1F-98BF-42BB-90C0-ABA48EF8F35C}.Release|x86.Build.0 = Release|Any CPU
{F7FBDC14-6ED2-46AC-B348-2427C14F0158}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F7FBDC14-6ED2-46AC-B348-2427C14F0158}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F7FBDC14-6ED2-46AC-B348-2427C14F0158}.Debug|x64.ActiveCfg = Debug|Any CPU
{F7FBDC14-6ED2-46AC-B348-2427C14F0158}.Debug|x64.Build.0 = Debug|Any CPU
{F7FBDC14-6ED2-46AC-B348-2427C14F0158}.Debug|x86.ActiveCfg = Debug|Any CPU
{F7FBDC14-6ED2-46AC-B348-2427C14F0158}.Debug|x86.Build.0 = Debug|Any CPU
{F7FBDC14-6ED2-46AC-B348-2427C14F0158}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F7FBDC14-6ED2-46AC-B348-2427C14F0158}.Release|Any CPU.Build.0 = Release|Any CPU
{F7FBDC14-6ED2-46AC-B348-2427C14F0158}.Release|x64.ActiveCfg = Release|Any CPU
{F7FBDC14-6ED2-46AC-B348-2427C14F0158}.Release|x64.Build.0 = Release|Any CPU
{F7FBDC14-6ED2-46AC-B348-2427C14F0158}.Release|x86.ActiveCfg = Release|Any CPU
{F7FBDC14-6ED2-46AC-B348-2427C14F0158}.Release|x86.Build.0 = Release|Any CPU
{F8DD5966-EE52-4ADA-BE4F-D23636F424F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F8DD5966-EE52-4ADA-BE4F-D23636F424F8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F8DD5966-EE52-4ADA-BE4F-D23636F424F8}.Debug|x64.ActiveCfg = Debug|Any CPU
{F8DD5966-EE52-4ADA-BE4F-D23636F424F8}.Debug|x64.Build.0 = Debug|Any CPU
{F8DD5966-EE52-4ADA-BE4F-D23636F424F8}.Debug|x86.ActiveCfg = Debug|Any CPU
{F8DD5966-EE52-4ADA-BE4F-D23636F424F8}.Debug|x86.Build.0 = Debug|Any CPU
{F8DD5966-EE52-4ADA-BE4F-D23636F424F8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F8DD5966-EE52-4ADA-BE4F-D23636F424F8}.Release|Any CPU.Build.0 = Release|Any CPU
{F8DD5966-EE52-4ADA-BE4F-D23636F424F8}.Release|x64.ActiveCfg = Release|Any CPU
{F8DD5966-EE52-4ADA-BE4F-D23636F424F8}.Release|x64.Build.0 = Release|Any CPU
{F8DD5966-EE52-4ADA-BE4F-D23636F424F8}.Release|x86.ActiveCfg = Release|Any CPU
{F8DD5966-EE52-4ADA-BE4F-D23636F424F8}.Release|x86.Build.0 = Release|Any CPU
{7998C735-EB8F-4DBE-BB32-978E9A465433}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7998C735-EB8F-4DBE-BB32-978E9A465433}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7998C735-EB8F-4DBE-BB32-978E9A465433}.Debug|x64.ActiveCfg = Debug|Any CPU
{7998C735-EB8F-4DBE-BB32-978E9A465433}.Debug|x64.Build.0 = Debug|Any CPU
{7998C735-EB8F-4DBE-BB32-978E9A465433}.Debug|x86.ActiveCfg = Debug|Any CPU
{7998C735-EB8F-4DBE-BB32-978E9A465433}.Debug|x86.Build.0 = Debug|Any CPU
{7998C735-EB8F-4DBE-BB32-978E9A465433}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7998C735-EB8F-4DBE-BB32-978E9A465433}.Release|Any CPU.Build.0 = Release|Any CPU
{7998C735-EB8F-4DBE-BB32-978E9A465433}.Release|x64.ActiveCfg = Release|Any CPU
{7998C735-EB8F-4DBE-BB32-978E9A465433}.Release|x64.Build.0 = Release|Any CPU
{7998C735-EB8F-4DBE-BB32-978E9A465433}.Release|x86.ActiveCfg = Release|Any CPU
{7998C735-EB8F-4DBE-BB32-978E9A465433}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -766,5 +808,8 @@ Global
{696931C9-2E49-4AE4-A674-4F90C2EF132F} = {A1B2C3D4-0001-0001-0001-000000000001}
{3E1CCAF1-B4D9-4DA6-8439-DC169DA0CA1A} = {A1B2C3D4-0001-0001-0001-000000000001}
{6074BF1F-98BF-42BB-90C0-ABA48EF8F35C} = {A1B2C3D4-0001-0001-0001-000000000001}
{F7FBDC14-6ED2-46AC-B348-2427C14F0158} = {A1B2C3D4-0001-0001-0001-000000000002}
{F8DD5966-EE52-4ADA-BE4F-D23636F424F8} = {A1B2C3D4-0001-0001-0001-000000000002}
{7998C735-EB8F-4DBE-BB32-978E9A465433} = {A1B2C3D4-0001-0001-0001-000000000002}
EndGlobalSection
EndGlobal
83 changes: 83 additions & 0 deletions EnterpriseIntegrationPlatform/rules/completion-log.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,89 @@ Detailed record of completed chunks, files created/modified, and notes.

See `milestones.md` for current phase status and next chunk.

## Chunk 102 – Update tutorials/README.md

- **Date**: 2026-04-06
- **Phase**: 27 — Coding Tutorial Labs & Exams
- **Status**: done
- **Goal**: Update tutorials/README.md to document the new coding-only format and TutorialLabs project.
- **Files modified**:
- `tutorials/README.md` — Added "Coding Labs & Exams" section with project structure, running instructions, and test counts.
- **Test counts**: 522 TutorialLabs tests. (Documentation-only change.)

## Chunk 101 – Update all 50 tutorial .md files

- **Date**: 2026-04-06
- **Phase**: 27 — Coding Tutorial Labs & Exams
- **Status**: done
- **Goal**: Replace MCQ Exam sections in all 50 tutorials with coding exam pointers. Add TutorialLabs lab references.
- **Files modified**:
- All 50 tutorial `.md` files — Added `> 💻 Runnable lab:` reference after `## Lab`, replaced MCQ `## Exam` sections with `> 💻 Coding exam:` pointer.
- **Test counts**: 522 TutorialLabs tests. (Documentation-only change.)
- **Notes**: All 150 MCQ questions (3 per tutorial × 50 tutorials) removed and replaced with pointers to coding exams.

## Chunk 100 – Tutorial 46-50 Lab.cs + Exam.cs

- **Date**: 2026-04-06
- **Phase**: 27 — Coding Tutorial Labs & Exams
- **Status**: done
- **Goal**: Create coding labs and exams for tutorials 46-50 (CompleteIntegration, SagaCompensation, NotificationUseCases, TestingIntegrations, BestPractices).
- **Files created**:
- `tests/TutorialLabs/Tutorial46/Lab.cs` — 7 tests: PipelineOrchestrator, PipelineOptions, IntegrationPipelineInput/Result, ITemporalWorkflowDispatcher mock
- `tests/TutorialLabs/Tutorial46/Exam.cs` — 3 tests: full pipeline flow, input mapping, dispatcher failure
- `tests/TutorialLabs/Tutorial47/Lab.cs` — 7 tests: DefaultCompensationActivityService, ICompensationActivityService, SagaCompensationActivities/Workflow reflection, IntegrationPipelineResult
- `tests/TutorialLabs/Tutorial47/Exam.cs` — 3 tests: multi-step compensation, failure scenario, workflow type verification
- `tests/TutorialLabs/Tutorial48/Lab.cs` — 7 tests: DefaultMessageValidationService, MessageValidationResult, DefaultMessageLoggingService, INotificationActivityService, IPersistenceActivityService
- `tests/TutorialLabs/Tutorial48/Exam.cs` — 3 tests: full notification flow, validation failure triggers nack, persistence activity mock
- `tests/TutorialLabs/Tutorial49/Lab.cs` — 7 tests: IntegrationEnvelope.Create, CausationId chain, FaultEnvelope.Create, MessagePriority/Intent enums, RoutingSlip advance/complete
- `tests/TutorialLabs/Tutorial49/Exam.cs` — 3 tests: three-generation causation chain, FaultEnvelope with exception, routing slip lifecycle
- `tests/TutorialLabs/Tutorial50/Lab.cs` — 7 tests: IsExpired, InputSanitizer idempotency, TenantResolver null handling, MessageHeaders.ReplayId, metadata round-trip, SchemaVersion default
- `tests/TutorialLabs/Tutorial50/Exam.cs` — 3 tests: end-to-end envelope+security+tenancy, expiration+priority, cross-cutting concerns flow
- **Test counts**: 522 TutorialLabs tests total (+50 from this chunk).
- **Notes**: Fixed compilation errors from previous session — RoutingSlipStep/RoutingSlip are positional records, DefaultMessageValidationService has parameterless constructor.

## Chunk 099 – Tutorial 41-45 Lab.cs + Exam.cs

- **Date**: 2026-04-06
- **Phase**: 27 — Coding Tutorial Labs & Exams
- **Status**: done
- **Goal**: Create coding labs and exams for tutorials 41-45 (OpenClawWeb, Configuration, KubernetesDeployment, DisasterRecovery, PerformanceProfiling).
- **Files created**:
- `tests/TutorialLabs/Tutorial41/Lab.cs` + `Exam.cs` — 10 tests: InspectionResult, MessageStateInspector, ITraceAnalyzer, IObservabilityEventLog, snapshot creation
- `tests/TutorialLabs/Tutorial42/Lab.cs` + `Exam.cs` — 10 tests: ConfigurationEntry, InMemoryConfigurationStore, FeatureFlag, InMemoryFeatureFlagService, variants, tenants
- `tests/TutorialLabs/Tutorial43/Lab.cs` + `Exam.cs` — 10 tests: TemporalOptions, PipelineOptions, JwtOptions, DisasterRecoveryOptions, configuration roundtrip
- `tests/TutorialLabs/Tutorial44/Lab.cs` + `Exam.cs` — 10 tests: FailoverResult, ReplicationStatus, DrDrillType, IFailoverManager, IRecoveryPointValidator, DisasterRecoveryOptions
- `tests/TutorialLabs/Tutorial45/Lab.cs` + `Exam.cs` — 10 tests: ContinuousProfiler, AllocationHotspotDetector, InMemoryBenchmarkRegistry, ProfilingOptions
- **Test counts**: 472 TutorialLabs tests total (+50 from this chunk).

## Chunk 098 – Tutorial 36-40 Lab.cs + Exam.cs

- **Date**: 2026-04-06
- **Phase**: 27 — Coding Tutorial Labs & Exams
- **Status**: done
- **Goal**: Create coding labs and exams for tutorials 36-40 (ConnectorEmail, ConnectorFile, OpenTelemetry, MessageLifecycle, RagOllama).
- **Files created**:
- `tests/TutorialLabs/Tutorial36/Lab.cs` + `Exam.cs` — 10 tests: EmailConnectorOptions, ISmtpClientWrapper, EmailConnector lifecycle
- `tests/TutorialLabs/Tutorial37/Lab.cs` + `Exam.cs` — 10 tests: FileConnectorOptions, IFileSystem, FileConnector write/read/list, PhysicalFileSystem
- `tests/TutorialLabs/Tutorial38/Lab.cs` + `Exam.cs` — 10 tests: MessageEvent, IMessageStateStore, InspectionResult, DeliveryStatus, CorrelationPropagator
- `tests/TutorialLabs/Tutorial39/Lab.cs` + `Exam.cs` — 10 tests: SmartProxy, TestMessageGenerator, ControlBusOptions/Result, TestMessageResult
- `tests/TutorialLabs/Tutorial40/Lab.cs` + `Exam.cs` — 10 tests: IOllamaService, IRagFlowService, RagFlowChatResponse, OllamaSettings, RagFlowOptions
- **Test counts**: 422 TutorialLabs tests total (+50 from this chunk).

## Chunk 097 – Tutorial 31-35 Lab.cs + Exam.cs

- **Date**: 2026-04-06
- **Phase**: 27 — Coding Tutorial Labs & Exams
- **Status**: done
- **Goal**: Create coding labs and exams for tutorials 31-35 (EventSourcing, MultiTenancy, Security, ConnectorHttp, ConnectorSftp).
- **Files created**:
- `tests/TutorialLabs/Tutorial31/Lab.cs` + `Exam.cs` — 10 tests: InMemoryEventStore, EventProjectionEngine, OptimisticConcurrencyException, InMemorySnapshotStore, EventSourcingOptions
- `tests/TutorialLabs/Tutorial32/Lab.cs` + `Exam.cs` — 10 tests: TenantResolver, TenantIsolationGuard, TenantContext, TenantIsolationException
- `tests/TutorialLabs/Tutorial33/Lab.cs` + `Exam.cs` — 10 tests: InputSanitizer, PayloadSizeGuard, PayloadTooLargeException, InMemorySecretProvider, SecretEntry
- `tests/TutorialLabs/Tutorial34/Lab.cs` + `Exam.cs` — 10 tests: InMemoryTokenCache, HttpConnectorOptions, HttpConnectorAdapter
- `tests/TutorialLabs/Tutorial35/Lab.cs` + `Exam.cs` — 10 tests: SftpConnectorOptions, ISftpClient reflection, SftpConnectionPool, ISftpConnector
- **Test counts**: 372 TutorialLabs tests total (+50 from this chunk).

## Chunk 092 – Kustomize Base Directory Structure

- **Date**: 2026-04-05
Expand Down
27 changes: 23 additions & 4 deletions EnterpriseIntegrationPlatform/rules/milestones.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,32 @@

48 src projects. All 50 tutorials rewritten with BizTalk-style Lab + Exam exercises focused on EIP patterns, scalability, and atomicity.

**Next chunk:** (none — all current work complete)

---

## Next Chunk
## Phase 27 — Coding Tutorial Labs & Exams

**Goal:** Convert all 50 tutorials from conceptual/MCQ format to coding-only format. Each tutorial gets:
- `tests/TutorialLabs/TutorialXX/Lab.cs` — Complete, runnable NUnit test class demonstrating the pattern
- `tests/TutorialLabs/TutorialXX/Exam.cs` — Coding exam challenges (NOT multiple choice)
- Updated tutorial `.md` file pointing to the implementation folder

**Project:** `tests/TutorialLabs/TutorialLabs.csproj` (added to solution, references all src projects)

**Key API findings for remaining chunks:**
- **DynamicRouter**: implements `IDynamicRouter` + `IRouterControlChannel`. Constructor: `IMessageBrokerProducer`, `IOptions<DynamicRouterOptions>`, `ILogger<DynamicRouter>`. Methods: `RegisterAsync()`, `UnregisterAsync()`, `RouteAsync<T>()`, `GetRoutingTable()`.
- **RecipientListRouter**: implements `IRecipientList`. Constructor: `IMessageBrokerProducer`, `IOptions<RecipientListOptions>`, `ILogger<RecipientListRouter>`. Uses `RecipientListRule` with `RoutingOperator`.
- **RoutingSlipRouter**: implements `IRoutingSlipRouter`. Constructor: `IEnumerable<IRoutingSlipStepHandler>`, `IMessageBrokerProducer`, `ILogger<RoutingSlipRouter>`. Handlers implement `IRoutingSlipStepHandler`.
- **Process Manager**: `PipelineOrchestrator` and `ITemporalWorkflowDispatcher` in `Demo.Pipeline`. Uses `IntegrationPipelineInput`/`IntegrationPipelineResult` from Activities.
- **MessageTranslator<TIn,TOut>**: takes `IPayloadTransform<TIn,TOut>`, `IMessageBrokerProducer`, `IOptions<TranslatorOptions>`, `ILogger`. `FuncPayloadTransform<TIn,TOut>` wraps a delegate.
- **Transform steps**: `JsonToXmlStep`, `XmlToJsonStep`, `RegexReplaceStep`, `JsonPathFilterStep`, `TransformPipeline`.

| Chunk | Scope | Status |
|-------|-------|--------|
✅ Phase 27 complete — see completion-log.md.

522 TutorialLabs tests (350 lab + 150 exam + 22 extra). All 50 tutorials updated with coding lab/exam pointers.

(none)
**Next chunk:** None — all chunks complete.

---

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<InternalsVisibleTo Include="UnitTests" />
<InternalsVisibleTo Include="TutorialLabs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Contracts\Contracts.csproj" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// ============================================================================
// Tutorial 01 – Introduction to Enterprise Integration (Exam)
// ============================================================================
// Coding challenges that test your understanding of the IntegrationEnvelope,
// message intents, causation chains, and record immutability.
// ============================================================================

using EnterpriseIntegrationPlatform.Contracts;
using NUnit.Framework;

namespace TutorialLabs.Tutorial01;

// A simple domain record used in the exam challenges.
public sealed record OrderPayload(string OrderId, string Product, int Quantity, decimal Price);

[TestFixture]
public sealed class Exam
{
// ── Challenge 1: Wrap a Domain Object in an Envelope ────────────────────

[Test]
public void Challenge1_CreateEnvelopeForOrderPayload()
{
// Create an OrderPayload and wrap it in an IntegrationEnvelope.
var order = new OrderPayload("ORD-001", "Widget", 5, 29.99m);

var envelope = IntegrationEnvelope<OrderPayload>.Create(
payload: order,
source: "OrderService",
messageType: "order.created");

// Verify the envelope wraps the domain object correctly.
Assert.That(envelope.Payload.OrderId, Is.EqualTo("ORD-001"));
Assert.That(envelope.Payload.Product, Is.EqualTo("Widget"));
Assert.That(envelope.Payload.Quantity, Is.EqualTo(5));
Assert.That(envelope.Payload.Price, Is.EqualTo(29.99m));
Assert.That(envelope.Source, Is.EqualTo("OrderService"));
Assert.That(envelope.MessageType, Is.EqualTo("order.created"));
Assert.That(envelope.MessageId, Is.Not.EqualTo(Guid.Empty));
}

// ── Challenge 2: Build a CausationId Chain ──────────────────────────────

[Test]
public void Challenge2_CausationIdLinking_MessageBCausedByA()
{
// Message A is the originating command.
var messageA = IntegrationEnvelope<string>.Create(
payload: "PlaceOrder",
source: "WebApp",
messageType: "order.place") with
{
Intent = MessageIntent.Command,
};

// Message B is caused by A — its CausationId points to A's MessageId
// and both share the same CorrelationId for end-to-end tracing.
var messageB = IntegrationEnvelope<string>.Create(
payload: "OrderPlaced",
source: "OrderService",
messageType: "order.placed",
correlationId: messageA.CorrelationId,
causationId: messageA.MessageId) with
{
Intent = MessageIntent.Event,
};

// Verify the causal link.
Assert.That(messageB.CausationId, Is.EqualTo(messageA.MessageId));
Assert.That(messageB.CorrelationId, Is.EqualTo(messageA.CorrelationId));
Assert.That(messageB.MessageId, Is.Not.EqualTo(messageA.MessageId));
}

// ── Challenge 3: Verify Envelope Immutability ───────────────────────────

[Test]
public void Challenge3_RecordImmutability_WithExpressionCreatesNewInstance()
{
// Records are immutable — you cannot change properties after creation.
// The `with` expression creates a shallow copy with modified values.
var original = IntegrationEnvelope<string>.Create(
"original-payload", "TestService", "test.message");

var modified = original with { Priority = MessagePriority.High };

// The original is untouched.
Assert.That(original.Priority, Is.EqualTo(MessagePriority.Normal));

// The modified copy has the new priority but retains all other values.
Assert.That(modified.Priority, Is.EqualTo(MessagePriority.High));
Assert.That(modified.MessageId, Is.EqualTo(original.MessageId));
Assert.That(modified.Payload, Is.EqualTo(original.Payload));

// They are different object references.
Assert.That(ReferenceEquals(original, modified), Is.False);
}
}
Loading
Loading