@haathie/pgmb 0.2.10 → 0.2.12
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.
- package/README.md +4 -1
- package/lib/types.d.ts +13 -0
- package/lib/webhook-handler.d.ts +1 -1
- package/lib/webhook-handler.js +16 -2
- package/package.json +1 -1
- package/sql/pgmb-0.2.0-0.2.8.sql +7 -5
- package/sql/pgmb.sql +7 -5
package/README.md
CHANGED
|
@@ -422,7 +422,10 @@ const pgmb = new PgmbClient({
|
|
|
422
422
|
headers: {
|
|
423
423
|
// add a custom user-agent header
|
|
424
424
|
'user-agent': 'my-service-client/1.0.0'
|
|
425
|
-
}
|
|
425
|
+
},
|
|
426
|
+
// if payload is larger than 1KB, will be sent as a gzipped body
|
|
427
|
+
// with content-encoding: gzip header
|
|
428
|
+
minCompressSizeBytes: 1024,
|
|
426
429
|
},
|
|
427
430
|
// this function is called to obtain webhook URLs
|
|
428
431
|
// for a given set of PGMB subscription IDs. These
|
package/lib/types.d.ts
CHANGED
|
@@ -34,6 +34,19 @@ export type PgmbWebhookOpts<T extends IEventData> = {
|
|
|
34
34
|
splitBy?: ISplitFn<T>;
|
|
35
35
|
jsonifier?: JSONifier;
|
|
36
36
|
serialiseEvent?(ev: IReadEvent, logger: Logger): SerialisedEvent;
|
|
37
|
+
/**
|
|
38
|
+
* Minimum size in bytes for the payload to be compressed.
|
|
39
|
+
* @default 1024
|
|
40
|
+
*/
|
|
41
|
+
minCompressSizeBytes?: number;
|
|
42
|
+
/**
|
|
43
|
+
* Compress the webhook payload before sending.
|
|
44
|
+
* By default, uses gzip compression via the `zlib` library.
|
|
45
|
+
*/
|
|
46
|
+
compress?(data: Uint8Array | string): Promise<{
|
|
47
|
+
data: Uint8Array | string;
|
|
48
|
+
contentEncoding: string;
|
|
49
|
+
}>;
|
|
37
50
|
};
|
|
38
51
|
export interface IEventData {
|
|
39
52
|
topic: string;
|
package/lib/webhook-handler.d.ts
CHANGED
|
@@ -3,4 +3,4 @@ import type { IEventData, IEventHandler, PgmbWebhookOpts } from './types.ts';
|
|
|
3
3
|
* Create a handler that sends events to a webhook URL via HTTP POST.
|
|
4
4
|
* @param url Where to send the webhook requests
|
|
5
5
|
*/
|
|
6
|
-
export declare function createWebhookHandler<T extends IEventData>({ timeoutMs, headers, retryOpts, jsonifier, serialiseEvent }: Partial<PgmbWebhookOpts<T>>): IEventHandler;
|
|
6
|
+
export declare function createWebhookHandler<T extends IEventData>({ timeoutMs, headers, retryOpts, jsonifier, serialiseEvent, minCompressSizeBytes, compress }: Partial<PgmbWebhookOpts<T>>): IEventHandler;
|
package/lib/webhook-handler.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import assert from 'node:assert';
|
|
2
2
|
import { createHash } from 'node:crypto';
|
|
3
|
+
import { promisify } from 'node:util';
|
|
4
|
+
import { gzip } from 'node:zlib';
|
|
3
5
|
import { createRetryHandler } from "./retry-handler.js";
|
|
6
|
+
import { getEnvNumber } from "./utils.js";
|
|
7
|
+
const gzipPromise = promisify(gzip);
|
|
4
8
|
/**
|
|
5
9
|
* Create a handler that sends events to a webhook URL via HTTP POST.
|
|
6
10
|
* @param url Where to send the webhook requests
|
|
@@ -8,7 +12,7 @@ import { createRetryHandler } from "./retry-handler.js";
|
|
|
8
12
|
export function createWebhookHandler({ timeoutMs = 5_000, headers, retryOpts = {
|
|
9
13
|
// retry after 5 minutes, then after 30 minutes
|
|
10
14
|
retriesS: [5 * 60, 30 * 60]
|
|
11
|
-
}, jsonifier = JSON, serialiseEvent = createSimpleSerialiser(jsonifier) }) {
|
|
15
|
+
}, jsonifier = JSON, serialiseEvent = createSimpleSerialiser(jsonifier), minCompressSizeBytes = getEnvNumber('PGMB_WEBHOOK_MIN_COMPRESS_SIZE_BYTES', 1024), compress = gzipCompress }) {
|
|
12
16
|
const handler = async (ev, { logger, extra }) => {
|
|
13
17
|
assert(typeof extra === 'object'
|
|
14
18
|
&& extra !== null
|
|
@@ -19,14 +23,18 @@ export function createWebhookHandler({ timeoutMs = 5_000, headers, retryOpts = {
|
|
|
19
23
|
const idempotencyKey = getIdempotencyKeyHeader(ev);
|
|
20
24
|
logger = logger.child({ idempotencyKey });
|
|
21
25
|
const { body, contentType } = serialiseEvent(ev, logger);
|
|
26
|
+
const { data: compBody, contentEncoding } = body.length >= minCompressSizeBytes
|
|
27
|
+
? await compress(body)
|
|
28
|
+
: { data: body };
|
|
22
29
|
const { status, statusText, body: res } = await fetch(url, {
|
|
23
30
|
method: 'POST',
|
|
24
31
|
headers: {
|
|
25
32
|
'content-type': contentType,
|
|
26
33
|
'idempotency-key': idempotencyKey,
|
|
34
|
+
...(contentEncoding ? { 'content-encoding': contentEncoding } : {}),
|
|
27
35
|
...headers
|
|
28
36
|
},
|
|
29
|
-
body,
|
|
37
|
+
body: compBody,
|
|
30
38
|
redirect: 'manual',
|
|
31
39
|
signal: AbortSignal.timeout(timeoutMs)
|
|
32
40
|
});
|
|
@@ -63,3 +71,9 @@ function createSimpleSerialiser(jsonifier) {
|
|
|
63
71
|
contentType: 'application/json'
|
|
64
72
|
});
|
|
65
73
|
}
|
|
74
|
+
async function gzipCompress(data) {
|
|
75
|
+
return {
|
|
76
|
+
data: await gzipPromise(data),
|
|
77
|
+
contentEncoding: 'gzip'
|
|
78
|
+
};
|
|
79
|
+
}
|
package/package.json
CHANGED
package/sql/pgmb-0.2.0-0.2.8.sql
CHANGED
|
@@ -64,11 +64,13 @@ EXECUTE FUNCTION manage_cron_jobs_trigger_fn();
|
|
|
64
64
|
DO $$
|
|
65
65
|
BEGIN
|
|
66
66
|
IF (
|
|
67
|
-
SELECT
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
67
|
+
SELECT true
|
|
68
|
+
FROM pg_available_extensions
|
|
69
|
+
WHERE name = 'pg_cron'
|
|
70
|
+
) AND (
|
|
71
|
+
-- ensure the current database is where pg_cron can be installed
|
|
72
|
+
current_database()
|
|
73
|
+
= coalesce(current_setting('cron.database_name', true), 'postgres')
|
|
72
74
|
) THEN
|
|
73
75
|
CREATE EXTENSION IF NOT EXISTS pg_cron;
|
|
74
76
|
INSERT INTO config(id, value) VALUES ('use_pg_cron', 'true');
|
package/sql/pgmb.sql
CHANGED
|
@@ -903,11 +903,13 @@ EXECUTE FUNCTION manage_cron_jobs_trigger_fn();
|
|
|
903
903
|
DO $$
|
|
904
904
|
BEGIN
|
|
905
905
|
IF (
|
|
906
|
-
SELECT
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
906
|
+
SELECT true
|
|
907
|
+
FROM pg_available_extensions
|
|
908
|
+
WHERE name = 'pg_cron'
|
|
909
|
+
) AND (
|
|
910
|
+
-- ensure the current database is where pg_cron can be installed
|
|
911
|
+
current_database()
|
|
912
|
+
= coalesce(current_setting('cron.database_name', true), 'postgres')
|
|
911
913
|
) THEN
|
|
912
914
|
CREATE EXTENSION IF NOT EXISTS pg_cron;
|
|
913
915
|
INSERT INTO config(id, value) VALUES ('use_pg_cron', 'true');
|