fix: TimescaleDB hypertable 오류 수정 - fast_record 테이블의 복합 키 설정

This commit is contained in:
windpacer
2026-04-29 18:46:54 +09:00
parent 38c0d3c888
commit c0f32177bf
2 changed files with 35 additions and 5 deletions

View File

@@ -1,4 +1,5 @@
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;
namespace ExperionCrawler.Core.Domain.Entities;
@@ -7,6 +8,7 @@ public class ExperionTag
{
public int Id { get; set; }
public string NodeId { get; set; } = string.Empty;
public string TagName { get; set; } = string.Empty;
public string DisplayName { get; set; } = string.Empty;
public string? Value { get; set; }
public string? DataType { get; set; }
@@ -94,3 +96,32 @@ public class ExperionStatusCodeInfo
public ulong Decimal { get; set; }
public string Description { get; set; } = string.Empty;
}
/// <summary>fastSession — 데이터 수집 세션 메타</summary>
[Table("fast_session")]
public class FastSession
{
[Column("id")] public int Id { get; set; }
[Column("name")] public string Name { get; set; } = string.Empty;
[Column("started_at")] public DateTime StartedAt { get; set; }
[Column("ended_at")] public DateTime? EndedAt { get; set; }
[Column("status")] public string Status { get; set; } = "Pending";
// Status 허용값: Pending / Running / Completed / Cancelled / Failed / RowLimitReached
[Column("sampling_ms")] public int SamplingMs { get; set; }
[Column("duration_sec")] public int DurationSec { get; set; }
[Column("tag_list")] public string TagList { get; set; } = "[]"; // JSONB → string[] 직렬화
[Column("row_count")] public int RowCount { get; set; }
[Column("retention_days")] public int? RetentionDays { get; set; } // null = 무한 보관
[Column("pinned")] public bool Pinned { get; set; }
}
/// <summary>fastRecord — 시계열 데이터 (Long 포맷: 태그 1행/시점)</summary>
[Table("fast_record")]
public class FastRecord
{
[NotMapped] public int Id { get; set; }
[Column("session_id")] public int SessionId { get; set; }
[Column("recorded_at")] public DateTime RecordedAt { get; set; }
[Column("tagname")] public string TagName { get; set; } = string.Empty;
[Column("value")] public string? Value { get; set; }
}

View File

@@ -68,9 +68,8 @@ public class ExperionDbContext : DbContext
modelBuilder.Entity<FastRecord>(e =>
{
e.HasKey(x => x.Id);
e.HasKey(x => new { x.SessionId, x.RecordedAt, x.TagName });
e.HasIndex(x => x.SessionId);
e.HasIndex(x => new { x.SessionId, x.TagName, x.RecordedAt });
});
}
}
@@ -113,17 +112,17 @@ public class ExperionDbService : IExperionDbService
await _ctx.Database.ExecuteSqlRawAsync("""
CREATE TABLE IF NOT EXISTS fast_record (
id SERIAL PRIMARY KEY,
session_id INTEGER NOT NULL REFERENCES fast_session(id) ON DELETE CASCADE,
recorded_at TIMESTAMPTZ NOT NULL,
tagname TEXT NOT NULL,
value TEXT
value TEXT,
PRIMARY KEY (session_id, recorded_at, tagname)
)
""");
// TimescaleDB hypertable 생성 (recorded_at 기준, chunk_interval = 1 day)
await _ctx.Database.ExecuteSqlRawAsync("""
SELECT create_hypertable('fast_record', 'recorded_at', if_not_exists => TRUE)
SELECT create_hypertable('fast_record', 'recorded_at', if_not_exists => TRUE, migrate_data => TRUE)
""");
await _ctx.Database.ExecuteSqlRawAsync("""