@opengeni/db 0.28.1 → 0.31.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/attached-browser-devices.d.ts +42 -0
- package/dist/attempt-tool-catalogs.d.ts +16 -0
- package/dist/browser-auth.d.ts +91 -0
- package/dist/browser-identities.d.ts +128 -0
- package/dist/browser-sessions.d.ts +272 -0
- package/dist/browser-state-artifacts.d.ts +17 -0
- package/dist/capability-components.d.ts +37 -0
- package/dist/capability-integrations.d.ts +192 -0
- package/dist/chunk-F5FT7BEZ.js +3535 -0
- package/dist/chunk-F5FT7BEZ.js.map +1 -0
- package/dist/chunk-ISI2TIUG.js +639 -0
- package/dist/chunk-ISI2TIUG.js.map +1 -0
- package/dist/chunk-MWDVXQOL.js +11639 -0
- package/dist/chunk-MWDVXQOL.js.map +1 -0
- package/dist/chunk-NBE6CHRI.js +955 -0
- package/dist/chunk-NBE6CHRI.js.map +1 -0
- package/dist/{chunk-DBS5HPEW.js → chunk-YHZXQ7HP.js} +760 -11
- package/dist/chunk-YHZXQ7HP.js.map +1 -0
- package/dist/codemode-operations.d.ts +117 -0
- package/dist/codex-token-resolver.d.ts +2 -2
- package/dist/company-profile-schema.d.ts +798 -0
- package/dist/company-profile.d.ts +268 -0
- package/dist/computer-sessions.d.ts +109 -0
- package/dist/connection-token-resolver.d.ts +9 -4
- package/dist/database.d.ts +52 -3
- package/dist/editable-artifact-durable-export.d.ts +153 -0
- package/dist/editable-artifact-durable-export.js +788 -0
- package/dist/editable-artifact-durable-export.js.map +1 -0
- package/dist/editable-artifact-materialization.d.ts +123 -0
- package/dist/editable-artifacts-schema.d.ts +4152 -0
- package/dist/editable-artifacts.d.ts +610 -0
- package/dist/editable-artifacts.js +26 -0
- package/dist/editable-artifacts.js.map +1 -0
- package/dist/environment-crypto.d.ts +8 -4
- package/dist/generated-images.d.ts +139 -0
- package/dist/index.d.ts +958 -126
- package/dist/index.js +31204 -12172
- package/dist/index.js.map +1 -1
- package/dist/insights.d.ts +51 -4
- package/dist/integration-bindings.d.ts +70 -0
- package/dist/integration-features.d.ts +99 -0
- package/dist/interaction-revisions.d.ts +3 -0
- package/dist/interaction-schema.d.ts +5372 -0
- package/dist/knowledge-source-sync-schema.d.ts +1679 -0
- package/dist/knowledge-source-sync.d.ts +274 -0
- package/dist/lossless-columns.d.ts +58 -0
- package/dist/lossless-json.d.ts +39 -0
- package/dist/memory-domain.d.ts +3 -6
- package/dist/memory-governance.d.ts +2 -2
- package/dist/memory-slack-delivery.d.ts +101 -0
- package/dist/new-session-drafts.d.ts +2 -2
- package/dist/pack-components.d.ts +76 -0
- package/dist/pack-installations.d.ts +86 -0
- package/dist/persistence-errors.d.ts +7 -14
- package/dist/plugin-packages.d.ts +126 -0
- package/dist/preference-registry.d.ts +1 -1
- package/dist/provision-roles.d.ts +9 -1
- package/dist/provision-roles.js +1 -1
- package/dist/runtime-posture.d.ts +18 -6
- package/dist/schema.d.ts +19122 -8731
- package/dist/schema.js +173 -1
- package/dist/scoped-knowledge.d.ts +97 -1
- package/dist/session-control.d.ts +4 -4
- package/dist/session-queue-commands.d.ts +19 -11
- package/dist/session-realtime-context.d.ts +2 -2
- package/dist/session-realtime-ledger.d.ts +4 -4
- package/dist/session-realtime-mirror.d.ts +2 -2
- package/dist/session-realtime-state.d.ts +1 -1
- package/dist/session-realtime-terminal.d.ts +8 -1
- package/dist/session-realtime.d.ts +7 -7
- package/dist/session-tool-call-settlement.d.ts +1 -1
- package/dist/slack-user-link-access.d.ts +54 -0
- package/dist/transcription-recordings-schema.d.ts +44 -6
- package/dist/transcription-recordings.d.ts +3 -3
- package/dist/turn-initiator.d.ts +2 -2
- package/dist/video-generation.d.ts +216 -0
- package/dist/video-generation.js +66 -0
- package/dist/video-generation.js.map +1 -0
- package/dist/workspace-artifacts.d.ts +1 -1
- package/dist/workspace-instruction-policies.d.ts +1 -1
- package/dist/workspace-learning-policy-schema.d.ts +932 -0
- package/dist/workspace-learning-policy.d.ts +161 -0
- package/drizzle/0065_enrollment_credential_generation.sql +10 -0
- package/drizzle/0140_retained_screenshot_artifacts.sql +192 -0
- package/drizzle/0176_lossless_canonical_json.sql +975 -0
- package/drizzle/0177_session_events_workspace_turn_type_index.sql +5 -0
- package/drizzle/0178_permissioned_secret_reads.sql +14 -0
- package/drizzle/0179_slack_private_shortcut_delivery_gate.sql +85 -0
- package/drizzle/0180_retained_screenshot_lifecycle_fences.sql +273 -0
- package/drizzle/0181_connected_machine_removal.sql +52 -0
- package/drizzle/0182_connected_machine_remove_session_default.sql +77 -0
- package/drizzle/0183_model_call_provider_cost_estimates.sql +39 -0
- package/drizzle/0184_sandbox_drain_teardown_fence.sql +682 -0
- package/drizzle/0185_temporal_schedule_cleanup_outbox.sql +168 -0
- package/drizzle/0186_sandbox_capture_provider_contract.sql +400 -0
- package/drizzle/0187_generated_image_artifacts.sql +173 -0
- package/drizzle/0188_image_generation_retention_failure.sql +25 -0
- package/drizzle/0189_retained_session_image_formats.sql +13 -0
- package/drizzle/0190_timeline_annotations.sql +31 -0
- package/drizzle/0191_editable_artifact_engine.sql +3853 -0
- package/drizzle/0192_editable_artifact_live_tickets.sql +338 -0
- package/drizzle/0193_editable_artifact_authorization.sql +190 -0
- package/drizzle/0194_editable_artifact_durable_exports.sql +160 -0
- package/drizzle/0195_editable_artifact_import_authorization.sql +203 -0
- package/drizzle/0196_rig_provider_images.sql +152 -0
- package/drizzle/0197_knowledge_source_sync_schedules.sql +523 -0
- package/drizzle/0198_memory_slack_publication_delivery.sql +393 -0
- package/drizzle/0199_workspace_learning_policy.sql +980 -0
- package/drizzle/0201_company_profile_authority.sql +849 -0
- package/drizzle/0202_document_index_checkpoints.sql +85 -0
- package/drizzle/0203_durable_video_generation.sql +353 -0
- package/drizzle/0204_video_generation_funding.sql +44 -0
- package/drizzle/0205_attempt_tool_catalogs.sql +230 -0
- package/drizzle/0206_browser_sessions.sql +646 -0
- package/drizzle/0207_browser_identities.sql +379 -0
- package/drizzle/0208_attached_browser_devices.sql +165 -0
- package/drizzle/0209_computer_sessions.sql +575 -0
- package/drizzle/0210_browser_auth_network_interventions.sql +441 -0
- package/drizzle/0211_editable_artifact_session_links.sql +58 -0
- package/drizzle/0212_slack_installation_bindings.sql +348 -0
- package/drizzle/0213_slack_user_link_access_requests.sql +177 -0
- package/drizzle/0214_session_activity_commit_gate.sql +262 -0
- package/drizzle/0215_capabilities_platform.sql +980 -0
- package/drizzle/0216_pack_component_ownership.sql +235 -0
- package/drizzle/0217_capability_definition_delete_authority.sql +32 -0
- package/package.json +18 -5
- package/src/attached-browser-devices.ts +371 -0
- package/src/attempt-tool-catalogs.ts +131 -0
- package/src/browser-auth.ts +1896 -0
- package/src/browser-identities.ts +1168 -0
- package/src/browser-sessions.ts +2005 -0
- package/src/browser-state-artifacts.ts +59 -0
- package/src/capability-components.ts +166 -0
- package/src/capability-integrations.ts +1663 -0
- package/src/codemode-operations.ts +674 -0
- package/src/company-profile-schema.ts +143 -0
- package/src/company-profile.ts +968 -0
- package/src/computer-sessions.ts +1130 -0
- package/src/connection-token-resolver.ts +270 -25
- package/src/database.ts +434 -24
- package/src/editable-artifact-durable-export.ts +1201 -0
- package/src/editable-artifact-materialization.ts +893 -0
- package/src/editable-artifacts-schema.ts +879 -0
- package/src/editable-artifacts.ts +5404 -0
- package/src/environment-crypto.ts +22 -9
- package/src/generated-images.ts +740 -0
- package/src/index.ts +10117 -2730
- package/src/insights.ts +160 -13
- package/src/integration-bindings.ts +455 -0
- package/src/integration-features.ts +859 -0
- package/src/interaction-revisions.ts +40 -0
- package/src/interaction-schema.ts +1303 -0
- package/src/knowledge-source-sync-schema.ts +192 -0
- package/src/knowledge-source-sync.ts +1922 -0
- package/src/lossless-columns.ts +35 -0
- package/src/lossless-json.ts +322 -0
- package/src/memory-domain.ts +5 -44
- package/src/memory-slack-delivery.ts +801 -0
- package/src/pack-components.ts +954 -0
- package/src/pack-installations.ts +929 -0
- package/src/persistence-errors.ts +26 -34
- package/src/plugin-packages.ts +1186 -0
- package/src/provision-roles.ts +302 -1
- package/src/runtime-posture-cli.ts +9 -0
- package/src/runtime-posture.ts +514 -5
- package/src/schema.ts +5177 -2957
- package/src/scoped-knowledge-schema.ts +1 -1
- package/src/scoped-knowledge.ts +655 -3
- package/src/session-control.ts +133 -81
- package/src/session-queue-commands.ts +511 -247
- package/src/session-realtime-context.ts +20 -7
- package/src/session-realtime-ledger.ts +32 -10
- package/src/session-realtime-mirror.ts +4 -2
- package/src/session-realtime-terminal.ts +89 -21
- package/src/session-realtime.ts +10 -9
- package/src/session-tool-call-settlement.ts +38 -15
- package/src/slack-user-link-access.ts +702 -0
- package/src/transcription-recordings-schema.ts +5 -2
- package/src/transcription-recordings.ts +70 -40
- package/src/video-generation.ts +1452 -0
- package/src/workspace-learning-policy-schema.ts +139 -0
- package/src/workspace-learning-policy.ts +595 -0
- package/dist/chunk-DBS5HPEW.js.map +0 -1
- package/dist/chunk-HT5T62CC.js +0 -6803
- package/dist/chunk-HT5T62CC.js.map +0 -1
- package/dist/event-payload-sanitizer.d.ts +0 -32
- package/src/event-payload-sanitizer.ts +0 -377
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
-- deployment-mode: maintenance
|
|
2
|
+
-- Replace the hidden per-row activity-counter allocator with one explicit
|
|
3
|
+
-- once-per-transaction commit gate. Readers become ordinary MVCC reads; writers
|
|
4
|
+
-- settle every other constraint before briefly advancing the workspace clock.
|
|
5
|
+
-- The durable ledger remains the source of truth; no application-local cache participates.
|
|
6
|
+
|
|
7
|
+
SET lock_timeout = '5s';
|
|
8
|
+
SET statement_timeout = '10min';
|
|
9
|
+
|
|
10
|
+
ALTER TABLE "sessions"
|
|
11
|
+
ADD COLUMN "activity_revision_pending_xid" bigint;
|
|
12
|
+
|
|
13
|
+
CREATE INDEX "sessions_workspace_activity_pending_idx"
|
|
14
|
+
ON "sessions" ("workspace_id", "activity_revision_pending_xid", "id")
|
|
15
|
+
WHERE "activity_revision_pending_xid" IS NOT NULL;
|
|
16
|
+
|
|
17
|
+
CREATE OR REPLACE FUNCTION opengeni_private.ensure_workspace_session_activity_revision(
|
|
18
|
+
target_schema text,
|
|
19
|
+
target_workspace_id uuid,
|
|
20
|
+
target_account_id uuid
|
|
21
|
+
)
|
|
22
|
+
RETURNS void
|
|
23
|
+
LANGUAGE plpgsql
|
|
24
|
+
SECURITY DEFINER
|
|
25
|
+
SET search_path = pg_catalog
|
|
26
|
+
AS $function$
|
|
27
|
+
DECLARE
|
|
28
|
+
previous_account_id text := current_setting('opengeni.account_id', true);
|
|
29
|
+
previous_workspace_id text := current_setting('opengeni.workspace_id', true);
|
|
30
|
+
BEGIN
|
|
31
|
+
-- FORCE RLS applies to supported non-bypass table owners too. Establish only
|
|
32
|
+
-- the row's own trusted scope, then restore the caller's transaction-local
|
|
33
|
+
-- context so structural initialization cannot leak authority downstream.
|
|
34
|
+
PERFORM set_config('opengeni.account_id', target_account_id::text, true);
|
|
35
|
+
PERFORM set_config('opengeni.workspace_id', target_workspace_id::text, true);
|
|
36
|
+
EXECUTE format(
|
|
37
|
+
'INSERT INTO %I.workspace_session_activity_revisions '
|
|
38
|
+
|| '(workspace_id, account_id, revision) VALUES ($1, $2, 0) '
|
|
39
|
+
|| 'ON CONFLICT (workspace_id) DO NOTHING',
|
|
40
|
+
target_schema
|
|
41
|
+
)
|
|
42
|
+
USING target_workspace_id, target_account_id;
|
|
43
|
+
PERFORM set_config('opengeni.account_id', coalesce(previous_account_id, ''), true);
|
|
44
|
+
PERFORM set_config('opengeni.workspace_id', coalesce(previous_workspace_id, ''), true);
|
|
45
|
+
EXCEPTION WHEN OTHERS THEN
|
|
46
|
+
PERFORM set_config('opengeni.account_id', coalesce(previous_account_id, ''), true);
|
|
47
|
+
PERFORM set_config('opengeni.workspace_id', coalesce(previous_workspace_id, ''), true);
|
|
48
|
+
RAISE;
|
|
49
|
+
END;
|
|
50
|
+
$function$;
|
|
51
|
+
|
|
52
|
+
REVOKE ALL ON FUNCTION opengeni_private.ensure_workspace_session_activity_revision(
|
|
53
|
+
text, uuid, uuid
|
|
54
|
+
) FROM PUBLIC;
|
|
55
|
+
|
|
56
|
+
CREATE OR REPLACE FUNCTION opengeni_private.initialize_workspace_session_activity_revision()
|
|
57
|
+
RETURNS trigger
|
|
58
|
+
LANGUAGE plpgsql
|
|
59
|
+
SECURITY DEFINER
|
|
60
|
+
SET search_path = pg_catalog
|
|
61
|
+
AS $function$
|
|
62
|
+
BEGIN
|
|
63
|
+
PERFORM opengeni_private.ensure_workspace_session_activity_revision(
|
|
64
|
+
TG_TABLE_SCHEMA,
|
|
65
|
+
NEW.id,
|
|
66
|
+
NEW.account_id
|
|
67
|
+
);
|
|
68
|
+
RETURN NEW;
|
|
69
|
+
END;
|
|
70
|
+
$function$;
|
|
71
|
+
|
|
72
|
+
REVOKE ALL ON FUNCTION opengeni_private.initialize_workspace_session_activity_revision()
|
|
73
|
+
FROM PUBLIC;
|
|
74
|
+
|
|
75
|
+
CREATE TRIGGER workspaces_initialize_session_activity_revision
|
|
76
|
+
AFTER INSERT ON "workspaces"
|
|
77
|
+
FOR EACH ROW
|
|
78
|
+
EXECUTE FUNCTION opengeni_private.initialize_workspace_session_activity_revision();
|
|
79
|
+
|
|
80
|
+
-- Install the structural initializer before taking the existing-workspace
|
|
81
|
+
-- snapshot. CREATE TRIGGER fences concurrent workspace writers; the subsequent
|
|
82
|
+
-- conflict-safe backfill covers every row that committed before the trigger,
|
|
83
|
+
-- while later rows are covered by the trigger itself. The same private helper
|
|
84
|
+
-- keeps this path valid when the schema owner is subject to FORCE RLS.
|
|
85
|
+
SELECT opengeni_private.ensure_workspace_session_activity_revision(
|
|
86
|
+
current_schema(),
|
|
87
|
+
"id",
|
|
88
|
+
"account_id"
|
|
89
|
+
)
|
|
90
|
+
FROM "workspaces";
|
|
91
|
+
|
|
92
|
+
-- Counter lifecycle is now structural: the workspace trigger creates rows and
|
|
93
|
+
-- the foreign-key cascade removes them. The application may only observe and
|
|
94
|
+
-- advance an existing counter at the explicit commit gate.
|
|
95
|
+
DO $grants$
|
|
96
|
+
DECLARE target_schema text := current_schema();
|
|
97
|
+
BEGIN
|
|
98
|
+
IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'opengeni_app') THEN
|
|
99
|
+
EXECUTE format(
|
|
100
|
+
'REVOKE INSERT, DELETE ON TABLE %I.workspace_session_activity_revisions FROM opengeni_app',
|
|
101
|
+
target_schema
|
|
102
|
+
);
|
|
103
|
+
END IF;
|
|
104
|
+
END $grants$;
|
|
105
|
+
|
|
106
|
+
-- UPDATE remains necessary for the runtime finalizer, but the table itself
|
|
107
|
+
-- rejects every other write shape. This catches a forgotten wrapper even when
|
|
108
|
+
-- application code reaches for the counter directly instead of a session row.
|
|
109
|
+
CREATE OR REPLACE FUNCTION opengeni_private.guard_workspace_session_activity_revision()
|
|
110
|
+
RETURNS trigger
|
|
111
|
+
LANGUAGE plpgsql
|
|
112
|
+
SET search_path = pg_catalog
|
|
113
|
+
AS $function$
|
|
114
|
+
DECLARE
|
|
115
|
+
gate_state text := nullif(current_setting('opengeni.session_activity_gate_state', true), '');
|
|
116
|
+
gate_workspace_id uuid := nullif(
|
|
117
|
+
current_setting('opengeni.session_activity_gate_workspace_id', true),
|
|
118
|
+
''
|
|
119
|
+
)::uuid;
|
|
120
|
+
BEGIN
|
|
121
|
+
IF gate_state <> 'finalizing'
|
|
122
|
+
OR gate_workspace_id IS DISTINCT FROM OLD.workspace_id
|
|
123
|
+
OR NEW.workspace_id IS DISTINCT FROM OLD.workspace_id
|
|
124
|
+
OR NEW.account_id IS DISTINCT FROM OLD.account_id
|
|
125
|
+
OR NEW.revision IS DISTINCT FROM OLD.revision + 1
|
|
126
|
+
THEN
|
|
127
|
+
RAISE EXCEPTION USING
|
|
128
|
+
ERRCODE = '55000',
|
|
129
|
+
MESSAGE = 'Workspace session activity revision requires the finalizing commit gate';
|
|
130
|
+
END IF;
|
|
131
|
+
RETURN NEW;
|
|
132
|
+
END;
|
|
133
|
+
$function$;
|
|
134
|
+
|
|
135
|
+
REVOKE ALL ON FUNCTION opengeni_private.guard_workspace_session_activity_revision()
|
|
136
|
+
FROM PUBLIC;
|
|
137
|
+
|
|
138
|
+
CREATE TRIGGER workspace_session_activity_revision_commit_gate
|
|
139
|
+
BEFORE UPDATE ON "workspace_session_activity_revisions"
|
|
140
|
+
FOR EACH ROW
|
|
141
|
+
EXECUTE FUNCTION opengeni_private.guard_workspace_session_activity_revision();
|
|
142
|
+
|
|
143
|
+
DROP TRIGGER sessions_assign_activity_revision ON "sessions";
|
|
144
|
+
DROP FUNCTION opengeni_private.assign_session_activity_revision();
|
|
145
|
+
|
|
146
|
+
CREATE OR REPLACE FUNCTION opengeni_private.mark_session_activity_pending()
|
|
147
|
+
RETURNS trigger
|
|
148
|
+
LANGUAGE plpgsql
|
|
149
|
+
SET search_path = pg_catalog
|
|
150
|
+
AS $function$
|
|
151
|
+
DECLARE
|
|
152
|
+
gate_state text := nullif(current_setting('opengeni.session_activity_gate_state', true), '');
|
|
153
|
+
gate_workspace_id uuid := nullif(
|
|
154
|
+
current_setting('opengeni.session_activity_gate_workspace_id', true),
|
|
155
|
+
''
|
|
156
|
+
)::uuid;
|
|
157
|
+
current_xid bigint := pg_current_xact_id()::text::bigint;
|
|
158
|
+
BEGIN
|
|
159
|
+
IF gate_state = 'finalizing' THEN
|
|
160
|
+
IF TG_OP <> 'UPDATE'
|
|
161
|
+
OR NEW.workspace_id IS DISTINCT FROM OLD.workspace_id
|
|
162
|
+
OR NEW.updated_at IS DISTINCT FROM OLD.updated_at
|
|
163
|
+
OR OLD.activity_revision_pending_xid IS DISTINCT FROM current_xid
|
|
164
|
+
OR NEW.activity_revision_pending_xid IS NOT NULL
|
|
165
|
+
OR NEW.activity_revision <= OLD.activity_revision
|
|
166
|
+
THEN
|
|
167
|
+
RAISE EXCEPTION USING
|
|
168
|
+
ERRCODE = '55000',
|
|
169
|
+
MESSAGE = 'Invalid session activity finalization';
|
|
170
|
+
END IF;
|
|
171
|
+
RETURN NEW;
|
|
172
|
+
END IF;
|
|
173
|
+
|
|
174
|
+
IF gate_state <> 'open' OR gate_workspace_id IS DISTINCT FROM NEW.workspace_id THEN
|
|
175
|
+
RAISE EXCEPTION USING
|
|
176
|
+
ERRCODE = '55000',
|
|
177
|
+
MESSAGE = 'Session activity write requires an open workspace commit gate';
|
|
178
|
+
END IF;
|
|
179
|
+
|
|
180
|
+
IF TG_OP = 'INSERT' THEN
|
|
181
|
+
IF NEW.activity_revision <> 0 OR NEW.activity_revision_pending_xid IS NOT NULL THEN
|
|
182
|
+
RAISE EXCEPTION USING
|
|
183
|
+
ERRCODE = '55000',
|
|
184
|
+
MESSAGE = 'Session activity revision is managed by the commit gate';
|
|
185
|
+
END IF;
|
|
186
|
+
ELSIF NEW.activity_revision IS DISTINCT FROM OLD.activity_revision
|
|
187
|
+
OR NEW.activity_revision_pending_xid IS DISTINCT FROM OLD.activity_revision_pending_xid
|
|
188
|
+
THEN
|
|
189
|
+
RAISE EXCEPTION USING
|
|
190
|
+
ERRCODE = '55000',
|
|
191
|
+
MESSAGE = 'Session activity revision is managed by the commit gate';
|
|
192
|
+
END IF;
|
|
193
|
+
|
|
194
|
+
NEW.activity_revision_pending_xid := current_xid;
|
|
195
|
+
RETURN NEW;
|
|
196
|
+
END;
|
|
197
|
+
$function$;
|
|
198
|
+
|
|
199
|
+
REVOKE ALL ON FUNCTION opengeni_private.mark_session_activity_pending()
|
|
200
|
+
FROM PUBLIC;
|
|
201
|
+
|
|
202
|
+
CREATE TRIGGER sessions_mark_activity_pending
|
|
203
|
+
BEFORE INSERT OR UPDATE OF "updated_at", "activity_revision", "activity_revision_pending_xid"
|
|
204
|
+
ON "sessions"
|
|
205
|
+
FOR EACH ROW
|
|
206
|
+
EXECUTE FUNCTION opengeni_private.mark_session_activity_pending();
|
|
207
|
+
|
|
208
|
+
-- A transaction that opens the gate manually but omits the finalizer still
|
|
209
|
+
-- cannot commit. The application gate switches to `preparing` before forcing
|
|
210
|
+
-- all deferred checks, then clears every pending marker in its final write.
|
|
211
|
+
CREATE OR REPLACE FUNCTION opengeni_private.reject_unfinalized_session_activity()
|
|
212
|
+
RETURNS trigger
|
|
213
|
+
LANGUAGE plpgsql
|
|
214
|
+
SET search_path = pg_catalog
|
|
215
|
+
AS $function$
|
|
216
|
+
DECLARE
|
|
217
|
+
gate_state text := nullif(current_setting('opengeni.session_activity_gate_state', true), '');
|
|
218
|
+
still_pending_xid bigint;
|
|
219
|
+
BEGIN
|
|
220
|
+
IF gate_state = 'preparing' THEN
|
|
221
|
+
RETURN NULL;
|
|
222
|
+
END IF;
|
|
223
|
+
EXECUTE format(
|
|
224
|
+
'SELECT activity_revision_pending_xid FROM %I.sessions WHERE id = $1',
|
|
225
|
+
TG_TABLE_SCHEMA
|
|
226
|
+
)
|
|
227
|
+
INTO still_pending_xid
|
|
228
|
+
USING NEW.id;
|
|
229
|
+
IF still_pending_xid IS NOT NULL THEN
|
|
230
|
+
RAISE EXCEPTION USING
|
|
231
|
+
ERRCODE = '55000',
|
|
232
|
+
MESSAGE = 'Session activity transaction reached commit without finalization';
|
|
233
|
+
END IF;
|
|
234
|
+
RETURN NULL;
|
|
235
|
+
END;
|
|
236
|
+
$function$;
|
|
237
|
+
|
|
238
|
+
REVOKE ALL ON FUNCTION opengeni_private.reject_unfinalized_session_activity()
|
|
239
|
+
FROM PUBLIC;
|
|
240
|
+
|
|
241
|
+
CREATE CONSTRAINT TRIGGER sessions_activity_insert_commit_guard
|
|
242
|
+
AFTER INSERT ON "sessions"
|
|
243
|
+
DEFERRABLE INITIALLY DEFERRED
|
|
244
|
+
FOR EACH ROW
|
|
245
|
+
WHEN (NEW.activity_revision_pending_xid IS NOT NULL)
|
|
246
|
+
EXECUTE FUNCTION opengeni_private.reject_unfinalized_session_activity();
|
|
247
|
+
|
|
248
|
+
-- The clearing write must queue a second check as well. The application first
|
|
249
|
+
-- flushes all existing deferred constraints, re-defers these two guards, stamps
|
|
250
|
+
-- every pending row, and then forces both guards against the final row state.
|
|
251
|
+
CREATE CONSTRAINT TRIGGER sessions_activity_update_commit_guard
|
|
252
|
+
AFTER UPDATE ON "sessions"
|
|
253
|
+
DEFERRABLE INITIALLY DEFERRED
|
|
254
|
+
FOR EACH ROW
|
|
255
|
+
WHEN (
|
|
256
|
+
NEW.activity_revision_pending_xid IS NOT NULL
|
|
257
|
+
OR OLD.activity_revision_pending_xid IS NOT NULL
|
|
258
|
+
)
|
|
259
|
+
EXECUTE FUNCTION opengeni_private.reject_unfinalized_session_activity();
|
|
260
|
+
|
|
261
|
+
RESET statement_timeout;
|
|
262
|
+
RESET lock_timeout;
|