From 2f2e7256fb134513490eeefbf7743e8564bba459 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=93=E8=89=AF?= <1204183885@qq.com> Date: Sun, 18 Oct 2026 19:01:55 +0800 Subject: [PATCH] perf(managed-agent): avoid redundant session root materialization (#14557) Keep the exclusive root UPSERT as the single initialization path before creating the Session event stream. Co-authored-by: Qwen-Coder --- .../store/ManagedSessionStore.java | 34 ++----------------- .../store/ManagedSessionGuardConvoyIT.java | 16 ++++----- 2 files changed, 8 insertions(+), 42 deletions(-) diff --git a/packages/managed-agent-server/src/main/java/com/alibaba/qwen/code/managedagent/store/ManagedSessionStore.java b/packages/managed-agent-server/src/main/java/com/alibaba/qwen/code/managedagent/store/ManagedSessionStore.java index dd7c4f2033..0faee08014 100644 --- a/packages/managed-agent-server/src/main/java/com/alibaba/qwen/code/managedagent/store/ManagedSessionStore.java +++ b/packages/managed-agent-server/src/main/java/com/alibaba/qwen/code/managedagent/store/ManagedSessionStore.java @@ -2843,42 +2843,12 @@ public class ManagedSessionStore { return sha256(writerToken.getBytes(StandardCharsets.UTF_8)); } - private boolean insertSessionRoot(String tenantId, String sessionId) { - long now = epochMillis(databaseNow()); - String tenantKey = com.alibaba.qwen.code.runtimebroker.JdbcRuntimeBindingRepository.harnessDrainKey(tenantId); - String sessionKey = com.alibaba.qwen.code.runtimebroker.JdbcRuntimeBindingRepository.harnessDrainKey(sessionId); - int inserted = jdbc.update( - "INSERT IGNORE INTO ma_session (tenant_id, session_id, session_kind, tenant_key," - + " session_key, session_scope_key, gmt_create, gmt_modified) VALUES (?, ?," - + " 'CONTROL', ?, ?, ?, ?, ?)", - tenantId, - sessionId, - tenantKey, - sessionKey, - sessionScopeKey(tenantId, sessionId), - now, - now); - return inserted == 1; - } - private void ensureSessionRoot(String tenantId, String sessionId) { // Take the root row exclusively first: ordinary writers lock it - // without a tenant guard (#13800), and the shared lock INSERT IGNORE - // takes on an existing row would otherwise upgrade behind one of - // them and deadlock; lockSessionRoot materializes the row with its - // keys, so the INSERT IGNORE below never inserts. + // without a tenant guard (#13800); keep that order before + // initializing the session event stream. ToolPublicationRetentionStore.lockSessionRoot(jdbc, tenantId, sessionId); - insertSessionRoot(tenantId, sessionId); - materializeSessionRoot(tenantId, sessionId); - } - - private void materializeSessionRoot(String tenantId, String sessionId) { long now = epochMillis(databaseNow()); - String tenantKey = JdbcRuntimeBindingRepository.harnessDrainKey(tenantId); - String sessionKey = JdbcRuntimeBindingRepository.harnessDrainKey(sessionId); - jdbc.update("UPDATE ma_session SET tenant_key = ?, session_key = ?, session_scope_key = ?" - + " WHERE tenant_id = ? AND session_id = ? AND session_scope_key IS NULL", - tenantKey, sessionKey, sessionScopeKey(tenantId, sessionId), tenantId, sessionId); jdbc.update( "INSERT IGNORE INTO ma_event_stream (tenant_id, session_id, stream_kind, stream_id," + " gmt_modified) VALUES (?, ?, 'SESSION', X'', ?)", diff --git a/packages/managed-agent-server/src/test/java/com/alibaba/qwen/code/managedagent/store/ManagedSessionGuardConvoyIT.java b/packages/managed-agent-server/src/test/java/com/alibaba/qwen/code/managedagent/store/ManagedSessionGuardConvoyIT.java index d503865db3..aff4ac2583 100644 --- a/packages/managed-agent-server/src/test/java/com/alibaba/qwen/code/managedagent/store/ManagedSessionGuardConvoyIT.java +++ b/packages/managed-agent-server/src/test/java/com/alibaba/qwen/code/managedagent/store/ManagedSessionGuardConvoyIT.java @@ -544,19 +544,15 @@ class ManagedSessionGuardConvoyIT { } /** - * Writer acquisition must hold the Session root exclusively before any - * shared lock on it. Since #13800 ordinary writers lock that root - * without a tenant guard, and on MariaDB a shared root lock upgraded - * behind one of their queued exclusive requests is an InnoDB 1213 - * deadlock. The acquisition pauses right after ensureSessionRoot's - * INSERT IGNORE while an ordinary blockRecovery of the same Session - * queues on the root; both must then complete. (MySQL 8.4 lets the - * shared holder upgrade ahead of the queue, so only MariaDB fails - * without the exclusive-first order.) + * Writer acquisition must hold the Session root exclusively before an + * ordinary writer can queue on it. The acquisition pauses after + * the acquisition's first root UPSERT, then an ordinary blockRecovery of the + * same Session queues on the root; releasing the pause must let both + * complete without an InnoDB deadlock. */ @Test void writerAcquisitionHoldsTheSessionRootExclusivelyAgainstOrdinaryWriters() throws Exception { - assertNoDeadlockAgainstOrdinaryWriter("INSERT IGNORE INTO ma_session (", + assertNoDeadlockAgainstOrdinaryWriter("INSERT INTO ma_session (", (store, grant) -> store.acquireWriter(TENANT, "victim", TOKEN, new AcquireWriterRequest(WORKSPACE, "writer-victim", 60_000L))); }