Reduce hot run polling pressure
This commit is contained in:
@@ -14,12 +14,16 @@ import (
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
)
|
||||
|
||||
const mysqlSnapshotID = "current"
|
||||
const (
|
||||
mysqlSnapshotID = "current"
|
||||
mysqlRuntimeSnapshotID = "runtime"
|
||||
)
|
||||
|
||||
type MySQLStore struct {
|
||||
*MemoryStore
|
||||
db *sql.DB
|
||||
persistMu sync.Mutex
|
||||
db *sql.DB
|
||||
persistMu sync.Mutex
|
||||
runtimePersistMu sync.Mutex
|
||||
}
|
||||
|
||||
func NewMySQLStore(dsn string) (*MySQLStore, error) {
|
||||
@@ -59,7 +63,7 @@ func (store *MySQLStore) AuthSessions() AuthSessionRepository {
|
||||
}
|
||||
|
||||
func (store *MySQLStore) RunControlSessions() RunControlSessionRepository {
|
||||
return &persistentRepository[domain.RunControlSession, struct{}]{repository: store.MemoryStore.runSessions, persist: store.persist}
|
||||
return &persistentRepository[domain.RunControlSession, struct{}]{repository: store.MemoryStore.runSessions, persist: store.persistRuntime}
|
||||
}
|
||||
|
||||
func (store *MySQLStore) AIProviders() AIProviderRepository {
|
||||
@@ -75,7 +79,7 @@ func (store *MySQLStore) ServerInstances() ServerInstanceRepository {
|
||||
}
|
||||
|
||||
func (store *MySQLStore) RunEndpoints() RunEndpointRepository {
|
||||
return &persistentRepository[domain.RunEndpoint, domain.RunEndpointFilter]{repository: store.MemoryStore.runEndpoints, persist: store.persist}
|
||||
return &persistentRepository[domain.RunEndpoint, domain.RunEndpointFilter]{repository: store.MemoryStore.runEndpoints, persist: store.persistRuntime}
|
||||
}
|
||||
|
||||
func (store *MySQLStore) Jobs() JobRepository {
|
||||
@@ -171,7 +175,7 @@ func (store *MySQLStore) load() error {
|
||||
err := store.db.QueryRowContext(ctx, "SELECT snapshot_json FROM platform_metadata_snapshots WHERE id = ?", mysqlSnapshotID).Scan(&payload)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
return nil
|
||||
return store.loadRuntime()
|
||||
}
|
||||
return fmt.Errorf("read mysql metadata snapshot: %w", err)
|
||||
}
|
||||
@@ -180,6 +184,25 @@ func (store *MySQLStore) load() error {
|
||||
return fmt.Errorf("decode mysql metadata snapshot: %w", err)
|
||||
}
|
||||
store.loadSnapshot(snapshot)
|
||||
return store.loadRuntime()
|
||||
}
|
||||
|
||||
func (store *MySQLStore) loadRuntime() error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
var payload []byte
|
||||
err := store.db.QueryRowContext(ctx, "SELECT snapshot_json FROM platform_metadata_snapshots WHERE id = ?", mysqlRuntimeSnapshotID).Scan(&payload)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("read mysql runtime metadata snapshot: %w", err)
|
||||
}
|
||||
var snapshot runtimeSnapshot
|
||||
if err := json.Unmarshal(payload, &snapshot); err != nil {
|
||||
return fmt.Errorf("decode mysql runtime metadata snapshot: %w", err)
|
||||
}
|
||||
store.loadRuntimeSnapshot(snapshot)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -204,6 +227,27 @@ ON DUPLICATE KEY UPDATE snapshot_json = ?, updated_at = CURRENT_TIMESTAMP`, mysq
|
||||
return nil
|
||||
}
|
||||
|
||||
func (store *MySQLStore) persistRuntime() error {
|
||||
store.runtimePersistMu.Lock()
|
||||
defer store.runtimePersistMu.Unlock()
|
||||
|
||||
snapshot := store.runtimeSnapshot()
|
||||
payload, err := json.Marshal(snapshot)
|
||||
if err != nil {
|
||||
return fmt.Errorf("encode mysql runtime metadata snapshot: %w", err)
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
_, err = store.db.ExecContext(ctx, `
|
||||
INSERT INTO platform_metadata_snapshots (id, snapshot_json)
|
||||
VALUES (?, ?)
|
||||
ON DUPLICATE KEY UPDATE snapshot_json = ?, updated_at = CURRENT_TIMESTAMP`, mysqlRuntimeSnapshotID, string(payload), string(payload))
|
||||
if err != nil {
|
||||
return fmt.Errorf("write mysql runtime metadata snapshot: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (store *MySQLStore) snapshot() StoreSnapshot {
|
||||
return StoreSnapshot{
|
||||
Users: snapshotRepository(store.MemoryStore.users),
|
||||
@@ -232,6 +276,13 @@ func (store *MySQLStore) snapshot() StoreSnapshot {
|
||||
}
|
||||
}
|
||||
|
||||
func (store *MySQLStore) runtimeSnapshot() runtimeSnapshot {
|
||||
return runtimeSnapshot{
|
||||
RunControlSessions: snapshotRepository(store.MemoryStore.runSessions),
|
||||
RunEndpoints: snapshotRepository(store.MemoryStore.runEndpoints),
|
||||
}
|
||||
}
|
||||
|
||||
func (store *MySQLStore) loadSnapshot(snapshot StoreSnapshot) {
|
||||
loadRepository(store.MemoryStore.users, snapshot.Users)
|
||||
loadRepository(store.MemoryStore.authSessions, snapshot.AuthSessions)
|
||||
@@ -257,3 +308,8 @@ func (store *MySQLStore) loadSnapshot(snapshot StoreSnapshot) {
|
||||
loadRepository(store.MemoryStore.bridgeStreams, snapshot.GameClientBridgeStreams)
|
||||
loadRepository(store.MemoryStore.pluginDataRecords, snapshot.PluginDataRecords)
|
||||
}
|
||||
|
||||
func (store *MySQLStore) loadRuntimeSnapshot(snapshot runtimeSnapshot) {
|
||||
loadRepository(store.MemoryStore.runSessions, snapshot.RunControlSessions)
|
||||
loadRepository(store.MemoryStore.runEndpoints, snapshot.RunEndpoints)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user