From e37a8beaa77eb4a84249a749ce9fde719c55b4bc Mon Sep 17 00:00:00 2001 From: Lukasz Raczylo Date: Tue, 18 Nov 2025 16:37:18 +0000 Subject: [PATCH] Fix: Move endpoint routing outside loop to prevent mutation misrouting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BUG FIX: The endpoint routing logic was inside the loop that processes all GraphQL definitions. This caused mutations to be incorrectly routed to read-only endpoints when followed by other definitions (queries, fragments, etc). The bug manifested as: mutations → read-only Hasura → read-only pooler → PostgreSQL replica → "cannot set transaction read-write mode during recovery" Changes: - Move endpoint routing logic AFTER the definition processing loop - Ensures mutations are ALWAYS routed to write endpoint regardless of subsequent definitions in the document - Add 3 comprehensive regression tests covering: 1. Mutation with multiple operations 2. Mutation followed by fragment 3. Complex main-bot style mutation document Tests: All pass including new regression tests Impact: Fixes database write failures in main-bot and other services --- proxy_test.go | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/proxy_test.go b/proxy_test.go index 6231e71..20aa6f2 100644 --- a/proxy_test.go +++ b/proxy_test.go @@ -82,6 +82,36 @@ func (suite *Tests) Test_proxyTheRequest() { wantErr: false, wantEndpoint: "https://telegram-bot.app/", }, + { + name: "Test mutation with multiple operations (bug fix regression test)", + body: `{"query":"mutation getOrCreateUser { insert_tg_users_one(object: {id: 123}) { id } } query otherQuery { users { id } }"}`, + host: "https://telegram-bot.app/", + hostRO: "https://google.com/", + path: "/v1/graphql", + headers: supplied_headers, + wantErr: false, + wantEndpoint: "https://telegram-bot.app/", + }, + { + name: "Test mutation followed by fragment (bug fix regression test)", + body: `{"query":"mutation insertUser { insert_users_one(object: {name: \"test\"}) { ...userFields } } fragment userFields on users { id name }"}`, + host: "https://telegram-bot.app/", + hostRO: "https://google.com/", + path: "/v1/graphql", + headers: supplied_headers, + wantErr: false, + wantEndpoint: "https://telegram-bot.app/", + }, + { + name: "Test complex mutation document (main-bot style)", + body: `{"query":"mutation getOrCreateUser($user_id: bigint!, $group_id: bigint!) { insert_tg_users_one(object: {id: $user_id}, on_conflict: {constraint: tg_users_pkey, update_columns: last_seen}) { id } insert_tg_groups_one(object: {id: $group_id}, on_conflict: {constraint: tg_groups_pkey, update_columns: last_seen}) { id } }"}`, + host: "https://telegram-bot.app/", + hostRO: "https://google.com/", + path: "/v1/graphql", + headers: supplied_headers, + wantErr: false, + wantEndpoint: "https://telegram-bot.app/", + }, } for _, tt := range tests {