feat(phase-16): anonymous play & share telemetry substrate (wave 16.1)
Player-service play-session tracker (floor + 3-bucket classify), SharePopover share tracker with debounce, sendBeacon interop, proxied rate-limited POST api/event/{play,share}, append-only event logs + incremental play_counter with server-side release resolution. Migration authored, not applied. No anonId, no read surface.
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
using DeepDrftModels.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace DeepDrftData.Data.Configurations;
|
||||
|
||||
/// <summary>
|
||||
/// EF configuration for the append-only <c>play_event</c> log (Phase 16 §4.2). Plain entity, not a
|
||||
/// <c>BaseEntity</c> — no soft-delete or updated_at, just an immutable fact with a created_at stamp.
|
||||
/// Indexed on track key, release id, and anon id (the last reserved for the wave-16.3 distinct-listener
|
||||
/// query) so the aggregation paths stay cheap as the log grows.
|
||||
/// </summary>
|
||||
public class PlayEventConfiguration : IEntityTypeConfiguration<PlayEvent>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<PlayEvent> builder)
|
||||
{
|
||||
builder.ToTable("play_event");
|
||||
|
||||
builder.HasKey(e => e.Id);
|
||||
builder.Property(e => e.Id).HasColumnName("id");
|
||||
|
||||
builder.Property(e => e.TrackEntryKey)
|
||||
.IsRequired()
|
||||
.HasMaxLength(100)
|
||||
.HasColumnName("track_entry_key");
|
||||
|
||||
builder.Property(e => e.ReleaseId)
|
||||
.HasColumnName("release_id");
|
||||
|
||||
builder.Property(e => e.Bucket)
|
||||
.IsRequired()
|
||||
.HasConversion<string>() // Store the readable bucket name, mirroring ReleaseMedium.
|
||||
.HasMaxLength(20)
|
||||
.HasColumnName("bucket");
|
||||
|
||||
// Reserved nullable token (wave 16.3). Same width as a stringified GUID.
|
||||
builder.Property(e => e.AnonId)
|
||||
.HasMaxLength(64)
|
||||
.HasColumnName("anon_id");
|
||||
|
||||
builder.Property(e => e.CreatedAt)
|
||||
.IsRequired()
|
||||
.HasColumnName("created_at");
|
||||
|
||||
builder.HasIndex(e => e.TrackEntryKey).HasDatabaseName("IX_play_event_track_entry_key");
|
||||
builder.HasIndex(e => e.ReleaseId).HasDatabaseName("IX_play_event_release_id");
|
||||
builder.HasIndex(e => e.AnonId).HasDatabaseName("IX_play_event_anon_id");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user