Запись: тестовые workspace test-* не публикуются; stopService Jibri с таймаутом 60 с

This commit is contained in:
crm-calls agent
2026-10-15 07:14:17 +00:00
parent 78f91952e8
commit 65427235b2
4 changed files with 33 additions and 1 deletions

View File

@@ -243,6 +243,25 @@ public sealed class ProcessorTests : IDisposable
Assert.False(Directory.Exists(dir));
}
[Fact]
public async Task TestWorkspace_NotPublished_FilesDeleted()
{
var c = _calls.Create("ws-t", "test-agent-a");
_calls.RecordingStarted(c.Id, c.Id);
_time.Advance(TimeSpan.FromMinutes(5));
_calls.Seen(c.Id, []);
_calls.Ended(c.Id, _calls.Now, true);
var dir = Path.Combine(_root, "rec", c.Id);
Directory.CreateDirectory(dir);
File.WriteAllText(Path.Combine(dir, "meta.json"), "{\"audio\":\"audio.mp3\",\"mime\":\"audio/mpeg\",\"duration\":300,\"bytes\":1,\"parts\":[]}");
File.WriteAllText(Path.Combine(dir, "ready"), "");
var http = Http();
await Proc(http, Opt()).RunOnceAsync(default);
Assert.Equal("skipped", _calls.Get(c.Id)!.Status);
Assert.False(Directory.Exists(dir));
Assert.Empty(http.Log);
}
[Fact]
public async Task ShortCall_Skipped_NoPage_FilesDeleted()
{

View File

@@ -20,6 +20,7 @@ builder.Services.AddSingleton<CrmSession>();
builder.Services.AddSingleton<AudioStorage>();
builder.Services.AddSingleton<WikiPublisher>();
builder.Services.AddHttpClient("jitsi", c => c.Timeout = TimeSpan.FromSeconds(5));
builder.Services.AddHttpClient("jibri-stop", c => c.Timeout = TimeSpan.FromSeconds(60));
builder.Services.AddHttpClient("openai", c => c.Timeout = TimeSpan.FromMinutes(10));
builder.Services.AddHttpClient("storage", c => c.Timeout = TimeSpan.FromMinutes(5));
builder.Services.AddHttpClient("wiki", c => c.Timeout = TimeSpan.FromSeconds(30));

View File

@@ -77,7 +77,10 @@ public sealed class JibriClient(IHttpClientFactory http, RecordingOptions opt)
{
try
{
using var r = await http.CreateClient("jitsi").PostAsync($"{opt.JibriUrl}/jibri/api/v1.0/stopService", null, ct);
// stopService ждёт, пока Jibri закроет ffmpeg и Chrome — это дольше обычного таймаута клиента.
using var cts = CancellationTokenSource.CreateLinkedTokenSource(ct);
cts.CancelAfter(TimeSpan.FromSeconds(60));
using var r = await http.CreateClient("jibri-stop").PostAsync($"{opt.JibriUrl}/jibri/api/v1.0/stopService", null, cts.Token);
return r.IsSuccessStatusCode;
}
catch (Exception e) when (e is HttpRequestException or TaskCanceledException) { return false; }

View File

@@ -82,6 +82,15 @@ public sealed class RecordingProcessor(
return;
}
// Тестовые комнаты test-* (служебный /api/admin/test-link) — только проверка записи: наружу не публикуем.
if (call.WorkspaceId.StartsWith("test-", StringComparison.Ordinal))
{
DeleteDir(dir);
calls.SetStatus(call.Id, "skipped", "тестовий воркспейс: запис перевірено, не публікується");
log.LogInformation("Дзвінок {C}: тестовий воркспейс {W} — не публікується, файли видалено", call.Id, call.WorkspaceId);
return;
}
// Без ключа OpenAI и пользователя CRM ничего наружу не отправляем: запись ждёт на диске.
if (!opt.HasOpenAi || !opt.HasCrmUser || opt.SupabaseUrl.Length == 0)
{