Migration 022 adds agent_hosts / game_instances / instance_clusters / instance_stats (named agent_hosts to avoid the existing B2B hosts table). HostAgentConsumerService now parses the full v2 heartbeat and upserts an agent_hosts row (host metrics: cpu/mem/disk/agent version, keyed by license_id+hostname until enrollment) plus one game_instances row per heartbeat instance entry (state + uptime, the billing unit). Legacy server_connections write retained so the current panel keeps working — additive migration, nothing breaks. Staleness sweep + offline beacon now flip agent_hosts too. cluster_id FK reserved for Soulmask/ Dune. Migration applied to live DB; tsc green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
75 lines
2.0 KiB
TypeScript
75 lines
2.0 KiB
TypeScript
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, JoinColumn, Check, Unique } from 'typeorm';
|
|
import { License } from './license.entity';
|
|
|
|
export interface AgentHostDisk {
|
|
mount: string;
|
|
total_mb: number;
|
|
free_mb: number;
|
|
}
|
|
|
|
/**
|
|
* One Corrosion host agent / one machine. Owns the machine-level facts.
|
|
*
|
|
* NOTE: distinct from the B2B `hosts` table (hosting-partner companies). This
|
|
* is `agent_hosts` — the physical/virtual box a customer runs the agent on.
|
|
*/
|
|
@Entity('agent_hosts')
|
|
@Unique(['license_id', 'hostname'])
|
|
@Check(`"status" IN ('connected', 'degraded', 'offline')`)
|
|
export class AgentHost {
|
|
@PrimaryGeneratedColumn('uuid')
|
|
id: string;
|
|
|
|
@Column({ type: 'uuid' })
|
|
license_id: string;
|
|
|
|
@Column({ type: 'varchar', length: 255, default: '' })
|
|
hostname: string;
|
|
|
|
@Column({ type: 'varchar', length: 64, nullable: true })
|
|
agent_version: string | null;
|
|
|
|
@Column({ type: 'varchar', length: 64, nullable: true })
|
|
agent_commit: string | null;
|
|
|
|
@Column({ type: 'varchar', length: 32, nullable: true })
|
|
os: string | null;
|
|
|
|
@Column({ type: 'varchar', length: 32, nullable: true })
|
|
arch: string | null;
|
|
|
|
@Column({ type: 'varchar', length: 20, default: 'offline' })
|
|
status: string;
|
|
|
|
@Column({ type: 'timestamptz', nullable: true })
|
|
last_heartbeat_at: Date | null;
|
|
|
|
@Column({ type: 'double precision', nullable: true })
|
|
cpu_percent: number | null;
|
|
|
|
@Column({ type: 'integer', nullable: true })
|
|
cpu_cores: number | null;
|
|
|
|
@Column({ type: 'bigint', nullable: true })
|
|
mem_total_mb: number | null;
|
|
|
|
@Column({ type: 'bigint', nullable: true })
|
|
mem_used_mb: number | null;
|
|
|
|
@Column({ type: 'bigint', nullable: true })
|
|
uptime_seconds: number | null;
|
|
|
|
@Column({ type: 'jsonb', nullable: true })
|
|
disks: AgentHostDisk[] | null;
|
|
|
|
@Column({ type: 'timestamptz', default: () => 'NOW()' })
|
|
created_at: Date;
|
|
|
|
@Column({ type: 'timestamptz', default: () => 'NOW()' })
|
|
updated_at: Date;
|
|
|
|
@ManyToOne(() => License, { onDelete: 'CASCADE' })
|
|
@JoinColumn({ name: 'license_id' })
|
|
license: License;
|
|
}
|