UNPKG

11.3 kBJavaScriptView Raw
1//- JavaScript source code
2
3//- defs-postgres.js ~~
4//
5// NOTE: SQL is _not_ a particular strength of mine, and I appreciate input!
6//
7// ~~ (c) SRW, 25 Sep 2012
8// ~~ last updated 21 Mar 2014
9
10(function () {
11 'use strict';
12
13 // Pragmas
14
15 /*jshint maxparams: 3, quotmark: single, strict: true */
16
17 /*jslint indent: 4, maxlen: 80, node: true */
18
19 // Declarations
20
21 var cluster, pg;
22
23 // Definitions
24
25 cluster = require('cluster');
26
27 pg = require('pg'); //- or, use `require('pg').native` ...
28
29 // Out-of-scope definitions
30
31 exports.api = function (options) {
32 // This function needs documentation.
33
34 var collect_garbage, connection_string, exp_date, get_avar, get_list,
35 set_avar;
36
37 collect_garbage = function () {
38 // This function needs documentation.
39 pg.connect(connection_string, function (err, client, done) {
40 // This function needs documentation.
41 if (err !== null) {
42 console.error('Error:', err);
43 done();
44 return;
45 }
46 var now, sql;
47 now = Math.ceil(Date.now() / 1000);
48 sql = 'DELETE FROM avars WHERE (exp_date < $1)';
49 client.query(sql, [now], function (err) {
50 // This function n needs documentation.
51 if (err !== null) {
52 console.error('Error:', err);
53 } else {
54 console.log('Finished collecting garbage.');
55 }
56 done();
57 return;
58 });
59 return;
60 });
61 return;
62 };
63
64 connection_string = options.postgres;
65
66 exp_date = function () {
67 // This function needs documentation.
68 return Math.ceil((Date.now() / 1000) + options.avar_ttl);
69 };
70
71 get_avar = function (params, callback) {
72 // This function needs documentation.
73 pg.connect(connection_string, function (err, client, done) {
74 // This function needs documentation.
75 if (err !== null) {
76 done();
77 return callback(err, undefined);
78 }
79 var x = 'SELECT body FROM avars WHERE box_key = $1';
80 client.query(x, [params.join('&')], function (err, results) {
81 // This function needs documentation.
82 done();
83 if (err !== null) {
84 return callback(err, undefined);
85 }
86 if (results.rows.length < 1) {
87 return callback(null, undefined);
88 }
89 return callback(null, results.rows[0].body);
90 });
91 return;
92 });
93 return;
94 };
95
96 get_list = function (params, callback) {
97 // This function needs documentation.
98 pg.connect(connection_string, function (err, client, done) {
99 // This function needs documentation.
100 if (err !== null) {
101 done();
102 return callback(err, undefined);
103 }
104 var x = 'SELECT key FROM avars WHERE box_status = $1';
105 client.query(x, [params.join('&')], function (err, results) {
106 // This function needs documentation.
107 done();
108 if (err !== null) {
109 return callback(err, undefined);
110 }
111 var y = (results === undefined) ? {rows: []} : results;
112 return callback(null, y.rows.map(function (row) {
113 // This function needs documentation.
114 return row.key;
115 }));
116 });
117 return;
118 });
119 return;
120 };
121
122 set_avar = function (params, callback) {
123 // This function needs documentation.
124 pg.connect(connection_string, function (err, client, done) {
125 // This function needs documentation.
126 if (err !== null) {
127 done();
128 return callback(err, undefined);
129 }
130 var args, sql;
131 if (params.length === 4) {
132 args = [
133 params[3],
134 params[0] + '&' + params[1],
135 params[0] + '&' + params[2],
136 exp_date(),
137 params[1]
138 ];
139 sql = 'SELECT upsert_task($1, $2, $3, $4, $5)';
140 } else {
141 args = [
142 params[2],
143 params[0] + '&' + params[1],
144 exp_date()
145 ];
146 sql = 'SELECT upsert_avar($1, $2, $3)';
147 }
148 client.query(sql, args, function (err, results) {
149 // This function needs documentation.
150 done();
151 return callback(err, results);
152 });
153 return;
154 });
155 return;
156 };
157
158 if (cluster.isMaster) {
159 pg.connect(connection_string, function (err, client, done) {
160 // This function needs documentation.
161 if (err !== null) {
162 done();
163 throw err;
164 }
165 var lines;
166 lines = [
167 'CREATE TABLE IF NOT EXISTS avars (',
168 ' body TEXT NOT NULL,',
169 ' box_key TEXT NOT NULL,',
170 ' box_status TEXT,',
171 ' exp_date INTEGER NOT NULL,',
172 ' key TEXT,', //- this doesn't need to be "NOT NULL"
173 ' PRIMARY KEY (box_key)',
174 ');',
175 'CREATE OR REPLACE FUNCTION upsert_avar' +
176 '(b2 TEXT, bk2 TEXT, ed2 INTEGER) RETURNS VOID AS',
177 '$$',
178 'BEGIN',
179 ' LOOP',
180 ' UPDATE avars',
181 ' SET body = b2,' +
182 ' box_status = NULL,' +
183 ' exp_date = ed2,' +
184 ' key = NULL',
185 ' WHERE box_key = bk2;',
186 ' IF found THEN',
187 ' RETURN;',
188 ' END IF;',
189 ' BEGIN',
190 ' INSERT INTO avars (body, box_key, exp_date)',
191 ' VALUES (b2, bk2, ed2);',
192 ' RETURN;',
193 ' EXCEPTION WHEN unique_violation THEN',
194 ' END;',
195 ' END LOOP;',
196 'END;',
197 '$$',
198 'LANGUAGE plpgsql;',
199 'CREATE OR REPLACE FUNCTION upsert_task' +
200 '(b2 TEXT, bk2 TEXT, bs2 TEXT, ed2 INTEGER, k2 TEXT)' +
201 'RETURNS VOID AS',
202 '$$',
203 'BEGIN',
204 ' LOOP',
205 ' UPDATE avars',
206 ' SET body = b2,' +
207 ' box_status = bs2,' +
208 ' exp_date = ed2,' +
209 ' key = k2',
210 ' WHERE box_key = bk2;',
211 ' IF found THEN',
212 ' RETURN;',
213 ' END IF;',
214 ' BEGIN',
215 ' INSERT INTO avars ' +
216 ' (body, box_key, box_status, exp_date, key)',
217 ' VALUES (b2, bk2, bs2, ed2, k2);',
218 ' RETURN;',
219 ' EXCEPTION WHEN unique_violation THEN',
220 ' END;',
221 ' END LOOP;',
222 'END;',
223 '$$',
224 'LANGUAGE plpgsql;'
225 ];
226 client.query(lines.join('\n'), function (err) {
227 // This function also accepts a second argument that contains
228 // the "results" of the query, but because I don't use it, I
229 // have omitted it to avoid irritating JSLint et al.
230 done();
231 if (err !== null) {
232 throw err;
233 }
234 console.log('API: Postgres storage is ready.');
235 return;
236 });
237 return;
238 });
239 }
240
241 return {
242 collect_garbage: collect_garbage,
243 get_avar: get_avar,
244 get_list: get_list,
245 set_avar: set_avar
246 };
247 };
248
249 exports.log = function (options) {
250 // This function needs documentation.
251 pg.connect(options.postgres, function (err, client, done) {
252 // This function needs documentation.
253 if (err !== null) {
254 done();
255 throw err;
256 }
257 var lines;
258 lines = [
259 'CREATE EXTENSION IF NOT EXISTS hstore;',
260 'CREATE TABLE IF NOT EXISTS traffic (',
261 ' id serial PRIMARY KEY,',
262 ' doc hstore',
263 ');'
264 ];
265 client.query(lines.join('\n'), function (err) {
266 // This function needs documentation.
267 if (err !== null) {
268 console.error('Error:', err);
269 }
270 done();
271 return;
272 });
273 return;
274 });
275 return function (obj) {
276 // This function needs documentation.
277 pg.connect(options.postgres, function (err, client, done) {
278 // This function needs documentation.
279 if (err !== null) {
280 done();
281 throw err;
282 }
283 var doc, key, sql, temp;
284 temp = [];
285 for (key in obj) {
286 if (obj.hasOwnProperty(key)) {
287 temp.push(key + ' => ' + JSON.stringify(obj[key]));
288 }
289 }
290 doc = temp.join(', ');
291 sql = 'INSERT INTO traffic (doc) VALUES (\'' + doc + '\');';
292 client.query(sql, function (err) {
293 // This function needs documentation.
294 if (err !== null) {
295 console.error('Error:', err);
296 }
297 done();
298 return;
299 });
300 return;
301 });
302 return;
303 };
304 };
305
306 // That's all, folks!
307
308 return;
309
310}());
311
312//- vim:set syntax=javascript: