fix(telegram): break the DI cycle through CalendarScriptEnvironment
ChatRegistry -> JobScheduler -> IScriptEnvironment -> ChatRegistry made the host fail at startup. CalendarScriptEnvironment now takes TelegramOptions and computes the workspace with the new static ChatRegistry.WorkspaceFor(options, chatId).
This commit is contained in:
@@ -82,7 +82,11 @@ public sealed class ChatRegistry(
|
||||
|
||||
public static string ScopeFor(long chatId) => $"telegram-{chatId}";
|
||||
|
||||
public string WorkspaceFor(long chatId) => Path.Combine(options.WorkspaceRoot, chatId.ToString(System.Globalization.CultureInfo.InvariantCulture));
|
||||
public string WorkspaceFor(long chatId) => WorkspaceFor(options, chatId);
|
||||
|
||||
/// <summary><c><WorkspaceRoot>/<chatId></c>, for services that can't depend on the registry (it would close a DI cycle).</summary>
|
||||
public static string WorkspaceFor(TelegramOptions options, long chatId) =>
|
||||
Path.Combine(options.WorkspaceRoot, chatId.ToString(System.Globalization.CultureInfo.InvariantCulture));
|
||||
|
||||
/// <summary>The chat's context if it was already created, without creating it.</summary>
|
||||
public ChatContext? Find(long chatId) =>
|
||||
|
||||
@@ -9,8 +9,10 @@ namespace Volcanic.AgenticCore.Telegram.Scheduling;
|
||||
/// Gives a chat's watcher scripts <c>GOOGLE_ACCESS_TOKEN</c>: an access token for that chat's calendar, valid for the
|
||||
/// run's timeout plus a minute (as far as Google's one-hour lifetime allows). The bot refreshes it; the refresh token
|
||||
/// and the client secret never reach the script. A chat without a connected calendar gets nothing.
|
||||
/// Takes <see cref="TelegramOptions"/>, not <see cref="ChatRegistry"/>: the registry depends on the scheduler, which
|
||||
/// depends on this.
|
||||
/// </summary>
|
||||
public sealed class CalendarScriptEnvironment(ChatRegistry chats, GoogleCalendarOptions calendar) : IScriptEnvironment
|
||||
public sealed class CalendarScriptEnvironment(TelegramOptions options, GoogleCalendarOptions calendar) : IScriptEnvironment
|
||||
{
|
||||
public const string AccessTokenVariable = "GOOGLE_ACCESS_TOKEN";
|
||||
private static readonly TimeSpan Margin = TimeSpan.FromMinutes(1);
|
||||
@@ -20,7 +22,7 @@ public sealed class CalendarScriptEnvironment(ChatRegistry chats, GoogleCalendar
|
||||
{
|
||||
if (!long.TryParse(target, NumberStyles.AllowLeadingSign, CultureInfo.InvariantCulture, out var chatId)) return None;
|
||||
var token = await (calendar.Connections ?? GoogleCalendarConnections.Shared)
|
||||
.TryGetAccessTokenAsync(calendar, ChatRegistry.ScopeFor(chatId), chats.WorkspaceFor(chatId), timeout + Margin, cancellationToken)
|
||||
.TryGetAccessTokenAsync(calendar, ChatRegistry.ScopeFor(chatId), ChatRegistry.WorkspaceFor(options, chatId), timeout + Margin, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
return token is null ? None : new Dictionary<string, string> { [AccessTokenVariable] = token };
|
||||
}
|
||||
|
||||
@@ -166,7 +166,7 @@ public class GoogleCalendarHostTests : IDisposable
|
||||
{
|
||||
var calendar = Calendar();
|
||||
await using var host = new ChatHost(calendar: calendar);
|
||||
var environment = new Volcanic.AgenticCore.Telegram.Scheduling.CalendarScriptEnvironment(host.Chats, calendar);
|
||||
var environment = new Volcanic.AgenticCore.Telegram.Scheduling.CalendarScriptEnvironment(host.Options, calendar);
|
||||
var target = Updates.AllowedUser.ToString(System.Globalization.CultureInfo.InvariantCulture);
|
||||
Assert.Empty(await environment.ForRunAsync(target, TimeSpan.FromMinutes(5), CancellationToken.None)); // not connected yet
|
||||
|
||||
|
||||
Reference in New Issue
Block a user