### Quick Start: Try /test-first Source: https://github.com/brightercommand/brighter/blob/master/docs/NEW_SKILLS_GUIDE.md Initiate test-first development by providing a description of the desired behavior. Claude will guide you through test writing, approval, implementation, and refactoring. ```bash # In Claude Code, type: /test-first when a message timeout occurs it should retry with backoff ``` -------------------------------- ### Install Docker and Docker Compose Source: https://github.com/brightercommand/brighter/blob/master/TESTING_GUIDE.md Installs Docker and Docker Compose on Debian-based systems and starts the Docker service. ```bash sudo apt update sudo apt install docker.io docker-compose -y sudo systemctl start docker sudo systemctl enable docker ``` -------------------------------- ### Run Validation Examples Source: https://github.com/brightercommand/brighter/blob/master/samples/Validation/README.md Command-line instructions to run the console applications for each validation provider example. ```sh dotnet run --project samples/Validation/FluentValidationSample dotnet run --project samples/Validation/DataAnnotationsSample dotnet run --project samples/Validation/SpecificationSample ``` -------------------------------- ### Start RabbitMQ Infrastructure Source: https://github.com/brightercommand/brighter/blob/master/samples/TaskQueue/RMQDeferOnError/README.md Starts the RabbitMQ infrastructure using Docker Compose. Ensure you are in the repository root directory. ```sh docker compose -f docker-compose-rmq.yaml up -d ``` -------------------------------- ### Start All Docker Services for Testing Source: https://github.com/brightercommand/brighter/blob/master/CONTRIBUTING.md Use docker-compose up -d to start all necessary infrastructure services for comprehensive testing, including RabbitMQ, databases, and observability tools. ```bash docker-compose up -d ``` -------------------------------- ### Start the Receiver Source: https://github.com/brightercommand/brighter/blob/master/samples/TaskQueue/KafkaDeferOnError/README.md Navigate to the receiver console directory and run the application to start receiving messages. ```sh cd samples/TaskQueue/KafkaDeferOnError/GreetingsReceiverConsole dotnet run ``` -------------------------------- ### Start Kafka Infrastructure Source: https://github.com/brightercommand/brighter/blob/master/samples/TaskQueue/KafkaDontAckOnError/README.md Use this command to start the Kafka infrastructure using Docker Compose. Ensure you are in the repository root directory. ```sh docker compose -f docker-compose-kafka.yaml up -d ``` -------------------------------- ### Install Service Activator Packages for Consumer Source: https://github.com/brightercommand/brighter/blob/master/README.md For consumer applications processing messages from external brokers, install the Service Activator packages. ```bash dotnet add package Paramore.Brighter.ServiceActivator.Extensions.DependencyInjection dotnet add package Paramore.Brighter.ServiceActivator.Extensions.Hosting ``` -------------------------------- ### SpyCommandProcessor Extensibility Example Source: https://github.com/brightercommand/brighter/blob/master/specs/0003-testing-support-for-command-processor-handlers/PROMPT.md Demonstrates how to extend the SpyCommandProcessor by overriding virtual methods. The ThrowingSpyCommandProcessor example shows custom behavior implementation for testing purposes. ```csharp - `ThrowingSpyCommandProcessor` example demonstrates override pattern ``` -------------------------------- ### Start the Receiver (Main Consumer) Source: https://github.com/brightercommand/brighter/blob/master/samples/TaskQueue/KafkaTaskQueueWithDLQ/README.md Starts the main consumer application that creates Kafka topics and begins consuming messages from the 'greeting.event' topic. ```sh cd samples/TaskQueue/KafkaTaskQueueWithDLQ/GreetingsReceiverConsole dotnet run ``` -------------------------------- ### Service Readiness Check Example Source: https://github.com/brightercommand/brighter/blob/master/docs/CI-Test-Reliability.md Add checks to verify service connectivity before performing operations. This example uses a PingAsync method and retries until the service is ready. ```csharp await WaitForServiceAsync(async () => { try { await producer.PingAsync(); return true; } catch { return false; } }); ``` -------------------------------- ### Kafka Test Attributes and Setup Source: https://github.com/brightercommand/brighter/blob/master/specs/0001-kafka-dead-letter-queue/test-analysis.md Demonstrates common attributes and setup for Kafka integration tests, including trait categorization, collection for parallel execution control, and ITestOutputHelper for logging. ```csharp [Trait("Category", "Kafka")] [Collection("Kafka")] public class When_a_message_is_acknowledged_update_offset.cs : IDisposable ``` -------------------------------- ### Setup and Test MySQL BoxProvisioning Source: https://github.com/brightercommand/brighter/blob/master/specs/0028-box-provisioning-rdd-role-interfaces/tasks.md Sets up a MySQL Docker container, builds the test project, runs BoxProvisioning tests for .NET 9.0, and tears down the container. Ensure the test project is built before running tests to avoid stale DLLs. ```bash docker compose -f docker-compose-mysql.yaml up -d ``` ```bash dotnet build tests/Paramore.Brighter.MySQL.Tests -f net9.0 ``` ```bash dotnet test tests/Paramore.Brighter.MySQL.Tests -f net9.0 --filter "FullyQualifiedName~BoxProvisioning" ``` ```bash docker compose -f docker-compose-mysql.yaml down ``` -------------------------------- ### Start Floci for AWS Emulation Source: https://github.com/brightercommand/brighter/blob/master/samples/Scheduler/QuartzTaskQueue/README.md Starts the Floci Docker container for emulating AWS SQS/SNS services locally. Ensure Docker is installed and running. ```sh docker-compose -f docker-compose-aws.yaml up ``` -------------------------------- ### Install Out-of-Process Transport Packages Source: https://github.com/brightercommand/brighter/blob/master/README.md Install a transport package for your chosen message broker to enable out-of-process messaging. Examples include RabbitMQ, AWS SQS, and Kafka. ```bash dotnet add package Paramore.Brighter.MessagingGateway.RMQ.Async # RabbitMQ dotnet add package Paramore.Brighter.MessagingGateway.AWSSQS.V4 # AWS SQS (uses AWS SDK v4; use AWSSQS for v3) dotnet add package Paramore.Brighter.MessagingGateway.Kafka # Kafka ``` -------------------------------- ### Migration Catalogues: Static to Instance Classes Source: https://github.com/brightercommand/brighter/blob/master/release_notes.md Illustrates the change from using static migration classes to instance classes for migration catalogues. The 'Before' example shows direct usage of a static class, while the 'After' example demonstrates instantiating a catalog and calling its methods, or receiving it via dependency injection. ```csharp // Before IReadOnlyList migrations = MsSqlOutboxMigrations.All(config); // After IAmABoxMigrationCatalog catalog = new MsSqlOutboxMigrationCatalog(); IReadOnlyList migrations = catalog.All(config); // or receive the catalogue via DI (singleton lifetime registered by AddMsSqlOutbox). ``` -------------------------------- ### Configure Quartz.NET Scheduler Source: https://github.com/brightercommand/brighter/blob/master/release_notes.md Example of configuring and building a Quartz.NET scheduler factory for use with Brighter. ```csharp var schedulerFactory = SchedulerBuilder.Create(new NameValueCollection()) .UseDefaultThreadPool(x => x.MaxConcurrency = 5) .UseJobFactory() .Build(); var scheduler = schedulerFactory.GetScheduler().GetAwaiter().GetResult(); scheduler.Start().GetAwaiter().GetResult(); _scheduler = new QuartzSchedulerFactory(scheduler); ``` -------------------------------- ### MSSQL V2 Inbox UpScript Example Source: https://github.com/brightercommand/brighter/blob/master/specs/0027-box-schema-versioning-and-migrations/tasks.md Illustrates the SQL pattern for the V2 UpScript, which checks for the existence of the 'ContextKey' column before altering the table to add it. This ensures backward compatibility and handles existing installations gracefully. ```sql IF COL_LENGTH(...'ContextKey') IS NULL ALTER TABLE ... ADD [ContextKey] NVARCHAR(128) NULL ``` -------------------------------- ### Configure and Send a Command Source: https://github.com/brightercommand/brighter/blob/master/README.md Configure the Brighter host services and obtain an `IAmACommandProcessor` to send commands. This example demonstrates in-process command dispatching. ```csharp // Setup var builder = Host.CreateApplicationBuilder(); builder.Services.AddBrighter().AutoFromAssemblies(); var host = builder.Build(); var commandProcessor = host.Services.GetRequiredService(); // Send command (in-process) commandProcessor.Send(new GreetingCommand("World")); ``` -------------------------------- ### Start the Sender Source: https://github.com/brightercommand/brighter/blob/master/samples/TaskQueue/RMQDeferOnError/README.md Starts the message sender application. Run this in a separate terminal from the receiver. ```sh cd samples/TaskQueue/RMQDeferOnError/GreetingsSender dotnet run ``` -------------------------------- ### Start MySQL with Docker Compose Source: https://github.com/brightercommand/brighter/blob/master/samples/WebAPI/WebAPI_EFCore/README.md This command starts only the MySQL service using Docker Compose. ```sh docker compose up -d mysql ``` -------------------------------- ### Start RabbitMQ with Docker Compose Source: https://github.com/brightercommand/brighter/blob/master/samples/WebAPI/WebAPI_EFCore/README.md This command starts only the RabbitMQ service using Docker Compose. ```sh docker compose up -d rabbitmq ``` -------------------------------- ### Setup and Test Spanner BoxProvisioning (net9.0) Source: https://github.com/brightercommand/brighter/blob/master/specs/0028-box-provisioning-rdd-role-interfaces/tasks.md Sets up the Spanner emulator, configures environment variables, and runs BoxProvisioning tests for .NET 9.0. This is a sanity check to ensure Spanner is unaffected by the rename. Tears down the emulator afterwards. ```bash docker compose -f docker-compose-spanner.yaml up -d ``` ```bash export SPANNER_EMULATOR_HOST=localhost:9010 && export GOOGLE_CLOUD_PROJECT=brighter-tests ``` ```bash dotnet test tests/Paramore.Brighter.Gcp.Tests -f net9.0 --filter "FullyQualifiedName~BoxProvisioning" ``` ```bash docker compose -f docker-compose-spanner.yaml down ``` -------------------------------- ### Start the Receiver Source: https://github.com/brightercommand/brighter/blob/master/samples/TaskQueue/RMQDeferOnError/README.md Starts the message receiver console application. Navigate to the receiver directory before running. ```sh cd samples/TaskQueue/RMQDeferOnError/GreetingsReceiverConsole dotnet run ``` -------------------------------- ### String Templated Logging Example (Before) Source: https://github.com/brightercommand/brighter/blob/master/docs/adr/0026-use-source-generated-logging.md Illustrates the traditional string-templated logging approach before migration. This pattern is being replaced by source-generated logging. ```csharp namespace Brighter; class SomeClass { static readonly ILogger s_logger = ...; void Hello(name) { s_logger.LogInformation("Hello {Name}", name); } } ``` -------------------------------- ### MSSQL Outbox Provisioner Implementation Source: https://github.com/brightercommand/brighter/blob/master/docs/adr/0053-box-database-migration.md Example of a backend provisioner for MSSQL outbox. It encapsulates database connection, DDL, and migration logic, using a migration runner to apply necessary changes. ```csharp public class MsSqlOutboxProvisioner : IAmABoxProvisioner { private readonly IAmARelationalDatabaseConfiguration _configuration; private readonly IAmABoxMigrationRunner _migrationRunner; public MsSqlOutboxProvisioner( IAmARelationalDatabaseConfiguration configuration, IAmABoxMigrationRunner migrationRunner) { _configuration = configuration; _migrationRunner = migrationRunner; } public BoxType BoxType => BoxType.Outbox; public async Task ProvisionAsync(CancellationToken cancellationToken = default) { var migrations = MsSqlOutboxMigrations.All(_configuration); // The provisioner owns all schema introspection knowledge and gathers // the current state into a BoxTableState record. The runner's job is // purely "apply the right migrations given this state". var tableState = await DetectTableStateAsync(cancellationToken); await _migrationRunner.MigrateAsync( _configuration.OutBoxTableName, _configuration.SchemaName, migrations, tableState, cancellationToken); } private async Task DetectTableStateAsync( CancellationToken cancellationToken) { await using var connection = new SqlConnection(_configuration.ConnectionString); await connection.OpenAsync(cancellationToken); // 1. Does the box table exist? var tableExists = await DoesTableExistAsync(connection, cancellationToken); if (!tableExists) return new BoxTableState(TableExists: false, HistoryExists: false, CurrentVersion: 0); // 2. Does migration history exist for this table? var historyExists = await DoesHistoryExistAsync(connection, cancellationToken); if (!historyExists) { // 3. Bootstrap: introspect columns to detect current schema version var detectedVersion = await DetectCurrentVersionAsync(connection, cancellationToken); return new BoxTableState(TableExists: true, HistoryExists: false, CurrentVersion: detectedVersion); } // 4. Normal: read max applied version from history var maxVersion = await GetMaxVersionAsync(connection, cancellationToken); return new BoxTableState(TableExists: true, HistoryExists: true, CurrentVersion: maxVersion); } } ``` -------------------------------- ### Install Paramore.Brighter.AsyncAPI Packages Source: https://github.com/brightercommand/brighter/blob/master/src/Paramore.Brighter.AsyncAPI/README.md Add the necessary Paramore.Brighter.AsyncAPI packages to your project using the dotnet CLI. ```bash dotnet add package Paramore.Brighter.AsyncAPI dotnet add package Paramore.Brighter.AsyncAPI.NJsonSchema ``` -------------------------------- ### Start the Receiver Source: https://github.com/brightercommand/brighter/blob/master/samples/TaskQueue/KafkaDontAckOnError/README.md Navigate to the receiver console directory and run this command to start the message receiver application. ```sh cd samples/TaskQueue/KafkaDontAckOnError/GreetingsReceiverConsole dotnet run ``` -------------------------------- ### FeatureSwitchAttribute Usage Example Source: https://github.com/brightercommand/brighter/blob/master/docs/adr/0038-dont-ack-action.md Example of using FeatureSwitchAttribute with dontAck set to true. When the feature is off, the message will not be acknowledged. ```csharp [FeatureSwitch(typeof(MyHandler), FeatureSwitchStatus.Config, step: 1, dontAck: true)] public override MyMessage Handle(MyMessage message) { // When feature is off: message stays on channel // When feature is on: normal processing return base.Handle(message); } ``` -------------------------------- ### Example of HashSet Initialization in MsSqlOutboxMigrationCatalog.cs Source: https://github.com/brightercommand/brighter/blob/master/specs/0030-primitive_obsession/review-requirements.md Demonstrates the initialization of a HashSet with StringComparer.OrdinalIgnoreCase, as found in the MsSqlOutboxMigrationCatalog.cs file. This is relevant to how logical columns are processed. ```csharp var set = new HashSet(StringComparer.OrdinalIgnoreCase); ``` -------------------------------- ### Start the Sender Source: https://github.com/brightercommand/brighter/blob/master/samples/TaskQueue/KafkaTaskQueueWithDLQ/README.md Starts the sender application to send messages to the Kafka topic, initiating the message processing flow. ```sh cd samples/TaskQueue/KafkaTaskQueueWithDLQ/GreetingsSender dotnet run ``` -------------------------------- ### Kafka Producer and Consumer Factory Setup Source: https://github.com/brightercommand/brighter/blob/master/specs/0001-kafka-dead-letter-queue/test-analysis.md Illustrates the common pattern for setting up Kafka producers and consumers in tests. Requires Kafka running on localhost:9092. ```csharp // Create KafkaProducerRegistryFactory with configuration pointing to localhost:9092 // Create KafkaMessageConsumerFactory with subscription // Send messages via producer // Receive messages via consumer // Call consumer.Acknowledge(message) or consumer.Reject(message) // Use Task.Delay() to allow Kafka propagation // Verify behavior ``` -------------------------------- ### Run MSSQL Server with Docker Source: https://github.com/brightercommand/brighter/blob/master/tests/Paramore.Brighter.MSSQL.Tests/ReadMe.md Use this command to start a SQL Server instance in Docker. Ensure you accept the EULA and set a strong SA password. ```bash docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=Password123!' -p 11433:1433 -d mcr.microsoft.com/mssql/server:latest ``` -------------------------------- ### Real Example: New Feature with /test-first Source: https://github.com/brightercommand/brighter/blob/master/docs/NEW_SKILLS_GUIDE.md Use `/test-first` when adding a new feature to a clean codebase. This ensures TDD practices are followed with an enforced approval step. ```bash # Clean codebase, just add feature /test-first when message fails validation it should log error details ``` -------------------------------- ### Start the Sender Source: https://github.com/brightercommand/brighter/blob/master/samples/TaskQueue/KafkaDontAckOnError/README.md In a separate terminal, navigate to the sender directory and run this command to start the message sender application. ```sh cd samples/TaskQueue/KafkaDontAckOnError/GreetingsSender dotnet run ``` -------------------------------- ### Build and Test Solution Locally Source: https://github.com/brightercommand/brighter/blob/master/CONTRIBUTING.md Use dotnet CLI commands to build the entire solution and run core tests locally. Ensure all tests pass before submitting a Pull Request. ```bash # Build entire solution dotnet build Brighter.slnx # Run core tests (no external dependencies needed) dotnet test tests/Paramore.Brighter.Core.Tests # Run all tests (requires Docker services - see below) dotnet test ``` -------------------------------- ### C# Documentation Comment Example Source: https://github.com/brightercommand/brighter/blob/master/CONTRIBUTING.md Example of XML documentation comments for a C# property, including summary and value tags. ```csharp /// /// Gets or sets the current status. /// /// The current status as a . public string Status { get; set; } ``` -------------------------------- ### Receiver Console Output Example Source: https://github.com/brightercommand/brighter/blob/master/samples/TaskQueue/KafkaDontAckOnError/README.md This is an example of the expected output from the GreetingsReceiverConsole, illustrating successful message processing and simulated failure. ```text Received message #1: Hello # 1 -> Successfully processed message #1 Received message #2: Hello # 2 -> Successfully processed message #2 ... Received message #5: Hello # 5 -> Simulating failure for message #5 (offset will not be committed) ``` -------------------------------- ### Configure Brighter with MS SQL Outbox Provisioning using Aspire Source: https://github.com/brightercommand/brighter/blob/master/docs/adr/0053-box-database-migration.md This configuration is for use with Aspire, where database connections are discovered automatically. It sets up MS SQL outbox provisioning. ```csharp services.AddBrighter() .AddProducers(...) .UseBoxProvisioning(options => { options.AddMsSqlOutbox(); // connection from }); // Aspire discovery ``` -------------------------------- ### DontAckOnErrorAttribute Usage Example Source: https://github.com/brightercommand/brighter/blob/master/docs/adr/0038-dont-ack-action.md Example of using DontAckOnErrorAttribute. If the handler fails after retries, the message will remain on the channel instead of being acknowledged. ```csharp [DontAckOnError(step: 0)] // Outermost - catches anything [UsePolicy("RetryPolicy", step: 2)] // Retries first public override MyMessage Handle(MyMessage message) { // If this fails after retries, message stays on channel return base.Handle(message); } ```