using DeepDrftData.Repositories; using DeepDrftModels.Enums; using Microsoft.Extensions.Logging; using NetBlocks.Models; namespace DeepDrftData; /// /// implementation over . The layer boundary /// matches the rest of DeepDrftData: the repository owns the EF constructs and the write transaction; /// this service catches at the boundary and returns a NetBlocks . Telemetry is /// best-effort by design (§2.2) — a failed write is logged and surfaced as a fail result, never thrown /// at the caller, so a telemetry hiccup can never reach a listener. /// public class EventManager : IEventService { private readonly EventRepository _repository; private readonly ILogger _logger; public EventManager(EventRepository repository, ILogger logger) { _repository = repository; _logger = logger; } public async Task RecordPlay( string trackEntryKey, PlayBucket bucket, string? anonId = null, CancellationToken cancellationToken = default) { try { await _repository.RecordPlayAsync(trackEntryKey, bucket, anonId, cancellationToken); return Result.CreatePassResult(); } catch (Exception e) { _logger.LogError(e, "Failed to record play event for track {TrackEntryKey}", trackEntryKey); return Result.CreateFailResult(e.Message); } } public async Task RecordShare( ShareTargetType targetType, string targetKey, ShareChannel channel, string? anonId = null, CancellationToken cancellationToken = default) { try { await _repository.RecordShareAsync(targetType, targetKey, channel, anonId, cancellationToken); return Result.CreatePassResult(); } catch (Exception e) { _logger.LogError(e, "Failed to record share event for {TargetType} {TargetKey}", targetType, targetKey); return Result.CreateFailResult(e.Message); } } public async Task> GetDistinctListenerCount(CancellationToken cancellationToken = default) { try { var count = await _repository.CountDistinctListenersAsync(cancellationToken); return ResultContainer.CreatePassResult(count); } catch (Exception e) { _logger.LogError(e, "Failed to count distinct listeners"); return ResultContainer.CreateFailResult(e.Message); } } public async Task> GetDistinctListenerCountForTrack( string trackEntryKey, CancellationToken cancellationToken = default) { try { var count = await _repository.CountDistinctListenersForTrackAsync(trackEntryKey, cancellationToken); return ResultContainer.CreatePassResult(count); } catch (Exception e) { _logger.LogError(e, "Failed to count distinct listeners for track {TrackEntryKey}", trackEntryKey); return ResultContainer.CreateFailResult(e.Message); } } public async Task> GetDistinctListenerCountForRelease( long releaseId, CancellationToken cancellationToken = default) { try { var count = await _repository.CountDistinctListenersForReleaseAsync(releaseId, cancellationToken); return ResultContainer.CreatePassResult(count); } catch (Exception e) { _logger.LogError(e, "Failed to count distinct listeners for release {ReleaseId}", releaseId); return ResultContainer.CreateFailResult(e.Message); } } }