Repository navigation
feat: install noncurrent lifecycle schema #1620
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
ca3e73c
feat: install noncurrent lifecycle schema
ferhatelmas 42a81b9
fix: orioledb workaround
ferhatelmas 9690903
fix: preserve unknown state
ferhatelmas 377a605
fix: orioledb test
ferhatelmas ddfd047
fix: set lock timeout
ferhatelmas d21aa5d
fix: improve fixture
ferhatelmas 5a3ce8c
fix: use remaning deadline for lock
ferhatelmas File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| CREATE TABLE IF NOT EXISTS public.lifecycle_tenants ( | ||
| tenant_id text PRIMARY KEY | ||
| REFERENCES public.tenants(id) | ||
| ON DELETE CASCADE, | ||
|
|
||
| next_dispatch_at timestamptz NOT NULL DEFAULT now(), | ||
|
|
||
| claim_id uuid, | ||
| claim_until timestamptz, | ||
|
|
||
| last_dispatched_at timestamptz, | ||
| last_completed_at timestamptz, | ||
| last_success_at timestamptz, | ||
|
|
||
| failure_count integer NOT NULL DEFAULT 0, | ||
| last_error jsonb, | ||
|
|
||
| -- Advisory snapshots collected by tenant dispatchers. | ||
| -- Timestamps expose stale or unavailable tenant observations. | ||
| -- Scheduling continues to use the tenant state. | ||
| max_bucket_failure_count integer, | ||
| oldest_in_flight_started_at timestamptz, | ||
| bucket_status_observed_at timestamptz, | ||
|
|
||
| CONSTRAINT lifecycle_tenants_failure_count_check | ||
| CHECK (failure_count >= 0) | ||
| ); | ||
|
|
||
| CREATE INDEX IF NOT EXISTS lifecycle_tenants_due_idx | ||
| ON public.lifecycle_tenants ( | ||
| next_dispatch_at, | ||
| tenant_id | ||
| ); | ||
|
|
||
| CREATE INDEX IF NOT EXISTS lifecycle_tenants_expired_claim_idx | ||
| ON public.lifecycle_tenants ( | ||
| claim_until, | ||
| tenant_id | ||
| ) | ||
| WHERE claim_until IS NOT NULL; | ||
|
|
||
| -- Existing policies, restored tenants and freshly migrated tenant DBs need dispatch without another policy PUT. | ||
| CREATE OR REPLACE FUNCTION public.enroll_lifecycle_tenant() | ||
| RETURNS trigger | ||
| LANGUAGE plpgsql | ||
| SET search_path = pg_catalog | ||
| AS $$ | ||
| BEGIN | ||
| IF TG_OP = 'UPDATE' | ||
| AND OLD.feature_object_versioning IS NOT DISTINCT FROM NEW.feature_object_versioning | ||
| AND OLD.migrations_version IS NOT DISTINCT FROM NEW.migrations_version THEN | ||
| RETURN NEW; | ||
| END IF; | ||
| INSERT INTO public.lifecycle_tenants (tenant_id, next_dispatch_at) | ||
| VALUES (NEW.id, clock_timestamp()) | ||
| ON CONFLICT (tenant_id) DO UPDATE | ||
| SET next_dispatch_at = LEAST(lifecycle_tenants.next_dispatch_at, EXCLUDED.next_dispatch_at); | ||
| RETURN NEW; | ||
| END; | ||
| $$; | ||
|
|
||
| DROP TRIGGER IF EXISTS enroll_lifecycle_tenant ON public.tenants; | ||
| CREATE TRIGGER enroll_lifecycle_tenant | ||
| AFTER INSERT OR UPDATE OF feature_object_versioning, migrations_version ON public.tenants | ||
| FOR EACH ROW WHEN (NEW.feature_object_versioning) | ||
| EXECUTE FUNCTION public.enroll_lifecycle_tenant(); | ||
|
|
||
| INSERT INTO public.lifecycle_tenants (tenant_id, next_dispatch_at) | ||
| SELECT id, clock_timestamp() FROM public.tenants WHERE feature_object_versioning | ||
| ON CONFLICT (tenant_id) DO UPDATE | ||
| SET next_dispatch_at = LEAST(lifecycle_tenants.next_dispatch_at, EXCLUDED.next_dispatch_at); | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,86 @@ | ||
| -- Add durable lifecycle execution state with one row per bucket. | ||
|
|
||
| CREATE TABLE IF NOT EXISTS storage.bucket_lifecycle_states ( | ||
| bucket_id text PRIMARY KEY, | ||
| generation uuid, | ||
| next_run_at timestamptz, | ||
| claim_id uuid, | ||
| claim_until timestamptz, | ||
| continuation jsonb, | ||
| last_started_at timestamptz, | ||
| last_completed_at timestamptz, | ||
| last_success_at timestamptz, | ||
| last_result jsonb, | ||
| failure_count integer NOT NULL DEFAULT 0, | ||
| last_error jsonb, | ||
| updated_at timestamptz NOT NULL DEFAULT now(), | ||
|
|
||
| CONSTRAINT bucket_lifecycle_states_bucket_id_fkey | ||
| FOREIGN KEY (bucket_id) | ||
| REFERENCES storage.buckets(id) | ||
| ON DELETE CASCADE, | ||
|
|
||
| CONSTRAINT bucket_lifecycle_failure_count_check | ||
| CHECK (failure_count >= 0), | ||
|
|
||
| CONSTRAINT bucket_lifecycle_continuation_object_check | ||
| CHECK ( | ||
| continuation IS NULL | ||
| OR jsonb_typeof(continuation) = 'object' | ||
| ), | ||
|
|
||
| CONSTRAINT bucket_lifecycle_recovery_due_check | ||
| CHECK ( | ||
| next_run_at IS NOT NULL | ||
| OR NOT jsonb_path_exists( | ||
| COALESCE(continuation, '{}'::jsonb), | ||
| '$.batch.inFlight' | ||
| ) | ||
| ), | ||
|
|
||
| CONSTRAINT bucket_lifecycle_last_result_object_check | ||
| CHECK ( | ||
| last_result IS NULL | ||
| OR jsonb_typeof(last_result) = 'object' | ||
| ) | ||
| ); | ||
|
|
||
| DO $$ | ||
| BEGIN | ||
| IF NOT (SELECT relrowsecurity FROM pg_catalog.pg_class | ||
| WHERE oid = 'storage.bucket_lifecycle_states'::regclass) THEN | ||
| ALTER TABLE storage.bucket_lifecycle_states ENABLE ROW LEVEL SECURITY; | ||
| END IF; | ||
| IF to_regclass('storage.bucket_lifecycle_states_due_idx') IS NULL THEN | ||
| CREATE INDEX IF NOT EXISTS bucket_lifecycle_states_due_idx | ||
| ON storage.bucket_lifecycle_states (next_run_at, bucket_id) | ||
| WHERE next_run_at IS NOT NULL; | ||
| END IF; | ||
| END; | ||
| $$; | ||
|
|
||
| DO $$ | ||
| DECLARE | ||
| anon_role text = COALESCE(current_setting('storage.anon_role', true), 'anon'); | ||
| authenticated_role text = COALESCE(current_setting('storage.authenticated_role', true), 'authenticated'); | ||
| service_role text = COALESCE(current_setting('storage.service_role', true), 'service_role'); | ||
| super_user text = COALESCE(current_setting('storage.super_user', true), 'postgres'); | ||
| role_name text; | ||
| BEGIN | ||
| REVOKE ALL ON TABLE storage.bucket_lifecycle_states FROM PUBLIC; | ||
|
|
||
| FOREACH role_name IN ARRAY ARRAY[anon_role, authenticated_role] | ||
| LOOP | ||
| IF EXISTS (SELECT 1 FROM pg_catalog.pg_roles WHERE rolname = role_name) THEN | ||
| EXECUTE format('REVOKE ALL ON TABLE storage.bucket_lifecycle_states FROM %I', role_name); | ||
| END IF; | ||
| END LOOP; | ||
|
|
||
| FOREACH role_name IN ARRAY ARRAY['postgres', super_user, service_role] | ||
| LOOP | ||
| IF EXISTS (SELECT 1 FROM pg_catalog.pg_roles WHERE rolname = role_name) THEN | ||
| EXECUTE format('GRANT ALL ON TABLE storage.bucket_lifecycle_states TO %I', role_name); | ||
| END IF; | ||
| END LOOP; | ||
| END; | ||
| $$; |
5 changes: 5 additions & 0 deletions
5
migrations/tenant/0077-noncurrent-lifecycle-archived-order-index.sql
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| -- postgres-migrations disable-transaction | ||
|
|
||
| CREATE UNIQUE INDEX CONCURRENTLY IF NOT EXISTS objects_archived_order_uq | ||
| ON storage.objects (bucket_id, name COLLATE "C", archived_at) | ||
| WHERE archived_at IS NOT NULL; |
10 changes: 10 additions & 0 deletions
10
migrations/tenant/0078-noncurrent-lifecycle-archived-due-index.sql
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| -- postgres-migrations disable-transaction | ||
|
|
||
| CREATE INDEX CONCURRENTLY IF NOT EXISTS objects_archived_due_idx | ||
| ON storage.objects ( | ||
| bucket_id, | ||
| archived_at, | ||
| name COLLATE "C" | ||
| ) | ||
| INCLUDE (id, version, is_delete_marker) | ||
| WHERE archived_at IS NOT NULL; |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.