Custom Database Provider
Altruist ships with PostgreSQL support. If you need a different database (MySQL, MongoDB, SQLite, etc.), implement IGeneralDatabaseProvider.
Implement the Provider
[Service(typeof(IGeneralDatabaseProvider))]
public class MyDbProvider : IGeneralDatabaseProvider
{
public string ServiceName => "MyDB";
public bool IsConnected { get; private set; }
public event Action? OnConnected;
public event Action<Exception>? OnFailed;
public event Action<Exception>? OnRetryExhausted;
public async Task ConnectAsync(int maxRetries = 30, int delayMilliseconds = 2000)
{
// Your connection logic — Altruist calls this at startup
// Retry loop, then call RaiseConnectedEvent() on success
IsConnected = true;
RaiseConnectedEvent();
}
public async Task CreateTableAsync<TVaultModel>(IKeyspace? keyspace = null)
where TVaultModel : class, IVaultModel
{
// Create table for the vault model
}
public async Task CreateTableAsync(Type entityType, IKeyspace? keyspace = null)
{
// Create table by type
}
public async Task CreateKeySpaceAsync(string keyspace, ReplicationOptions? options = null)
{
// Create schema/keyspace
}
public async Task ChangeKeyspaceAsync(string keyspace)
{
// Switch active schema
}
public void RaiseConnectedEvent() => OnConnected?.Invoke();
public void RaiseFailedEvent(Exception ex) => OnFailed?.Invoke(ex);
public void RaiseOnRetryExhaustedEvent(Exception ex) => OnRetryExhausted?.Invoke(ex);
}
Because IGeneralDatabaseProvider extends IConnectable, Altruist automatically monitors your provider's health during startup.
Create a Keyspace
public class MyKeyspace : IKeyspace
{
public string Name { get; set; } = "myapp";
}
Custom Vault (Optional)
If your database needs custom query behavior, implement IVault<T>:
public class MyVault<T> : IVault<T> where T : class, IVaultModel
{
// Implement Where, OrderBy, Save, SaveBatchAsync, Delete, etc.
}
And register a custom service factory so IVault<T> resolves to your implementation:
[ConditionalOnConfig("altruist:persistence:database:provider", havingValue: "mydb")]
public class MyDbServiceFactory : IServiceFactory
{
public bool CanCreate(Type serviceType)
{
if (!serviceType.IsGenericType) return false;
return serviceType.GetGenericTypeDefinition() == typeof(IVault<>);
}
public object Create(IServiceProvider sp, Type serviceType)
{
var modelType = serviceType.GetGenericArguments()[0];
var vaultType = typeof(MyVault<>).MakeGenericType(modelType);
return ActivatorUtilities.CreateInstance(sp, vaultType);
}
}
Using Your Provider
Once registered, IVault<T> injection works automatically:
[Service]
public class MyService
{
private readonly IVault<PlayerVault> _players;
public MyService(IVault<PlayerVault> players)
{
_players = players;
}
}
Note:
The framework resolves which provider to use based on your config.yml. Set provider: mydb and your factory handles the rest.