# MIDCON.Backend.Plugin.Abstractions

Shared contracts for **MIDCON Backend Server** hot-swap plugins and their optional scheduled
worker processes.

Provides the minimal, dependency-light interface surface that both the Gateway process and a
plugin's isolated `AssemblyLoadContext` load from the same Default-ALC assembly — without this,
hot-swap plugin types would suffer type-identity mismatches across ALC boundaries.

---

## Installation

```bash
dotnet add package MIDCON.Backend.Plugin.Abstractions
```

Or in your `.csproj`:

```xml
<PackageReference Include="MIDCON.Backend.Plugin.Abstractions" Version="x.y.z" />
```

---

## Contents

| Type | Purpose |
|---|---|
| `IOdooPlugin` | Hot-swap plugin handler contract (`HandleRequestAsync`) — implement this instead of `OdooPluginControllerBase` when no MVC stack is needed and hot-swap (no gateway restart) is desired. |
| `IPluginWorker` | Contract for periodically executed plugin code that runs in a separate, gateway-managed child process ([ADR-0020](https://github.com/JDueckMidCon/midcon-server/blob/develop/docs/architecture-decisions/0020-plugin-scheduling-separater-worker-prozess.md)). Optional, declared via the `worker` section in the MCM manifest. |
| `IPluginWorkerContext` | Runtime context passed to `IPluginWorker.RunAsync` — exposes an `HttpClient` pre-configured for gateway-loopback calls with an auto-refreshed token. |
| `WorkerScheduleType` | `Daily` or `Interval` — shared between the worker host's scheduling loop and the gateway's manifest parsing/spawn arguments. |

Target framework: **net10.0**

---

## `IOdooPlugin` — hot-swap plugin contract

```csharp
using MIDCON.Backend.Plugin.Abstractions;

public sealed class MyPlugin : IOdooPlugin
{
    public string PluginId => "my-plugin";
    public string Version => "1.0.0";

    public Task<IResult> HandleRequestAsync(HttpContext context, string remainingPath) =>
        Task.FromResult(Results.Ok(new { message = "hello" }));

    public void Dispose() { }
}
```

## `IPluginWorker` — scheduled background task contract

```csharp
using MIDCON.Backend.Plugin.Abstractions;

public sealed class MyWorker : IPluginWorker
{
    public async Task RunAsync(IPluginWorkerContext context, CancellationToken ct)
    {
        // context.HttpClient is pre-authenticated against the gateway's own plugin route.
        await context.HttpClient.PostAsync("expire-check", content: null, ct);
    }
}
```

Binding contract for implementations (ADR-0020, not just a recommendation):

- **Interruptible/repeatable** — the host can cancel `RunAsync` via `ct` at any time (hang-kill,
  gateway shutdown, plugin update). Implementations must tolerate being interrupted mid-tick and
  re-invoked on the next schedule without duplicate side effects (writes must be idempotent).
- **Binary success/failure** — a normal return means the tick succeeded; a thrown exception means
  it failed. There is no third "partially succeeded" state.
- **No overlap** — the host never starts a new tick while the previous one is still running.

---

## Versioning

This package uses [GitVersion](https://gitversion.net/) via `GitVersion.MsBuild`. The version is
derived automatically from the git history and tags.

```bash
git tag v1.0.0
dotnet pack -c Release
```

---

## Building & Packing

```bash
# Restore & build
dotnet build src/MIDCON.Backend.Plugin.Abstractions.slnx -c Release

# Create NuGet package
dotnet pack src/MIDCON.Backend.Plugin.Abstractions/MIDCON.Backend.Plugin.Abstractions.csproj -c Release -o ./artifacts
```

The resulting `.nupkg` is in `./artifacts/`. `push-packages.bat` builds, packs, and pushes to the
MIDCON sleet feed (`https://midconsulting.de/feed/`) in one step.

---

## License

MIT — see [LICENSE](LICENSE).

**Author:** MidConsulting
**Company:** MidConsulting
