Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
e7e2fd7
feat(network): add ITransportCodec contract and test codec
tgiachi Jun 26, 2026
3e76b9f
feat(network): add ConnectionPipeline per-connection descriptor
tgiachi Jun 26, 2026
23ed22b
feat(network): apply per-connection transport codec on send and receive
tgiachi Jun 26, 2026
8b9d447
fix(network): keep receive history in sync with decoded output and cl…
tgiachi Jun 26, 2026
2429914
style(network): drop unused codec using in TCP server
tgiachi Jun 26, 2026
eefd529
feat(network): add atomic SwapCodec for mid-connection codec upgrade
tgiachi Jun 26, 2026
5a8be55
test(network): cover per-connection codec state isolation
tgiachi Jun 26, 2026
ddf732c
test(network): cover codec combined with stream framing
tgiachi Jun 26, 2026
851e4c8
test(network): cover keystream integrity under concurrent sends
tgiachi Jun 26, 2026
d4a5187
test(network): confirm codec-less path is unchanged
tgiachi Jun 26, 2026
267ca7b
merge: per-connection transport codec in SquidStd.Network
tgiachi Jun 26, 2026
30b0d57
feat(events): add IEventListener<T> and EventBusOptions contracts
tgiachi Jun 26, 2026
fcb84b1
feat(events): parallel dispatch, catch-all, fault isolation, delegate…
tgiachi Jun 26, 2026
f1940ef
feat(events): DI-native listener auto-subscription
tgiachi Jun 26, 2026
cf78fcb
merge: parallel event bus dispatch with catch-all, fault isolation, a…
tgiachi Jun 26, 2026
7c3e45c
build: add source generator project
tgiachi Jun 26, 2026
1292f18
test: cover generated event listener registration
tgiachi Jun 26, 2026
f8786d8
feat: generate event listener registrations
tgiachi Jun 26, 2026
daef78b
build: track generator diagnostics
tgiachi Jun 26, 2026
58e0454
docs: demonstrate generated event listener registration
tgiachi Jun 26, 2026
2b99967
feat: require event listener registration attribute
tgiachi Jun 26, 2026
a099b19
docs: document source generator registration
tgiachi Jun 26, 2026
6d15f77
build: fix generator analyzer package symbols
tgiachi Jun 26, 2026
e6cfee7
feat: add generated registration attributes
tgiachi Jun 26, 2026
be78e57
test: prepare registration generator harness
tgiachi Jun 26, 2026
febf319
feat: generate standard service registrations
tgiachi Jun 26, 2026
092e52e
feat: generate config section registrations
tgiachi Jun 26, 2026
e16ab20
feat: generate job handler registrations
tgiachi Jun 26, 2026
d879f42
feat: generate lua script module registrations
tgiachi Jun 26, 2026
ea652ca
docs: demonstrate generated registrations
tgiachi Jun 26, 2026
2ca1ef1
Merge branch 'feat/source-generators-registration' into develop
tgiachi Jun 26, 2026
3ecbd63
style: format code with JetBrains cleanup
tgiachi Jun 26, 2026
7cdb74f
feat(core): add FNV-1a ChecksumUtils
tgiachi Jun 26, 2026
4f3fce2
feat(persistence): scaffold persistence packages and abstractions
tgiachi Jun 26, 2026
1711672
feat(persistence): fixed-binary journal and snapshot codecs
tgiachi Jun 26, 2026
27b7cfe
feat(persistence): state store and serializer-injected entity descriptor
tgiachi Jun 26, 2026
6aa4b74
feat(persistence): binary append-only journal service
tgiachi Jun 26, 2026
f5a6e45
feat(persistence): atomic per-type binary snapshot service
tgiachi Jun 26, 2026
b3d822f
feat(persistence): entity descriptor registry
tgiachi Jun 26, 2026
c9a242e
feat(persistence): in-memory entity store with write-ordered journaling
tgiachi Jun 26, 2026
532ad55
feat(persistence): lifecycle service with snapshot+journal replay and…
tgiachi Jun 26, 2026
bf2a046
feat(persistence): MessagePack serializer provider and DI entity regi…
tgiachi Jun 26, 2026
73518e3
test(persistence): end-to-end snapshot+journal restart cycle
tgiachi Jun 26, 2026
0310e97
docs(persistence): module READMEs, root table rows, and runnable sample
tgiachi Jun 26, 2026
0c6a36d
style(persistence): apply JetBrains cleanup
tgiachi Jun 26, 2026
8a0eb2c
merge: binary persistence engine (in-memory store + snapshot/journal)
tgiachi Jun 26, 2026
1e71541
build: bump Microsoft.CodeAnalysis.CSharp to 5.3.0
tgiachi Jun 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,13 @@ block until cancellation for long-running hosts.
|---------|-------------|-------|
| `SquidStd.Core` | Foundational contracts & utilities (config, event bus, jobs, metrics, serialization, YAML/JSON, Serilog sink). | [![readme](https://img.shields.io/badge/readme-1390A3.svg)](src/SquidStd.Core/README.md) · [![NuGet](https://img.shields.io/nuget/v/SquidStd.Core.svg)](https://www.nuget.org/packages/SquidStd.Core/) |
| `SquidStd.Abstractions` | DI registration plumbing (`ISquidStdService`, `RegisterStdService`, `RegisterConfigSection`). | [![readme](https://img.shields.io/badge/readme-1390A3.svg)](src/SquidStd.Abstractions/README.md) · [![NuGet](https://img.shields.io/nuget/v/SquidStd.Abstractions.svg)](https://www.nuget.org/packages/SquidStd.Abstractions/) |
| `SquidStd.Generators` | Roslyn source generators for event listener, service, config, worker, and Lua registration helpers. | [![readme](https://img.shields.io/badge/readme-1390A3.svg)](src/SquidStd.Generators/README.md) · [![NuGet](https://img.shields.io/nuget/v/SquidStd.Generators.svg)](https://www.nuget.org/packages/SquidStd.Generators/) |
| `SquidStd.Services.Core` | Concrete services: config, event bus, jobs, timer/cron scheduler, dispatcher, metrics, health checks, secrets. | [![readme](https://img.shields.io/badge/readme-1390A3.svg)](src/SquidStd.Services.Core/README.md) · [![NuGet](https://img.shields.io/nuget/v/SquidStd.Services.Core.svg)](https://www.nuget.org/packages/SquidStd.Services.Core/) |
| `SquidStd.AspNetCore` | ASP.NET Core host integration for the SquidStd service stack. | [![readme](https://img.shields.io/badge/readme-1390A3.svg)](src/SquidStd.AspNetCore/README.md) · [![NuGet](https://img.shields.io/nuget/v/SquidStd.AspNetCore.svg)](https://www.nuget.org/packages/SquidStd.AspNetCore/) |
| `SquidStd.Network` | TCP/UDP servers & clients, sessions, framing/middleware pipeline, span readers/writers. | [![readme](https://img.shields.io/badge/readme-1390A3.svg)](src/SquidStd.Network/README.md) · [![NuGet](https://img.shields.io/nuget/v/SquidStd.Network.svg)](https://www.nuget.org/packages/SquidStd.Network/) |
| `SquidStd.Persistence.Abstractions` | Binary-persistence contracts (`IEntityStore<T,TKey>`, `IPersistenceService`, journal/snapshot/registry, `PersistenceConfig`). | [![readme](https://img.shields.io/badge/readme-1390A3.svg)](src/SquidStd.Persistence.Abstractions/README.md) · [![NuGet](https://img.shields.io/nuget/v/SquidStd.Persistence.Abstractions.svg)](https://www.nuget.org/packages/SquidStd.Persistence.Abstractions/) |
| `SquidStd.Persistence` | In-memory entity store with durable binary snapshot + journal (WAL); serializer-agnostic engine. | [![readme](https://img.shields.io/badge/readme-1390A3.svg)](src/SquidStd.Persistence/README.md) · [![NuGet](https://img.shields.io/nuget/v/SquidStd.Persistence.svg)](https://www.nuget.org/packages/SquidStd.Persistence/) |
| `SquidStd.Persistence.MessagePack` | MessagePack-backed binary `IDataSerializer` for SquidStd.Persistence (recommended default). | [![readme](https://img.shields.io/badge/readme-1390A3.svg)](src/SquidStd.Persistence.MessagePack/README.md) · [![NuGet](https://img.shields.io/nuget/v/SquidStd.Persistence.MessagePack.svg)](https://www.nuget.org/packages/SquidStd.Persistence.MessagePack/) |
| `SquidStd.Plugin.Abstractions` | Plugin contracts (`ISquidStdPlugin`, metadata, context). | [![readme](https://img.shields.io/badge/readme-1390A3.svg)](src/SquidStd.Plugin.Abstractions/README.md) · [![NuGet](https://img.shields.io/nuget/v/SquidStd.Plugin.Abstractions.svg)](https://www.nuget.org/packages/SquidStd.Plugin.Abstractions/) |
| `SquidStd.Database.Abstractions` | Provider-agnostic data-access contracts (`IDataAccess<T>`, `BaseEntity`, `PagedResultData`). | [![readme](https://img.shields.io/badge/readme-1390A3.svg)](src/SquidStd.Database.Abstractions/README.md) · [![NuGet](https://img.shields.io/nuget/v/SquidStd.Database.Abstractions.svg)](https://www.nuget.org/packages/SquidStd.Database.Abstractions/) |
| `SquidStd.Database` | FreeSql-backed data access (CRUD/bulk/paging, URI connection strings, ZLinq helpers). | [![readme](https://img.shields.io/badge/readme-1390A3.svg)](src/SquidStd.Database/README.md) · [![NuGet](https://img.shields.io/nuget/v/SquidStd.Database.svg)](https://www.nuget.org/packages/SquidStd.Database/) |
Expand Down
5 changes: 5 additions & 0 deletions SquidStd.slnx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<Solution>
<Folder Name="/src/">
<Project Path="src/SquidStd.Abstractions/SquidStd.Abstractions.csproj"/>
<Project Path="src/SquidStd.Generators/SquidStd.Generators.csproj"/>
<Project Path="src/SquidStd.Telemetry.Abstractions/SquidStd.Telemetry.Abstractions.csproj"/>
<Project Path="src/SquidStd.Telemetry.OpenTelemetry/SquidStd.Telemetry.OpenTelemetry.csproj"/>
<Project Path="src/SquidStd.Aws.Abstractions/SquidStd.Aws.Abstractions.csproj"/>
Expand All @@ -16,6 +17,9 @@
<Project Path="src/SquidStd.Messaging.Sqs/SquidStd.Messaging.Sqs.csproj"/>
<Project Path="src/SquidStd.Messaging/SquidStd.Messaging.csproj"/>
<Project Path="src/SquidStd.Network/SquidStd.Network.csproj"/>
<Project Path="src/SquidStd.Persistence.Abstractions/SquidStd.Persistence.Abstractions.csproj"/>
<Project Path="src/SquidStd.Persistence/SquidStd.Persistence.csproj"/>
<Project Path="src/SquidStd.Persistence.MessagePack/SquidStd.Persistence.MessagePack.csproj"/>
<Project Path="src/SquidStd.Plugin.Abstractions/SquidStd.Plugin.Abstractions.csproj"/>
<Project Path="src/SquidStd.Scripting.Lua/SquidStd.Scripting.Lua.csproj"/>
<Project Path="src/SquidStd.Services.Core/SquidStd.Services.Core.csproj"/>
Expand All @@ -41,6 +45,7 @@
<Project Path="samples/SquidStd.Samples.ScriptingLua/SquidStd.Samples.ScriptingLua.csproj"/>
<Project Path="samples/SquidStd.Samples.Plugins/SquidStd.Samples.Plugins.csproj"/>
<Project Path="samples/SquidStd.Samples.Networking/SquidStd.Samples.Networking.csproj"/>
<Project Path="samples/SquidStd.Samples.Persistence/SquidStd.Samples.Persistence.csproj"/>
<Project Path="samples/SquidStd.Samples.Email/SquidStd.Samples.Email.csproj"/>
<Project Path="samples/SquidStd.Samples.Database/SquidStd.Samples.Database.csproj"/>
<Project Path="samples/SquidStd.Samples.AspNetCore/SquidStd.Samples.AspNetCore.csproj"/>
Expand Down
122 changes: 122 additions & 0 deletions docs/articles/source-generators.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# SquidStd.Generators

`SquidStd.Generators` contains Roslyn source generators that create compile-time registration helpers for SquidStd projects.

Generators are opt-in per registration surface. Mark the type you want registered and call the generated extension method while configuring the DryIoc container:

```csharp
container.RegisterGeneratedEventListeners();
container.RegisterGeneratedStdServices();
container.RegisterGeneratedConfigSections();
container.RegisterGeneratedJobHandlers();
container.RegisterGeneratedScriptModules();
```

Each generated method uses the same runtime path as manual registration. For example, the event listener generator emits:

```csharp
container.RegisterEventListener<PingEvent, PingListener>();
```

This keeps startup behavior compatible with `EventListenerActivator` and the normal `SquidStdBootstrap` lifecycle.

## Usage

Add the generator package:

```bash
dotnet add package SquidStd.Generators
```

Call the generated extension while configuring the DryIoc container:

```csharp
using SquidStd.Abstractions.Attributes;
using SquidStd.Core.Interfaces.Events;
using SquidStd.Generators.Events;

[RegisterEventListener]
public sealed class PingListener : IEventListener<PingEvent>
{
public Task HandleAsync(PingEvent eventData, CancellationToken cancellationToken = default)
{
Console.WriteLine(eventData.Message);

return Task.CompletedTask;
}
}

bootstrap.ConfigureServices(container => container.RegisterGeneratedEventListeners());
```

## Generated registration families

### Event listeners

Use `[RegisterEventListener]` on a concrete `IEventListener<TEvent>` implementation and call:

```csharp
using SquidStd.Generators.Events;

container.RegisterGeneratedEventListeners();
```

### Standard services

Use `[RegisterStdService(typeof(IMyService), Priority = 10)]` on the implementation and call:

```csharp
using SquidStd.Generators.Services;

container.RegisterGeneratedStdServices();
```

The generator emits `RegisterStdService<IMyService, MyService>(container, 10)`.

### Config sections

Use `[RegisterConfigSection("workers", Priority = -50)]` on the config type and call:

```csharp
using SquidStd.Generators.Config;

container.RegisterGeneratedConfigSections();
```

The generator emits `RegisterConfigSection<WorkersConfig>(container, "workers", priority: -50)`.

### Job handlers

Use `[RegisterJobHandler]` on an `IJobHandler` implementation and call:

```csharp
using SquidStd.Generators.Workers;

container.RegisterGeneratedJobHandlers();
```

The generator emits `AddJobHandler<MyJobHandler>(container)`.

### Lua script modules

Use `[RegisterScriptModule]` together with the runtime `[ScriptModule("name")]` metadata and call:

```csharp
using SquidStd.Generators.Scripting.Lua;

container.RegisterGeneratedScriptModules();
```

The generator emits `RegisterScriptModule<MyScriptModule>(container)`.

## Supported shapes and diagnostics

Generated source can only reference public or internal non-generic concrete classes. Unsupported types are skipped and reported as warnings.

| Diagnostic | Registration family |
|------------|---------------------|
| `SQDGEN001` | Event listener cannot be generated. |
| `SQDGEN002` | Standard service cannot be generated. |
| `SQDGEN003` | Config section cannot be generated. |
| `SQDGEN004` | Job handler cannot be generated. |
| `SQDGEN005` | Script module cannot be generated. |
2 changes: 2 additions & 0 deletions docs/articles/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
href: core.md
- name: SquidStd.Abstractions
href: abstractions.md
- name: SquidStd.Generators
href: source-generators.md
- name: SquidStd.Services.Core
href: services-core.md
- name: SquidStd.AspNetCore
Expand Down
2 changes: 1 addition & 1 deletion docs/docfx.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
{
"src": "../",
"files": [ "src/**/*.csproj" ],
"exclude": [ "**/bin/**", "**/obj/**" ]
"exclude": [ "**/bin/**", "**/obj/**", "src/SquidStd.Generators/**" ]
}
],
"dest": "api",
Expand Down
13 changes: 12 additions & 1 deletion docs/tutorials/scripting-lua.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@ bootstrap, runs a small Lua script, and prints values evaluated by the engine.
- .NET 10 SDK
- `dotnet add package SquidStd.Scripting.Lua`
- `dotnet add package SquidStd.Services.Core`
- `dotnet add package SquidStd.Generators`

## Steps

### 1. Register the Lua engine

The engine needs a `LuaEngineConfig` (it watches a scripts directory) and is started by the bootstrap as a
SquidStd service. The `DirectoriesConfig` it depends on is already registered by the core services.
SquidStd service. The `DirectoriesConfig` it depends on is already registered by the core services. The generated
script-module registration call adds any `[RegisterScriptModule]` modules before startup.

[!code-csharp[](../../samples/SquidStd.Samples.ScriptingLua/Program.cs#step-1)]

Expand All @@ -29,6 +31,13 @@ SquidStd service. The `DirectoriesConfig` it depends on is already registered by

[!code-csharp[](../../samples/SquidStd.Samples.ScriptingLua/Program.cs#step-2)]

### 3. Define a generated module

`[RegisterScriptModule]` opts the type into source generation. `[ScriptModule("sample")]` is still the runtime Lua
metadata used as the module name.

[!code-csharp[](../../samples/SquidStd.Samples.ScriptingLua/Program.cs#step-3)]

## Run it

```bash
Expand All @@ -38,6 +47,7 @@ dotnet run --project samples/SquidStd.Samples.ScriptingLua
Prints:

```
lua modules = 1
3 + 4 = 7
result = hello from C# and lua
```
Expand All @@ -52,3 +62,4 @@ configured scripts directory. Globals you register become Lua variables, and `Ex
## See also

- [SquidStd.Scripting.Lua reference](../articles/scripting-lua.md)
- [Generated registrations](source-generators-registration.md)
53 changes: 53 additions & 0 deletions docs/tutorials/source-generators-event-listeners.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Generated event listener registration

This tutorial shows how to use `SquidStd.Generators` to register event listeners at compile time.

## Add the generator

```bash
dotnet add package SquidStd.Generators
```

## Create an event and listener

```csharp
using SquidStd.Abstractions.Attributes;
using SquidStd.Core.Interfaces.Events;

public sealed record PingEvent(string Message) : IEvent;

[RegisterEventListener]
public sealed class PingListener : IEventListener<PingEvent>
{
public Task HandleAsync(PingEvent eventData, CancellationToken cancellationToken = default)
{
Console.WriteLine(eventData.Message);

return Task.CompletedTask;
}
}
```

## Register generated listeners

```csharp
using SquidStd.Generators.Events;
using SquidStd.Services.Core.Services.Bootstrap;

var bootstrap = SquidStdBootstrap.Create()
.ConfigureServices(container => container.RegisterGeneratedEventListeners());

await bootstrap.StartAsync();
```

At build time the generator emits a method that calls:

```csharp
container.RegisterEventListener<PingEvent, PingListener>();
```

The listener is then subscribed during the normal SquidStd service startup.

## See also

- [Generated registrations](source-generators-registration.md)
84 changes: 84 additions & 0 deletions docs/tutorials/source-generators-registration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Generated registrations

Use `SquidStd.Generators` to replace repetitive manual registration calls with compile-time generated DryIoc extensions.

## Add the generator

```bash
dotnet add package SquidStd.Generators
```

## Standard services

```csharp
using SquidStd.Abstractions.Attributes;
using SquidStd.Abstractions.Interfaces.Services;
using SquidStd.Generators.Services;

public interface IGreetingService : ISquidStdService { }

[RegisterStdService(typeof(IGreetingService), Priority = 10)]
public sealed class GreetingService : IGreetingService
{
public ValueTask StartAsync(CancellationToken cancellationToken = default) => ValueTask.CompletedTask;

public ValueTask StopAsync(CancellationToken cancellationToken = default) => ValueTask.CompletedTask;
}

container.RegisterGeneratedStdServices();
```

## Config sections

```csharp
using SquidStd.Abstractions.Attributes;
using SquidStd.Generators.Config;

[RegisterConfigSection("greeting", Priority = -10)]
public sealed class GreetingConfig
{
public string Message { get; set; } = "hello";
}

container.RegisterGeneratedConfigSections();
```

## Job handlers

```csharp
using SquidStd.Generators.Workers;
using SquidStd.Workers.Abstractions.Data;
using SquidStd.Workers.Attributes;
using SquidStd.Workers.Interfaces;

[RegisterJobHandler]
public sealed class GreetingJobHandler : IJobHandler
{
public string JobName => "greet";

public Task HandleAsync(JobRequest job, CancellationToken cancellationToken)
{
Console.WriteLine(job.JobName);

return Task.CompletedTask;
}
}

container.RegisterGeneratedJobHandlers();
```

## Lua script modules

```csharp
using SquidStd.Generators.Scripting.Lua;
using SquidStd.Scripting.Lua.Attributes;
using SquidStd.Scripting.Lua.Attributes.Scripts;

[RegisterScriptModule]
[ScriptModule("greeting")]
public sealed class GreetingScriptModule { }

container.RegisterGeneratedScriptModules();
```

The Lua generator only emits `RegisterScriptModule<T>()`; `[ScriptModule("name")]` is still required because the Lua runtime uses it as the module name.
4 changes: 4 additions & 0 deletions docs/tutorials/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
href: getting-started.md
- name: Events, jobs and scheduling
href: events-jobs-scheduling.md
- name: Generated event listener registration
href: source-generators-event-listeners.md
- name: Generated registrations
href: source-generators-registration.md
- name: Caching
href: caching.md
- name: Messaging
Expand Down
Loading
Loading