Connector Implementation
Minimum implementation
using Ratatosk;
using Microsoft.Extensions.Logging;
[ChannelSchema(typeof(MySchemaFactory))]
public class MyConnector : ChannelConnectorBase
{
private HttpClient _httpClient;
public MyConnector(
IChannelSchema schema,
ConnectionSettings? settings = null,
ILogger? logger = null,
IAuthenticationManager? authManager = null)
: base(schema, settings, logger, authManager) { }
// ── 1. Initialize ─────────────────────────────────────────
// Validate settings, create provider client, authenticate.
// Called by InitializeAsync().
protected override ValueTask InitializeConnectorAsync(CancellationToken ct)
{
var apiKey = ConnectionSettings.GetParameter("ApiKey");
if (string.IsNullOrEmpty(apiKey))
throw new InvalidOperationException("ApiKey is required");
_httpClient = new HttpClient();
_httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {apiKey}");
SetState(ConnectorState.Ready);
return ValueTask.CompletedTask;
}
// ── 2. Test connection ────────────────────────────────────
// Lightweight ping to verify the provider is reachable.
// Called by TestConnectionAsync().
protected override ValueTask TestConnectorConnectionAsync(CancellationToken ct)
{
// Throw on failure — base class wraps the exception
return ValueTask.CompletedTask;
}
// ── 3. Send message ──────────────────────────────────────
// Translate IMessage to the provider API and send.
// Called by SendMessageAsync().
protected override async Task<SendResult> SendMessageCoreAsync(
IMessage message, CancellationToken ct)
{
var payload = new
{
to = message.Receiver?.Address,
from = message.Sender?.Address,
text = (message.Content as TextContent)?.Text
};
var response = await _httpClient.PostAsJsonAsync("/api/send", payload, ct);
response.EnsureSuccessStatusCode();
var result = await response.Content.ReadFromJsonAsync<ApiResponse>(ct);
return new SendResult
{
MessageId = message.Id,
RemoteMessageId = result!.Id,
Status = MessageStatus.Sent,
Timestamp = DateTimeOffset.UtcNow
};
}
// ── 4. Get status ────────────────────────────────────────
// Return the current connector status.
// Called by GetStatusAsync().
protected override async Task<StatusInfo> GetConnectorStatusAsync(
CancellationToken ct)
{
try
{
var response = await _httpClient.GetAsync("/api/health", ct);
return new StatusInfo(
response.IsSuccessStatusCode ? "connected" : "degraded",
null,
DateTimeOffset.UtcNow);
}
catch
{
return new StatusInfo("disconnected", "Provider unreachable",
DateTimeOffset.UtcNow);
}
}
}What the base class does
Concern
Provided by base class
How wrapping works
Retry policy
Optional overrides
State management
Authentication integration
When auto-authentication fails
Schema auth configuration
Error handling
Error conventions
Logging
DI registration
The factory pattern
Full example: complete connector
Last updated