Added Task number
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
-- Improve task_number generation to eliminate race conditions.
|
||||
-- Maintain a separate counter table so concurrent inserts can safely bump the
|
||||
-- sequence using an atomic upsert. This migration retains the existing
|
||||
-- trigger name but replaces its body, and creates the helper table.
|
||||
|
||||
-- 1. Create counter table
|
||||
CREATE TABLE IF NOT EXISTS task_number_counters (
|
||||
year_month text PRIMARY KEY,
|
||||
counter bigint NOT NULL
|
||||
);
|
||||
|
||||
-- 2. Initialize counters from existing tasks
|
||||
INSERT INTO task_number_counters(year_month, counter)
|
||||
SELECT s.prefix, s.cnt
|
||||
FROM (
|
||||
SELECT to_char(created_at::timestamp, 'YYYY-MM-') AS prefix,
|
||||
max((substring(task_number FROM 8))::int) AS cnt
|
||||
FROM tasks
|
||||
GROUP BY prefix
|
||||
) s
|
||||
ON CONFLICT (year_month) DO UPDATE SET counter = EXCLUDED.counter;
|
||||
|
||||
-- 3. Replace trigger function with atomic counter logic
|
||||
CREATE OR REPLACE FUNCTION tasks_set_task_number()
|
||||
RETURNS trigger AS $$
|
||||
DECLARE
|
||||
prefix text;
|
||||
seq bigint;
|
||||
BEGIN
|
||||
IF NEW.task_number IS NOT NULL THEN
|
||||
RETURN NEW;
|
||||
END IF;
|
||||
|
||||
prefix := to_char(now(), 'YYYY-MM-');
|
||||
INSERT INTO task_number_counters(year_month, counter)
|
||||
VALUES (prefix, 1)
|
||||
ON CONFLICT (year_month)
|
||||
DO UPDATE SET counter = task_number_counters.counter + 1
|
||||
RETURNING counter INTO seq;
|
||||
|
||||
NEW.task_number := prefix || lpad(seq::text, 5, '0');
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
-- 4. Recreate trigger (drop/recreate to ensure correct function is bound)
|
||||
DROP TRIGGER IF EXISTS tasks_set_task_number_before_insert ON tasks;
|
||||
CREATE TRIGGER tasks_set_task_number_before_insert
|
||||
BEFORE INSERT ON tasks
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION tasks_set_task_number();
|
||||
Reference in New Issue
Block a user