🧱 Creating a Resilient Service

Here’s a complete, minimal but meaningful example of how to write a custom ResilientService that implements IConnectable, simulating connection behavior and integrating with Altruist’s resilient service lifecycle.

using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Altruist;

public class DummyResilientService : IConnectable
{
    private bool _connected;
    private int _connectionAttempts;

    public string ServiceName => "DummyResilientService";

    public bool IsConnected => _connected;

    public event Action? OnConnected;
    public event Action<Exception>? OnFailed;
    public event Action<Exception>? OnRetryExhausted;

    // accept connection info, configuration etc here, in the constructor
    public DummyResilientService()
    {

    }

    // retrying for 1 minute max
    public async Task ConnectAsync(int maxRetries = 30, int delayMilliseconds = 2000)
    {
        _connected = false;
        _connectionAttempts = 0;

        while (!_connected && _connectionAttempts < maxRetries)
        {
            _connectionAttempts++;
            try
            {
                // Simulate work — this is where real connection logic would be
                await Task.Delay(500);

                // Simulate random success/failure (for demo)
                if (_connectionAttempts >= 3)
                {
                    _connected = true;
                    RaiseConnectedEvent();
                    return;
                }

                throw new Exception("Simulated connection failure");
            }
            catch (Exception ex)
            {
                RaiseFailedEvent(ex);
            }
        }

        if (!_connected)
        {
            // Irreversible error, Altruist will shutdown the server.
            RaiseOnRetryExhaustedEvent(new Exception("Max retries reached."));
        }
    }

    // we implement these for now, in the future Altruist will provide a default implementation
    public void RaiseConnectedEvent()
    {
        OnConnected?.Invoke();
    }

    public void RaiseFailedEvent(Exception ex)
    {
        OnFailed?.Invoke(ex);
    }

    public void RaiseOnRetryExhaustedEvent(Exception ex)
    {
        OnRetryExhausted?.Invoke(ex);
    }
}

🧩 Registering in DI

In your app's Program.cs or Startup.cs, you can wire this up like so:

builder.Services.AddSingleton<IConnectable, DummyResilientService>();

Note:

This is what makes it truly resilient by letting Altruist auto-discover and monitor the service during startup, handling connection lifecycle for you.

🧪 What Happens

  • During app startup, Altruist calls ConnectAsync().
  • The service simulates connection attempts.
  • After 3 failed attempts, it connects successfully and raises OnConnected.
  • If it never connects, it raises OnRetryExhausted and the app shuts down gracefully (per Altruist's default ServerStatus logic).

💡 Use Cases

This structure makes it easy to create services for:

  • External databases or caches
  • Game-specific third-party APIs
  • Gateways or message brokers (e.g., Kafka, NATS)
  • Monitoring or analytics services
  • Or just dummy services used for local dev/testing