hanni76

Untitled

Oct 17th, 2025
104
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.69 KB | None | 0 0
  1. -- ============================================
  2. -- Complete Async Task System in PostgreSQL
  3. -- ============================================
  4.  
  5. -- 1. Create task queue and results tables
  6. CREATE TABLE IF NOT EXISTS task_queue (
  7. id SERIAL PRIMARY KEY,
  8. task_type TEXT NOT NULL,
  9. task_data JSONB,
  10. status TEXT DEFAULT 'pending' CHECK (status IN ('pending', 'processing', 'completed', 'failed')),
  11. priority INTEGER DEFAULT 5,
  12. created_at TIMESTAMP DEFAULT NOW(),
  13. started_at TIMESTAMP,
  14. completed_at TIMESTAMP,
  15. result JSONB,
  16. error_message TEXT,
  17. retry_count INTEGER DEFAULT 0,
  18. max_retries INTEGER DEFAULT 3
  19. );
  20.  
  21. CREATE INDEX idx_task_queue_status ON task_queue(status, priority DESC, created_at);
  22.  
  23. -- 2. Function to enqueue a task (returns immediately)
  24. CREATE OR REPLACE FUNCTION enqueue_task(
  25. p_task_type TEXT,
  26. p_task_data JSONB DEFAULT '{}'::JSONB,
  27. p_priority INTEGER DEFAULT 5
  28. )
  29. RETURNS INTEGER AS $$
  30. DECLARE
  31. v_task_id INTEGER;
  32. BEGIN
  33. -- Insert task into queue
  34. INSERT INTO task_queue (task_type, task_data, status, priority)
  35. VALUES (p_task_type, p_task_data, 'pending', p_priority)
  36. RETURNING id INTO v_task_id;
  37.  
  38. -- Notify workers that a new task is available
  39. PERFORM pg_notify('new_task', v_task_id::TEXT);
  40.  
  41. RETURN v_task_id;
  42. END;
  43. $$ LANGUAGE plpgsql;
  44.  
  45. -- 3. Function to get next pending task (for workers)
  46. CREATE OR REPLACE FUNCTION get_next_task()
  47. RETURNS TABLE (
  48. task_id INTEGER,
  49. task_type TEXT,
  50. task_data JSONB
  51. ) AS $$
  52. BEGIN
  53. RETURN QUERY
  54. UPDATE task_queue
  55. SET status = 'processing',
  56. started_at = NOW()
  57. WHERE id = (
  58. SELECT id FROM task_queue
  59. WHERE status = 'pending'
  60. ORDER BY priority DESC, created_at ASC
  61. FOR UPDATE SKIP LOCKED
  62. LIMIT 1
  63. )
  64. RETURNING id, task_queue.task_type, task_queue.task_data;
  65. END;
  66. $$ LANGUAGE plpgsql;
  67.  
  68. -- 4. Function to mark task as completed
  69. CREATE OR REPLACE FUNCTION complete_task(
  70. p_task_id INTEGER,
  71. p_result JSONB DEFAULT NULL
  72. )
  73. RETURNS VOID AS $$
  74. BEGIN
  75. UPDATE task_queue
  76. SET status = 'completed',
  77. completed_at = NOW(),
  78. result = p_result
  79. WHERE id = p_task_id;
  80.  
  81. -- Notify listeners that task is complete
  82. PERFORM pg_notify('task_completed', p_task_id::TEXT);
  83. END;
  84. $$ LANGUAGE plpgsql;
  85.  
  86. -- 5. Function to mark task as failed
  87. CREATE OR REPLACE FUNCTION fail_task(
  88. p_task_id INTEGER,
  89. p_error_message TEXT
  90. )
  91. RETURNS VOID AS $$
  92. DECLARE
  93. v_retry_count INTEGER;
  94. v_max_retries INTEGER;
  95. BEGIN
  96. -- Get current retry info
  97. SELECT retry_count, max_retries
  98. INTO v_retry_count, v_max_retries
  99. FROM task_queue
  100. WHERE id = p_task_id;
  101.  
  102. -- Check if we should retry
  103. IF v_retry_count < v_max_retries THEN
  104. UPDATE task_queue
  105. SET status = 'pending',
  106. retry_count = retry_count + 1,
  107. error_message = p_error_message
  108. WHERE id = p_task_id;
  109. ELSE
  110. UPDATE task_queue
  111. SET status = 'failed',
  112. completed_at = NOW(),
  113. error_message = p_error_message
  114. WHERE id = p_task_id;
  115. END IF;
  116.  
  117. PERFORM pg_notify('task_failed', p_task_id::TEXT);
  118. END;
  119. $$ LANGUAGE plpgsql;
  120.  
  121. -- 6. Function to get task status
  122. CREATE OR REPLACE FUNCTION get_task_status(p_task_id INTEGER)
  123. RETURNS TABLE (
  124. id INTEGER,
  125. task_type TEXT,
  126. status TEXT,
  127. result JSONB,
  128. error_message TEXT,
  129. created_at TIMESTAMP,
  130. completed_at TIMESTAMP
  131. ) AS $$
  132. BEGIN
  133. RETURN QUERY
  134. SELECT
  135. t.id,
  136. t.task_type,
  137. t.status,
  138. t.result,
  139. t.error_message,
  140. t.created_at,
  141. t.completed_at
  142. FROM task_queue t
  143. WHERE t.id = p_task_id;
  144. END;
  145. $$ LANGUAGE plpgsql;
  146.  
  147. -- 7. Example long-running function
  148. CREATE OR REPLACE FUNCTION process_large_dataset(p_dataset_id INTEGER)
  149. RETURNS JSONB AS $$
  150. DECLARE
  151. v_result JSONB;
  152. v_count INTEGER;
  153. BEGIN
  154. -- Simulate long-running processing
  155. PERFORM pg_sleep(5); -- 5 seconds
  156.  
  157. -- Do actual work here
  158. -- SELECT COUNT(*) INTO v_count FROM large_table WHERE dataset_id = p_dataset_id;
  159.  
  160. v_result := jsonb_build_object(
  161. 'dataset_id', p_dataset_id,
  162. 'processed_records', 1000,
  163. 'status', 'success'
  164. );
  165.  
  166. RETURN v_result;
  167. END;
  168. $$ LANGUAGE plpgsql;
  169.  
  170. -- 8. Cleanup old completed tasks
  171. CREATE OR REPLACE FUNCTION cleanup_old_tasks(p_days_old INTEGER DEFAULT 7)
  172. RETURNS INTEGER AS $$
  173. DECLARE
  174. v_deleted INTEGER;
  175. BEGIN
  176. DELETE FROM task_queue
  177. WHERE status IN ('completed', 'failed')
  178. AND completed_at < NOW() - INTERVAL '1 day' * p_days_old;
  179.  
  180. GET DIAGNOSTICS v_deleted = ROW_COUNT;
  181. RETURN v_deleted;
  182. END;
  183. $$ LANGUAGE plpgsql;
  184.  
  185. -- ============================================
  186. -- USAGE EXAMPLES
  187. -- ============================================
  188.  
  189. -- Enqueue a task (returns immediately with task_id)
  190. SELECT enqueue_task(
  191. 'process_large_dataset',
  192. '{"dataset_id": 123, "options": {"verbose": true}}'::JSONB,
  193. 10 -- high priority
  194. );
  195. -- Returns: task_id (e.g., 1)
  196.  
  197. -- Check task status
  198. SELECT * FROM get_task_status(1);
  199.  
  200. -- Poll for completion
  201. SELECT
  202. id,
  203. status,
  204. result,
  205. EXTRACT(EPOCH FROM (completed_at - created_at)) as duration_seconds
  206. FROM task_queue
  207. WHERE id = 1;
  208.  
  209. -- Get all pending tasks
  210. SELECT * FROM task_queue WHERE status = 'pending' ORDER BY priority DESC;
  211.  
  212. -- Get all completed tasks from last hour
  213. SELECT * FROM task_queue
  214. WHERE status = 'completed'
  215. AND completed_at > NOW() - INTERVAL '1 hour';
  216.  
  217. -- Clean up old tasks
  218. SELECT cleanup_old_tasks(7); -- Remove tasks older than 7 days
Advertisement
Add Comment
Please, Sign In to add comment