tep 0.11.4 → 0.11.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Makefile +11 -1
- data/README.md +34 -30
- data/bin/tep +49 -4
- data/examples/pg_hello.rb +12 -1
- data/lib/tep/broadcast.rb +18 -80
- data/lib/tep/net.rb +8 -3
- data/lib/tep/pg.rb +444 -5
- data/lib/tep/presence.rb +22 -318
- data/lib/tep/proxy.rb +2 -2
- data/lib/tep/shell.rb +17 -6
- data/lib/tep/version.rb +1 -1
- data/lib/tep.rb +26 -107
- data/spinel-ext.json +6 -0
- data/test/test_broadcast_pg.rb +1 -0
- data/test/test_pg.rb +1 -0
- data/test/test_presence_pg.rb +1 -0
- metadata +15 -1
data/lib/tep/pg.rb
CHANGED
|
@@ -197,11 +197,10 @@ module PG
|
|
|
197
197
|
h = Pg.tep_pg_connect(opts)
|
|
198
198
|
end
|
|
199
199
|
else
|
|
200
|
-
# Hash form
|
|
201
|
-
# buffers
|
|
202
|
-
#
|
|
203
|
-
#
|
|
204
|
-
# Scheduled-context shortcut points only at conninfo.)
|
|
200
|
+
# Hash-conninfo form: pack the key/value pairs into NUL-delimited
|
|
201
|
+
# buffers for the C shim. (`opts` narrows to Hash in this
|
|
202
|
+
# is_a?(String) ELSE branch -- the narrowing gap that blocked the
|
|
203
|
+
# re-pin, matz/spinel#1434, is fixed as of the SPINEL_PIN bump.)
|
|
205
204
|
keys = ""
|
|
206
205
|
vals = ""
|
|
207
206
|
n = 0
|
|
@@ -1126,3 +1125,443 @@ module PG
|
|
|
1126
1125
|
end
|
|
1127
1126
|
end
|
|
1128
1127
|
end
|
|
1128
|
+
|
|
1129
|
+
# ===================================================================
|
|
1130
|
+
# Opt-in PG backend overrides (#216). Loaded only via `require "tep/pg"`.
|
|
1131
|
+
# These REDEFINE the no-op hooks in core Broadcast/Presence (last-
|
|
1132
|
+
# definition-wins) so a PG app gets the real LISTEN/NOTIFY + mirror
|
|
1133
|
+
# behavior, while a non-PG app keeps the no-ops and DCEs libpq.
|
|
1134
|
+
# ===================================================================
|
|
1135
|
+
module Tep
|
|
1136
|
+
module Broadcast
|
|
1137
|
+
# Cross-worker NOTIFY override (#216). Replaces the core no-op so a
|
|
1138
|
+
# `require "tep/pg"` app fans publishes out to other workers over the
|
|
1139
|
+
# LISTEN/NOTIFY channel. Mirrors the pre-#216 inline branch in
|
|
1140
|
+
# Broadcast.publish.
|
|
1141
|
+
def self.cross_worker_notify(topic, payload)
|
|
1142
|
+
if Tep::APP.broadcast_pg_enabled != 0
|
|
1143
|
+
wire = Tep::Broadcast.encode_wire(topic, payload)
|
|
1144
|
+
Tep::APP.broadcast_pg_conn.notify(
|
|
1145
|
+
Tep::APP.broadcast_pg_channel, wire)
|
|
1146
|
+
end
|
|
1147
|
+
0
|
|
1148
|
+
end
|
|
1149
|
+
|
|
1150
|
+
def self.enable_pg_backend(conninfo, channel)
|
|
1151
|
+
conn = PG::Connection.new(conninfo)
|
|
1152
|
+
if conn.pgh < 0
|
|
1153
|
+
return -1
|
|
1154
|
+
end
|
|
1155
|
+
if conn.listen(channel) < 0
|
|
1156
|
+
return -1
|
|
1157
|
+
end
|
|
1158
|
+
Tep::APP.set_broadcast_pg_conn(conn)
|
|
1159
|
+
Tep::APP.set_broadcast_pg_channel(channel)
|
|
1160
|
+
Tep::APP.set_broadcast_pg_enabled(1)
|
|
1161
|
+
0
|
|
1162
|
+
end
|
|
1163
|
+
|
|
1164
|
+
def self.disable_pg_backend
|
|
1165
|
+
if Tep::APP.broadcast_pg_enabled == 0
|
|
1166
|
+
return 0
|
|
1167
|
+
end
|
|
1168
|
+
Tep::APP.broadcast_pg_conn.unlisten(Tep::APP.broadcast_pg_channel)
|
|
1169
|
+
Tep::APP.broadcast_pg_conn.finish
|
|
1170
|
+
Tep::APP.set_broadcast_pg_enabled(0)
|
|
1171
|
+
0
|
|
1172
|
+
end
|
|
1173
|
+
|
|
1174
|
+
def self.poll_pg_once(timeout_ms)
|
|
1175
|
+
if Tep::APP.broadcast_pg_enabled == 0
|
|
1176
|
+
return -1
|
|
1177
|
+
end
|
|
1178
|
+
r = Tep::APP.broadcast_pg_conn.poll_notification(timeout_ms)
|
|
1179
|
+
if r != 1
|
|
1180
|
+
return r
|
|
1181
|
+
end
|
|
1182
|
+
wire = Tep::APP.broadcast_pg_conn.last_notify_payload
|
|
1183
|
+
Tep::Broadcast.deliver_wire_local(wire)
|
|
1184
|
+
1
|
|
1185
|
+
end
|
|
1186
|
+
|
|
1187
|
+
def self.encode_wire(topic, payload)
|
|
1188
|
+
topic.length.to_s + ":" + topic + payload
|
|
1189
|
+
end
|
|
1190
|
+
|
|
1191
|
+
def self.deliver_wire_local(wire)
|
|
1192
|
+
colon = Tep.str_find(wire, ":", 0)
|
|
1193
|
+
if colon <= 0
|
|
1194
|
+
return -1
|
|
1195
|
+
end
|
|
1196
|
+
len_str = wire[0, colon]
|
|
1197
|
+
tlen = len_str.to_i
|
|
1198
|
+
if tlen < 0 || colon + 1 + tlen > wire.length
|
|
1199
|
+
return -1
|
|
1200
|
+
end
|
|
1201
|
+
topic = wire[colon + 1, tlen]
|
|
1202
|
+
payload = wire[colon + 1 + tlen, wire.length - colon - 1 - tlen]
|
|
1203
|
+
Tep::Broadcast.publish_local_only(topic, payload)
|
|
1204
|
+
end
|
|
1205
|
+
|
|
1206
|
+
end
|
|
1207
|
+
|
|
1208
|
+
module Presence
|
|
1209
|
+
def self.enable_pg_mirror(conninfo)
|
|
1210
|
+
conn = PG::Connection.new(conninfo)
|
|
1211
|
+
if conn.pgh < 0
|
|
1212
|
+
return -1
|
|
1213
|
+
end
|
|
1214
|
+
# exec raises PG::Error on failure now; degrade gracefully
|
|
1215
|
+
# (close + return -1) rather than letting it escape the worker.
|
|
1216
|
+
begin
|
|
1217
|
+
r = conn.exec(Tep::Presence.schema_sql)
|
|
1218
|
+
r.clear
|
|
1219
|
+
# Heartbeat table for the prune-stale-workers path (#47).
|
|
1220
|
+
r = conn.exec(Tep::Presence.worker_schema_sql)
|
|
1221
|
+
r.clear
|
|
1222
|
+
rescue PG::Error
|
|
1223
|
+
conn.finish
|
|
1224
|
+
return -1
|
|
1225
|
+
end
|
|
1226
|
+
Tep::APP.set_presence_pg_conn(conn)
|
|
1227
|
+
worker_id = Sock.sphttp_getpid.to_s + "-" + Time.now.to_i.to_s
|
|
1228
|
+
Tep::APP.set_presence_pg_worker_id(worker_id)
|
|
1229
|
+
Tep::APP.set_presence_pg_enabled(1)
|
|
1230
|
+
# Drop any rows from a prior worker that managed to leave
|
|
1231
|
+
# stale entries with this same worker_id (unlikely thanks
|
|
1232
|
+
# to the boot-epoch suffix, but defensive). Best-effort.
|
|
1233
|
+
Tep::Presence.mirror_exec(
|
|
1234
|
+
"DELETE FROM tep_presence WHERE worker_id = $1",
|
|
1235
|
+
[worker_id])
|
|
1236
|
+
# Register this worker's heartbeat row immediately. Apps
|
|
1237
|
+
# refresh it periodically via Tep::Presence.heartbeat;
|
|
1238
|
+
# prune_stale_workers deletes rows whose heartbeat is stale.
|
|
1239
|
+
Tep::Presence.heartbeat
|
|
1240
|
+
0
|
|
1241
|
+
end
|
|
1242
|
+
|
|
1243
|
+
def self.disable_pg_mirror
|
|
1244
|
+
if Tep::APP.presence_pg_enabled == 0
|
|
1245
|
+
return 0
|
|
1246
|
+
end
|
|
1247
|
+
# Best-effort cleanup -- swallow PG errors (we're tearing the
|
|
1248
|
+
# mirror down regardless) and still finish + disable below.
|
|
1249
|
+
begin
|
|
1250
|
+
r = Tep::APP.presence_pg_conn.exec_params(
|
|
1251
|
+
"DELETE FROM tep_presence WHERE worker_id = $1",
|
|
1252
|
+
[Tep::APP.presence_pg_worker_id])
|
|
1253
|
+
r.clear
|
|
1254
|
+
# Remove the heartbeat row so prune_stale_workers doesn't
|
|
1255
|
+
# see this worker as live after we're gone.
|
|
1256
|
+
r = Tep::APP.presence_pg_conn.exec_params(
|
|
1257
|
+
"DELETE FROM tep_presence_worker WHERE worker_id = $1",
|
|
1258
|
+
[Tep::APP.presence_pg_worker_id])
|
|
1259
|
+
r.clear
|
|
1260
|
+
rescue PG::Error
|
|
1261
|
+
# swallow -- shutting the mirror down anyway
|
|
1262
|
+
end
|
|
1263
|
+
Tep::APP.presence_pg_conn.finish
|
|
1264
|
+
Tep::APP.set_presence_pg_enabled(0)
|
|
1265
|
+
0
|
|
1266
|
+
end
|
|
1267
|
+
|
|
1268
|
+
def self.schema_sql
|
|
1269
|
+
"CREATE TABLE IF NOT EXISTS tep_presence (" +
|
|
1270
|
+
"worker_id TEXT NOT NULL, " +
|
|
1271
|
+
"topic TEXT NOT NULL, " +
|
|
1272
|
+
"fd INTEGER NOT NULL, " +
|
|
1273
|
+
"principal_id TEXT NOT NULL, " +
|
|
1274
|
+
"kind TEXT NOT NULL, " +
|
|
1275
|
+
"agent_id TEXT NOT NULL, " +
|
|
1276
|
+
"since_ts BIGINT NOT NULL, " +
|
|
1277
|
+
"status_state TEXT NOT NULL, " +
|
|
1278
|
+
"status_note TEXT NOT NULL, " +
|
|
1279
|
+
"status_until BIGINT NOT NULL, " +
|
|
1280
|
+
"PRIMARY KEY (worker_id, topic, fd)" +
|
|
1281
|
+
")"
|
|
1282
|
+
end
|
|
1283
|
+
|
|
1284
|
+
def self.worker_schema_sql
|
|
1285
|
+
"CREATE TABLE IF NOT EXISTS tep_presence_worker (" +
|
|
1286
|
+
"worker_id TEXT PRIMARY KEY, " +
|
|
1287
|
+
"last_seen_ts BIGINT NOT NULL" +
|
|
1288
|
+
")"
|
|
1289
|
+
end
|
|
1290
|
+
|
|
1291
|
+
def self.heartbeat
|
|
1292
|
+
if Tep::APP.presence_pg_enabled == 0
|
|
1293
|
+
return 0
|
|
1294
|
+
end
|
|
1295
|
+
wid = Tep::APP.presence_pg_worker_id
|
|
1296
|
+
if wid.length == 0
|
|
1297
|
+
return 0
|
|
1298
|
+
end
|
|
1299
|
+
begin
|
|
1300
|
+
r = Tep::APP.presence_pg_conn.exec_params(
|
|
1301
|
+
"INSERT INTO tep_presence_worker (worker_id, last_seen_ts) " +
|
|
1302
|
+
"VALUES ($1, $2) " +
|
|
1303
|
+
"ON CONFLICT (worker_id) DO UPDATE SET " +
|
|
1304
|
+
" last_seen_ts = EXCLUDED.last_seen_ts",
|
|
1305
|
+
[wid, Time.now.to_i.to_s])
|
|
1306
|
+
r.clear
|
|
1307
|
+
rescue PG::Error
|
|
1308
|
+
return 0
|
|
1309
|
+
end
|
|
1310
|
+
1
|
|
1311
|
+
end
|
|
1312
|
+
|
|
1313
|
+
def self.prune_stale_workers(ttl_seconds)
|
|
1314
|
+
if Tep::APP.presence_pg_enabled == 0
|
|
1315
|
+
return 0
|
|
1316
|
+
end
|
|
1317
|
+
cutoff = Time.now.to_i - ttl_seconds
|
|
1318
|
+
conn = Tep::APP.presence_pg_conn
|
|
1319
|
+
begin
|
|
1320
|
+
# Drop dead heartbeats first; the second DELETE then walks
|
|
1321
|
+
# the worker_id space that's still alive.
|
|
1322
|
+
r1 = conn.exec_params(
|
|
1323
|
+
"DELETE FROM tep_presence_worker WHERE last_seen_ts < $1",
|
|
1324
|
+
[cutoff.to_s])
|
|
1325
|
+
r1.clear
|
|
1326
|
+
# Now drop presence rows whose worker_id isn't in the live
|
|
1327
|
+
# heartbeat table. NOT IN handles both crashed-and-pruned
|
|
1328
|
+
# workers and workers that never registered (legacy rows
|
|
1329
|
+
# from before this prune feature shipped).
|
|
1330
|
+
r2 = conn.exec(
|
|
1331
|
+
"DELETE FROM tep_presence " +
|
|
1332
|
+
"WHERE worker_id NOT IN (SELECT worker_id FROM tep_presence_worker)")
|
|
1333
|
+
n = r2.cmd_tuples
|
|
1334
|
+
r2.clear
|
|
1335
|
+
rescue PG::Error
|
|
1336
|
+
return 0
|
|
1337
|
+
end
|
|
1338
|
+
n
|
|
1339
|
+
end
|
|
1340
|
+
|
|
1341
|
+
def self.mirror_exec(sql, params)
|
|
1342
|
+
begin
|
|
1343
|
+
r = Tep::APP.presence_pg_conn.exec_params(sql, params)
|
|
1344
|
+
r.clear
|
|
1345
|
+
rescue PG::Error
|
|
1346
|
+
# swallow -- advisory mirror, local presence is authoritative
|
|
1347
|
+
end
|
|
1348
|
+
0
|
|
1349
|
+
end
|
|
1350
|
+
|
|
1351
|
+
def self.mirror_insert(entry)
|
|
1352
|
+
if Tep::APP.presence_pg_enabled == 0
|
|
1353
|
+
return 0
|
|
1354
|
+
end
|
|
1355
|
+
Tep::Presence.mirror_exec(
|
|
1356
|
+
"INSERT INTO tep_presence " +
|
|
1357
|
+
"(worker_id, topic, fd, principal_id, kind, agent_id, " +
|
|
1358
|
+
" since_ts, status_state, status_note, status_until) " +
|
|
1359
|
+
"VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) " +
|
|
1360
|
+
"ON CONFLICT (worker_id, topic, fd) DO UPDATE SET " +
|
|
1361
|
+
" principal_id = EXCLUDED.principal_id, " +
|
|
1362
|
+
" kind = EXCLUDED.kind, " +
|
|
1363
|
+
" agent_id = EXCLUDED.agent_id, " +
|
|
1364
|
+
" since_ts = EXCLUDED.since_ts, " +
|
|
1365
|
+
" status_state = EXCLUDED.status_state, " +
|
|
1366
|
+
" status_note = EXCLUDED.status_note, " +
|
|
1367
|
+
" status_until = EXCLUDED.status_until",
|
|
1368
|
+
[
|
|
1369
|
+
Tep::APP.presence_pg_worker_id,
|
|
1370
|
+
entry.topic,
|
|
1371
|
+
entry.fd.to_s,
|
|
1372
|
+
entry.principal_id,
|
|
1373
|
+
entry.kind.to_s,
|
|
1374
|
+
entry.agent_id,
|
|
1375
|
+
entry.since.to_s,
|
|
1376
|
+
entry.status_state.to_s,
|
|
1377
|
+
entry.status_note,
|
|
1378
|
+
entry.status_until.to_s
|
|
1379
|
+
])
|
|
1380
|
+
end
|
|
1381
|
+
|
|
1382
|
+
def self.mirror_delete(topic, fd)
|
|
1383
|
+
if Tep::APP.presence_pg_enabled == 0
|
|
1384
|
+
return 0
|
|
1385
|
+
end
|
|
1386
|
+
Tep::Presence.mirror_exec(
|
|
1387
|
+
"DELETE FROM tep_presence " +
|
|
1388
|
+
"WHERE worker_id = $1 AND topic = $2 AND fd = $3",
|
|
1389
|
+
[Tep::APP.presence_pg_worker_id, topic, fd.to_s])
|
|
1390
|
+
end
|
|
1391
|
+
|
|
1392
|
+
def self.mirror_status(topic, fd, state, note, until_ts)
|
|
1393
|
+
if Tep::APP.presence_pg_enabled == 0
|
|
1394
|
+
return 0
|
|
1395
|
+
end
|
|
1396
|
+
Tep::Presence.mirror_exec(
|
|
1397
|
+
"UPDATE tep_presence " +
|
|
1398
|
+
"SET status_state = $4, status_note = $5, status_until = $6 " +
|
|
1399
|
+
"WHERE worker_id = $1 AND topic = $2 AND fd = $3",
|
|
1400
|
+
[Tep::APP.presence_pg_worker_id, topic, fd.to_s,
|
|
1401
|
+
state.to_s, note, until_ts.to_s])
|
|
1402
|
+
end
|
|
1403
|
+
|
|
1404
|
+
def self.list_global(topic)
|
|
1405
|
+
result = [Tep::PresenceEntry.new("", "", :human, "", -1, 0)]
|
|
1406
|
+
result.delete_at(0)
|
|
1407
|
+
if Tep::APP.presence_pg_enabled == 0
|
|
1408
|
+
return result
|
|
1409
|
+
end
|
|
1410
|
+
begin
|
|
1411
|
+
r = Tep::APP.presence_pg_conn.exec_params(
|
|
1412
|
+
"SELECT principal_id, kind, agent_id, fd, since_ts, " +
|
|
1413
|
+
" status_state, status_note, status_until " +
|
|
1414
|
+
"FROM tep_presence WHERE topic = $1 ORDER BY since_ts",
|
|
1415
|
+
[topic])
|
|
1416
|
+
rescue PG::Error
|
|
1417
|
+
return result
|
|
1418
|
+
end
|
|
1419
|
+
i = 0
|
|
1420
|
+
n = r.ntuples
|
|
1421
|
+
while i < n
|
|
1422
|
+
kind_sym = :human
|
|
1423
|
+
if r.getvalue(i, 1) == "agent_for"
|
|
1424
|
+
kind_sym = :agent_for
|
|
1425
|
+
end
|
|
1426
|
+
state_sym = :available
|
|
1427
|
+
sstr = r.getvalue(i, 5)
|
|
1428
|
+
if sstr == "busy"
|
|
1429
|
+
state_sym = :busy
|
|
1430
|
+
elsif sstr == "blocked"
|
|
1431
|
+
state_sym = :blocked
|
|
1432
|
+
end
|
|
1433
|
+
e = Tep::PresenceEntry.new(
|
|
1434
|
+
topic,
|
|
1435
|
+
r.getvalue(i, 0),
|
|
1436
|
+
kind_sym,
|
|
1437
|
+
r.getvalue(i, 2),
|
|
1438
|
+
r.getvalue(i, 3).to_i,
|
|
1439
|
+
r.getvalue(i, 4).to_i)
|
|
1440
|
+
e.status_state = state_sym
|
|
1441
|
+
e.status_note = r.getvalue(i, 6)
|
|
1442
|
+
e.status_until = r.getvalue(i, 7).to_i
|
|
1443
|
+
result.push(e)
|
|
1444
|
+
i += 1
|
|
1445
|
+
end
|
|
1446
|
+
r.clear
|
|
1447
|
+
result
|
|
1448
|
+
end
|
|
1449
|
+
|
|
1450
|
+
def self.count_global(topic)
|
|
1451
|
+
if Tep::APP.presence_pg_enabled == 0
|
|
1452
|
+
return 0
|
|
1453
|
+
end
|
|
1454
|
+
begin
|
|
1455
|
+
r = Tep::APP.presence_pg_conn.exec_params(
|
|
1456
|
+
"SELECT count(*) FROM tep_presence WHERE topic = $1",
|
|
1457
|
+
[topic])
|
|
1458
|
+
rescue PG::Error
|
|
1459
|
+
return 0
|
|
1460
|
+
end
|
|
1461
|
+
n = r.getvalue(0, 0).to_i
|
|
1462
|
+
r.clear
|
|
1463
|
+
n
|
|
1464
|
+
end
|
|
1465
|
+
|
|
1466
|
+
end
|
|
1467
|
+
end
|
|
1468
|
+
|
|
1469
|
+
# ===================================================================
|
|
1470
|
+
# Opt-in PG seeds (#216, relocated from lib/tep.rb). Pin parameter /
|
|
1471
|
+
# return C types for every PG-backed cmeth so a `require "tep/pg"`
|
|
1472
|
+
# app compiles cleanly even when it exercises only a subset.
|
|
1473
|
+
# PG::Connection.new("") returns a failed-conn instance (@pgh<0)
|
|
1474
|
+
# rather than raising, so all of this is safe at module load.
|
|
1475
|
+
# ===================================================================
|
|
1476
|
+
|
|
1477
|
+
# Broadcast PG-backend setters + cmeths. set_* via constant because
|
|
1478
|
+
# PG::Connection.new cannot run inside App#initialize (Tep::APP is
|
|
1479
|
+
# mid-construction). enable_pg_backend("","") connect-fails (-1).
|
|
1480
|
+
Tep::APP.set_broadcast_pg_enabled(0)
|
|
1481
|
+
Tep::APP.set_broadcast_pg_channel("")
|
|
1482
|
+
Tep::APP.set_broadcast_pg_conn(PG::Connection.new(""))
|
|
1483
|
+
Tep::Broadcast.enable_pg_backend("", "")
|
|
1484
|
+
Tep::Broadcast.poll_pg_once(0)
|
|
1485
|
+
Tep::Broadcast.disable_pg_backend
|
|
1486
|
+
Tep::Broadcast.encode_wire("", "")
|
|
1487
|
+
Tep::Broadcast.deliver_wire_local("0:")
|
|
1488
|
+
Tep::Broadcast.cross_worker_notify("_seed", "")
|
|
1489
|
+
|
|
1490
|
+
# Presence PG mirror cmeths. mirror_insert needs a PresenceEntry.
|
|
1491
|
+
_tep_pg_seed_entry = Tep::PresenceEntry.new("_seed", "_seed", :human, "", -1, 0)
|
|
1492
|
+
Tep::Presence.enable_pg_mirror("")
|
|
1493
|
+
Tep::Presence.schema_sql
|
|
1494
|
+
Tep::Presence.mirror_insert(_tep_pg_seed_entry)
|
|
1495
|
+
Tep::Presence.mirror_delete("_seed", -1)
|
|
1496
|
+
Tep::Presence.mirror_status("_seed", -1, :available, "", 0)
|
|
1497
|
+
Tep::Presence.list_global("_seed")
|
|
1498
|
+
Tep::Presence.count_global("_seed")
|
|
1499
|
+
Tep::Presence.worker_schema_sql
|
|
1500
|
+
Tep::Presence.heartbeat
|
|
1501
|
+
Tep::Presence.prune_stale_workers(90)
|
|
1502
|
+
Tep::Presence.disable_pg_mirror
|
|
1503
|
+
Tep::APP.set_presence_pg_enabled(0)
|
|
1504
|
+
Tep::APP.set_presence_pg_worker_id("")
|
|
1505
|
+
Tep::APP.set_presence_pg_conn(PG::Connection.new(""))
|
|
1506
|
+
|
|
1507
|
+
# PG::Connection / Result / Pool type-seeding.
|
|
1508
|
+
_tep_seed_pg_conn = PG::Connection.new("")
|
|
1509
|
+
_tep_seed_pg_conn.connected?
|
|
1510
|
+
_tep_seed_pg_conn.status
|
|
1511
|
+
_tep_seed_pg_conn.transaction_status
|
|
1512
|
+
_tep_seed_pg_conn.server_version
|
|
1513
|
+
_tep_seed_pg_conn.error_message
|
|
1514
|
+
_tep_seed_pg_conn.escape_string("")
|
|
1515
|
+
_tep_seed_pg_conn.escape_identifier("")
|
|
1516
|
+
_tep_seed_pg_conn.escape_literal("")
|
|
1517
|
+
_tep_seed_pg_conn.last_sqlstate = ""
|
|
1518
|
+
_tep_seed_pg_conn.last_error_message = ""
|
|
1519
|
+
_tep_seed_pg_conn.last_result_rh = -1
|
|
1520
|
+
# Async surface seed -- calling these on a failed-conn instance
|
|
1521
|
+
# is harmless (the C shim short-circuits on conn slot < 1).
|
|
1522
|
+
_tep_seed_pg_conn.async_exec("")
|
|
1523
|
+
_tep_seed_pg_seed_arr = [""]
|
|
1524
|
+
_tep_seed_pg_seed_arr.delete_at(0)
|
|
1525
|
+
_tep_seed_pg_conn.async_exec_params("", _tep_seed_pg_seed_arr)
|
|
1526
|
+
# Async connect cmeth. Returns -1 for empty conninfo from a
|
|
1527
|
+
# non-scheduled context (the shim's PQconnectStart-then-FAILED
|
|
1528
|
+
# path), which is type-equivalent to the success path.
|
|
1529
|
+
PG::Connection.async_connect("")
|
|
1530
|
+
# LISTEN / NOTIFY surface (Tep::Broadcast PG backend lands here).
|
|
1531
|
+
_tep_seed_pg_conn.listen("_seed")
|
|
1532
|
+
_tep_seed_pg_conn.unlisten("_seed")
|
|
1533
|
+
_tep_seed_pg_conn.notify("_seed", "")
|
|
1534
|
+
_tep_seed_pg_conn.poll_notification(0)
|
|
1535
|
+
_tep_seed_pg_conn.last_notify_channel
|
|
1536
|
+
_tep_seed_pg_conn.last_notify_payload
|
|
1537
|
+
_tep_seed_pg_res = PG::Result.new(-1)
|
|
1538
|
+
_tep_seed_pg_res.ntuples
|
|
1539
|
+
_tep_seed_pg_res.nfields
|
|
1540
|
+
_tep_seed_pg_res.fname(0)
|
|
1541
|
+
_tep_seed_pg_res.fnumber("")
|
|
1542
|
+
_tep_seed_pg_res.ftype(0)
|
|
1543
|
+
_tep_seed_pg_res.fformat(0)
|
|
1544
|
+
_tep_seed_pg_res.fmod(0)
|
|
1545
|
+
_tep_seed_pg_res.getvalue(0, 0)
|
|
1546
|
+
_tep_seed_pg_res.getisnull(0, 0)
|
|
1547
|
+
_tep_seed_pg_res.getlength(0, 0)
|
|
1548
|
+
_tep_seed_pg_res.value(0, 0)
|
|
1549
|
+
_tep_seed_pg_res.error_field(67)
|
|
1550
|
+
_tep_seed_pg_res.cmd_status
|
|
1551
|
+
_tep_seed_pg_res.cmd_tuples
|
|
1552
|
+
_tep_seed_pg_res.error_message
|
|
1553
|
+
_tep_seed_pg_res.sql_state
|
|
1554
|
+
_tep_seed_pg_res.fields
|
|
1555
|
+
_tep_seed_pg_res.values
|
|
1556
|
+
_tep_seed_pg_res.column_values(0)
|
|
1557
|
+
_tep_seed_pg_res.clear
|
|
1558
|
+
_tep_seed_pg_conn.close
|
|
1559
|
+
# Pool seed -- size 0 so we don't try to open real conns at load.
|
|
1560
|
+
_tep_seed_pg_pool = PG::Pool.new("", 0)
|
|
1561
|
+
_tep_seed_pg_pool.healthy?
|
|
1562
|
+
_tep_seed_pg_pool.available
|
|
1563
|
+
_tep_seed_pg_pool.size
|
|
1564
|
+
_tep_seed_pg_pool.set_checkout_timeout_ms(0)
|
|
1565
|
+
_tep_seed_pg_pool.close_all
|
|
1566
|
+
# NB: don't checkout/checkin against the size-0 seed pool; it'd
|
|
1567
|
+
# spin until timeout. The seed has @free.length=0 forever.
|