@opengis/fastify-table 2.0.111 → 2.0.112

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.
@@ -1 +1 @@
1
- {"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../../../../server/routes/file/controllers/export.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AA+BzD;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,wBAA8B,WAAW,CACvC,EACE,EAAqB,EACrB,OAAO,EACP,IAAI,EACJ,OAAO,EAAE,QAAQ,EACjB,GAAG,EACH,KAAU,EACV,IAAkB,EAClB,QAAQ,EACR,UAAU,GACX,EAAE;IACD,EAAE,EAAE,UAAU,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,GAAG,CAAC;IACV,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,EACD,KAAK,EAAE,YAAY,gBAyXpB"}
1
+ {"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../../../../server/routes/file/controllers/export.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAgCzD;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,wBAA8B,WAAW,CACvC,EACE,EAAqB,EACrB,OAAO,EACP,IAAI,EACJ,OAAO,EAAE,QAAQ,EACjB,GAAG,EACH,KAAU,EACV,IAAkB,EAClB,QAAQ,EACR,UAAU,GACX,EAAE;IACD,EAAE,EAAE,UAAU,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,GAAG,CAAC;IACV,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,EACD,KAAK,EAAE,YAAY,gBAsYpB"}
@@ -20,6 +20,7 @@ import jsonToXls from "./utils/jsonToXls.js";
20
20
  import jsonToCsv from "./utils/jsonToCsv.js";
21
21
  import formatResult from "./utils/formatResult.js";
22
22
  import jsonlToJsonFile from "./utils/jsonlToJsonFile.js";
23
+ import pubsub from "./utils/pubsub.js";
23
24
  const startStreamWithTotal = 10000;
24
25
  const rootDir = getFolder(config, "local");
25
26
  /**
@@ -84,12 +85,6 @@ export default async function exportTable({ pg = pgClients.client, headers, user
84
85
  reply,
85
86
  });
86
87
  }
87
- // delete old file, prevent append
88
- if (cacheFile && (nocache || config.disableCache)) {
89
- await rm(filePath);
90
- }
91
- // create directory if not exists
92
- await mkdir(path.dirname(filePath), { recursive: true });
93
88
  const loadTable = await getTemplate("table", table);
94
89
  const meta = await getMeta({ pg, table: loadTable?.table || table });
95
90
  const viewSql = await getTemplate("view", loadTable?.table || table);
@@ -165,12 +160,22 @@ export default async function exportTable({ pg = pgClients.client, headers, user
165
160
  .split(".")
166
161
  .pop()}` // check for json data
167
162
  : el.name);
168
- const send = ((!slice && +filtered > startStreamWithTotal) || stream) &&
169
- process.env.NODE_ENV !== "test"
170
- ? eventStream(reply)
171
- : process.env.NODE_ENV === "test"
172
- ? console.log
173
- : () => { };
163
+ const isStream = ((!slice && +filtered > startStreamWithTotal) || stream) &&
164
+ process.env.NODE_ENV !== "test" &&
165
+ !process.env.VITEST;
166
+ const sendOriginal = isStream ? eventStream(reply) : () => { };
167
+ const redisKey = `exportTable:${fileName}`;
168
+ const send = isStream
169
+ ? await pubsub(redisKey, (msg, finishStream = false) => {
170
+ sendOriginal(msg, finishStream);
171
+ }, query.reload && user?.user_type?.includes?.("admin"))
172
+ : () => { };
173
+ // delete old file, prevent append
174
+ if (cacheFile && (nocache || config.disableCache)) {
175
+ await rm(filePath);
176
+ }
177
+ // create directory if not exists
178
+ await mkdir(path.dirname(filePath), { recursive: true });
174
179
  // export xlsx / csv / json
175
180
  const source = loadTable?.title || loadTable?.ua || table || sourceName;
176
181
  const interval = setInterval(async () => {
@@ -248,7 +253,8 @@ export default async function exportTable({ pg = pgClients.client, headers, user
248
253
  await jsonlToJsonFile(filePathJSON.replace(/.json$/, ".jsonl"));
249
254
  clearInterval(interval);
250
255
  if (res.error) {
251
- send(res.error, 1);
256
+ send("finish");
257
+ sendOriginal(res.error, 1);
252
258
  return reply.status(500).send(res.error);
253
259
  }
254
260
  logger.file("export/table", {
@@ -302,7 +308,8 @@ export default async function exportTable({ pg = pgClients.client, headers, user
302
308
  if (resp.error) {
303
309
  return reply.status(resp.status || 500).send(resp.error);
304
310
  }
305
- send("Файл успішно сформовано. Натистіть кнопку ще раз для завантаження даних", 1);
311
+ send("finish");
312
+ sendOriginal("Файл успішно сформовано. Натистіть кнопку ще раз для завантаження даних", 1);
306
313
  return formatResult({
307
314
  filePath,
308
315
  formatAnswer,
@@ -0,0 +1,2 @@
1
+ export default function subscribe(code: string, cb: any, reload: any): Promise<any>;
2
+ //# sourceMappingURL=pubsub.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pubsub.d.ts","sourceRoot":"","sources":["../../../../../../server/routes/file/controllers/utils/pubsub.ts"],"names":[],"mappings":"AAkDA,wBAA8B,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,gBA2EzE"}
@@ -0,0 +1,112 @@
1
+ const keyCacheSubscribe = "emit_cache";
2
+ const listenter = {}; // callback send message listener
3
+ const promise = {}; // promise await for subscribe
4
+ const resolve = {}; // resolve
5
+ const publish = {}; // publish
6
+ import config from "../../../../../config.js";
7
+ import getRedis from "../../../../plugins/redis/funcs/getRedis.js";
8
+ // getRedisPublisher
9
+ function getRedisPublisher() {
10
+ const rst = getRedis({
11
+ name: "rst",
12
+ ...(config.redis || {}),
13
+ });
14
+ const subscriber = getRedis({
15
+ name: "sub",
16
+ ...(config.redis || {}),
17
+ });
18
+ subscriber.unsubscribe(keyCacheSubscribe);
19
+ subscriber.subscribe(keyCacheSubscribe, () => { });
20
+ subscriber.on("message", async (channel, text) => {
21
+ const [code, msg] = text.split("|||");
22
+ if (msg === "finish" && resolve[code]) {
23
+ resolve[code]();
24
+ resolve[code] = null;
25
+ }
26
+ listenter[code].forEach((cb1, i) => {
27
+ cb1(`${msg} - ${i}`);
28
+ });
29
+ });
30
+ return rst;
31
+ }
32
+ // native publisher
33
+ function getPublisher() {
34
+ const rst = {
35
+ publish(key, text) {
36
+ const [code, msg] = text.split("|||");
37
+ listenter[code]?.forEach((cb1, i) => {
38
+ cb1?.(`${msg} - ${i}`);
39
+ });
40
+ },
41
+ };
42
+ return rst;
43
+ }
44
+ // !!! work non cluster mode for cluster subscribe redis
45
+ export default async function subscribe(code, cb, reload) {
46
+ try {
47
+ const rclient = getRedis();
48
+ const { isRedis, timeout = 150 } = config?.redis?.pubsub || {}; // test!
49
+ const publisher = isRedis ? getRedisPublisher() : getPublisher();
50
+ const keyCacheCode = `${keyCacheSubscribe}:${code}`;
51
+ // check code is run
52
+ const isNotRun = await rclient.setnx(keyCacheCode, 1);
53
+ const ttl = await rclient.ttl(keyCacheCode);
54
+ // if Run
55
+ if (!isNotRun && !reload && ttl > 0) {
56
+ // add listener
57
+ cb(`==== run as slave ttl: ${ttl}==== `);
58
+ const alldata = await rclient.lrange(keyCacheCode + ":list", 0, -1);
59
+ alldata.forEach((el) => {
60
+ cb(el);
61
+ });
62
+ // for redis
63
+ if (!listenter[code]) {
64
+ listenter[code] = [];
65
+ promise[code] = new Promise((rsv) => {
66
+ resolve[code] = rsv;
67
+ });
68
+ }
69
+ // check master finish
70
+ const interval = setInterval(async () => {
71
+ const ttl1 = await rclient.ttl(keyCacheCode);
72
+ if (ttl1 < 0) {
73
+ clearInterval(interval);
74
+ cb(`finish master timeout ${timeout}`, 1);
75
+ }
76
+ }, 5000);
77
+ listenter[code].push(cb);
78
+ return promise[code];
79
+ }
80
+ await rclient.expire(keyCacheCode, timeout);
81
+ // if not run
82
+ // create return promise
83
+ promise[code] = new Promise((rsv) => {
84
+ resolve[code] = rsv;
85
+ });
86
+ listenter[code] = [cb];
87
+ // listenter[code].push(cb);
88
+ // create publish function
89
+ publish[code] = (msg) => {
90
+ rclient.rpush(keyCacheCode + ":list", msg);
91
+ rclient.expire(keyCacheCode, timeout);
92
+ // send message to all listener
93
+ publisher.publish(keyCacheSubscribe, `${code}|||${msg}`); // redis
94
+ // finish and clear
95
+ if (msg === "finish") {
96
+ // clear code to run again
97
+ rclient.del(keyCacheCode);
98
+ rclient.del(keyCacheCode + ":list");
99
+ // resolve promise
100
+ resolve[code]();
101
+ // clear
102
+ resolve[code] = null;
103
+ promise[code] = null;
104
+ listenter[code] = [];
105
+ }
106
+ };
107
+ return publish[code];
108
+ }
109
+ catch (err) {
110
+ console.error(err.toString());
111
+ }
112
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengis/fastify-table",
3
- "version": "2.0.111",
3
+ "version": "2.0.112",
4
4
  "type": "module",
5
5
  "description": "core-plugins",
6
6
  "keywords": [