-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathprocesses.sql
More file actions
230 lines (188 loc) · 7.41 KB
/
processes.sql
File metadata and controls
230 lines (188 loc) · 7.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
-------------
-- PROCESSES
-------------
-- processes
CREATE TABLE IF NOT EXISTS processes (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL UNIQUE,
state TEXT NOT NULL CHECK (state IN ('new', 'ready', 'running', 'waiting', 'terminated')),
priority INTEGER DEFAULT 1, -- Higher numbers = higher priority
created_at TIMESTAMP DEFAULT now(),
updated_at TIMESTAMP DEFAULT now(),
owner_user_id INTEGER REFERENCES users(id),
duration INTEGER DEFAULT 1,
waiting_on_semaphore TEXT
);
-- process logs
CREATE TABLE IF NOT EXISTS process_logs (
id SERIAL PRIMARY KEY,
process_id INTEGER REFERENCES processes(id) ON DELETE CASCADE,
action TEXT NOT NULL,
timestamp TIMESTAMP DEFAULT now()
);
-- create a process
CREATE OR REPLACE PROCEDURE create_process(
process_name TEXT,
owner_id INTEGER,
process_priority INTEGER DEFAULT 1
)
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pg_temp
AS $$
BEGIN
-- Permission check
IF NOT check_permission(owner_id, 'process', 'execute') THEN
RAISE EXCEPTION 'User % does not have permission to create a process', owner_id;
END IF;
-- Insert the process
INSERT INTO processes (name, state, priority, owner_user_id, duration)
VALUES (process_name, 'new', process_priority, owner_id, 1);
EXCEPTION
WHEN unique_violation THEN
RAISE EXCEPTION 'Process name % already exists', process_name;
WHEN others THEN
RAISE EXCEPTION 'Could not create process: %', SQLERRM;
END;
$$;
ALTER PROCEDURE create_process(TEXT, INTEGER, INTEGER) OWNER TO pg_os_admin;
CREATE OR REPLACE PROCEDURE start_process(user_id INTEGER, process_id INTEGER)
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pg_temp
AS $$
BEGIN
-- Permission check
IF NOT check_permission(user_id, 'process', 'execute') THEN
RAISE EXCEPTION 'User % does not have permission to start processes', user_id;
END IF;
-- Update the process state to 'ready' only if it's currently 'new'
UPDATE processes
SET state = 'ready', updated_at = now()
WHERE id = process_id AND state = 'new';
-- Check if the update was successful
IF NOT FOUND THEN
RAISE EXCEPTION 'Process % is not in a valid state to be started', process_id;
END IF;
EXCEPTION
WHEN others THEN
RAISE EXCEPTION 'Failed to start process %: %', process_id, SQLERRM;
END;
$$;
ALTER PROCEDURE start_process(INTEGER, INTEGER) OWNER TO pg_os_admin;
CREATE OR REPLACE PROCEDURE execute_process(user_id INTEGER, process_id INTEGER)
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pg_temp
AS $$
DECLARE
exec_duration INTEGER;
BEGIN
-- Permission check
IF NOT check_permission(user_id, 'process', 'execute') THEN
RAISE EXCEPTION 'User % does not have permission to execute processes', user_id;
END IF;
-- Check if the process is ready
UPDATE processes
SET state = 'running', updated_at = now()
WHERE id = process_id AND state = 'ready';
IF NOT FOUND THEN
RAISE NOTICE 'Process % is not ready for execution', process_id;
RETURN;
END IF;
-- Log the start
PERFORM log_process_action(process_id, 'Execution started');
-- Simulate work
SELECT duration INTO exec_duration FROM processes WHERE id = process_id;
IF exec_duration IS NULL OR exec_duration < 0 THEN
exec_duration := 0;
END IF;
PERFORM pg_sleep(exec_duration);
-- Mark process as terminated
UPDATE processes
SET state = 'terminated', updated_at = now()
WHERE id = process_id;
-- Log completion
PERFORM log_process_action(process_id, 'Execution finished');
EXCEPTION
WHEN others THEN
RAISE EXCEPTION 'Failed to execute process %: %', process_id, SQLERRM;
END;
$$;
ALTER PROCEDURE execute_process(INTEGER, INTEGER) OWNER TO pg_os_admin;
-- list all processes by state
CREATE OR REPLACE FUNCTION list_processes_by_state(state_filter TEXT)
RETURNS SETOF processes AS $$
BEGIN
RETURN QUERY SELECT * FROM processes WHERE state = state_filter;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER SET search_path = pg_catalog, pg_temp;
ALTER FUNCTION list_processes_by_state(TEXT) OWNER TO pg_os_admin;
-- list all running or ready processes by priority
CREATE OR REPLACE FUNCTION list_ready_or_running_processes()
RETURNS SETOF processes AS $$
BEGIN
RETURN QUERY SELECT * FROM processes WHERE state IN ('ready', 'running') ORDER BY priority DESC, created_at;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER SET search_path = pg_catalog, pg_temp;
ALTER FUNCTION list_ready_or_running_processes() OWNER TO pg_os_admin;
CREATE OR REPLACE FUNCTION set_process_priority(user_id INTEGER, process_id INTEGER, new_priority INTEGER) RETURNS VOID AS $$
BEGIN
-- Permission check
IF NOT check_permission(user_id, 'process', 'execute') THEN
RAISE EXCEPTION 'User % does not have permission to set process priority', user_id;
END IF;
UPDATE processes SET priority = new_priority, updated_at = now()
WHERE id = process_id;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER SET search_path = pg_catalog, pg_temp;
ALTER FUNCTION set_process_priority(INTEGER, INTEGER, INTEGER) OWNER TO pg_os_admin;
CREATE OR REPLACE FUNCTION terminate_process(user_id INTEGER, process_id INTEGER) RETURNS VOID AS $$
BEGIN
-- Permission check
IF NOT check_permission(user_id, 'process', 'execute') THEN
RAISE EXCEPTION 'User % does not have permission to terminate processes', user_id;
END IF;
UPDATE processes
SET state = 'terminated', updated_at = now()
WHERE id = process_id AND state != 'terminated';
END;
$$ LANGUAGE plpgsql SECURITY DEFINER SET search_path = pg_catalog, pg_temp;
ALTER FUNCTION terminate_process(INTEGER, INTEGER) OWNER TO pg_os_admin;
-- log process
CREATE OR REPLACE FUNCTION log_process_action(process_id INTEGER, action TEXT) RETURNS VOID AS $$
BEGIN
INSERT INTO process_logs (process_id, action) VALUES (process_id, action);
END;
$$ LANGUAGE plpgsql SECURITY DEFINER SET search_path = pg_catalog, pg_temp;
ALTER FUNCTION log_process_action(INTEGER, TEXT) OWNER TO pg_os_admin;
-- count states
CREATE OR REPLACE FUNCTION process_count_by_state() RETURNS TABLE(state TEXT, count INTEGER) AS $$
BEGIN
RETURN QUERY
SELECT state, COUNT(*) FROM processes GROUP BY state;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER SET search_path = pg_catalog, pg_temp;
ALTER FUNCTION process_count_by_state() OWNER TO pg_os_admin;
CREATE OR REPLACE FUNCTION pause_all_processes(user_id INTEGER) RETURNS VOID AS $$
BEGIN
-- Permission check
IF NOT check_permission(user_id, 'process', 'execute') THEN
RAISE EXCEPTION 'User % does not have permission to pause processes', user_id;
END IF;
UPDATE processes SET state = 'waiting', updated_at = now()
WHERE state IN ('ready', 'running');
END;
$$ LANGUAGE plpgsql SECURITY DEFINER SET search_path = pg_catalog, pg_temp;
ALTER FUNCTION pause_all_processes(INTEGER) OWNER TO pg_os_admin;
CREATE OR REPLACE FUNCTION resume_all_waiting_processes(user_id INTEGER) RETURNS VOID AS $$
BEGIN
-- Permission check
IF NOT check_permission(user_id, 'process', 'execute') THEN
RAISE EXCEPTION 'User % does not have permission to resume processes', user_id;
END IF;
UPDATE processes SET state = 'ready', updated_at = now()
WHERE state = 'waiting';
END;
$$ LANGUAGE plpgsql SECURITY DEFINER SET search_path = pg_catalog, pg_temp;
ALTER FUNCTION resume_all_waiting_processes(INTEGER) OWNER TO pg_os_admin;