@playwright-orchestrator/pg 1.0.5 → 1.1.0
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/dist/create-args.d.ts +3 -0
- package/dist/index.d.ts +1 -2
- package/dist/index.js +21 -5
- package/dist/package.json +1 -1
- package/dist/postgresql-adapter.d.ts +1 -1
- package/dist/postgresql-adapter.js +62 -29
- package/package.json +1 -1
package/dist/create-args.d.ts
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Command } from '@commander-js/extra-typings';
|
|
2
2
|
import { CreateArgs } from './create-args';
|
|
3
3
|
import { PostgreSQLAdapter } from './postgresql-adapter';
|
|
4
|
-
export
|
|
5
|
-
export declare function factory(args: CreateArgs): PostgreSQLAdapter;
|
|
4
|
+
export declare function factory(args: CreateArgs): Promise<PostgreSQLAdapter>;
|
|
6
5
|
export declare function createOptions(command: Command): void;
|
|
7
6
|
export declare const description = "PostgreSQL storage adapter";
|
package/dist/index.js
CHANGED
|
@@ -1,16 +1,32 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.description =
|
|
3
|
+
exports.description = void 0;
|
|
4
4
|
exports.factory = factory;
|
|
5
5
|
exports.createOptions = createOptions;
|
|
6
|
+
const extra_typings_1 = require("@commander-js/extra-typings");
|
|
6
7
|
const postgresql_adapter_1 = require("./postgresql-adapter");
|
|
7
|
-
|
|
8
|
-
function factory(args) {
|
|
8
|
+
const promises_1 = require("node:fs/promises");
|
|
9
|
+
async function factory(args) {
|
|
10
|
+
const { sslCa, sslCert, sslKey } = args;
|
|
11
|
+
if (sslCa) {
|
|
12
|
+
args.sslCa = await (0, promises_1.readFile)(sslCa);
|
|
13
|
+
}
|
|
14
|
+
if (sslCert && sslKey) {
|
|
15
|
+
args.sslCert = await (0, promises_1.readFile)(sslCert);
|
|
16
|
+
args.sslKey = await (0, promises_1.readFile)(sslKey);
|
|
17
|
+
}
|
|
9
18
|
return new postgresql_adapter_1.PostgreSQLAdapter(args);
|
|
10
19
|
}
|
|
11
20
|
function createOptions(command) {
|
|
12
21
|
command
|
|
13
|
-
.
|
|
14
|
-
.
|
|
22
|
+
.addOption(new extra_typings_1.Option('--table-name-prefix <string>', 'Tables name prefix')
|
|
23
|
+
.default('playwright_orchestrator')
|
|
24
|
+
.env('TABLE_NAME_PREFIX'))
|
|
25
|
+
.addOption(new extra_typings_1.Option('--ssl-ca <string>', 'SSL CA file').env('SSL_CA'))
|
|
26
|
+
.addOption(new extra_typings_1.Option('--ssl-cert <string>', 'SSL certificate file').env('SSL_CERT'))
|
|
27
|
+
.addOption(new extra_typings_1.Option('--ssl-key <string>', 'SSL key file').env('SSL_KEY'))
|
|
28
|
+
.addOption(new extra_typings_1.Option('--connection-string <string>', 'Connection string')
|
|
29
|
+
.makeOptionMandatory()
|
|
30
|
+
.env('CONNECTION_STRING'));
|
|
15
31
|
}
|
|
16
32
|
exports.description = 'PostgreSQL storage adapter';
|
package/dist/package.json
CHANGED
|
@@ -4,7 +4,7 @@ export declare class PostgreSQLAdapter extends Adapter {
|
|
|
4
4
|
private readonly configTable;
|
|
5
5
|
private readonly testsTable;
|
|
6
6
|
private readonly pool;
|
|
7
|
-
constructor({ connectionString, tableNamePrefix }: CreateArgs);
|
|
7
|
+
constructor({ connectionString, tableNamePrefix, sslCa, sslCert, sslKey }: CreateArgs);
|
|
8
8
|
getNextTest(runId: string, config: TestRunConfig): Promise<TestItem | undefined>;
|
|
9
9
|
finishTest(runId: string, test: TestItem): Promise<void>;
|
|
10
10
|
failTest(runId: string, test: TestItem): Promise<void>;
|
|
@@ -4,9 +4,18 @@ exports.PostgreSQLAdapter = void 0;
|
|
|
4
4
|
const core_1 = require("@playwright-orchestrator/core");
|
|
5
5
|
const pg_1 = require("pg");
|
|
6
6
|
class PostgreSQLAdapter extends core_1.Adapter {
|
|
7
|
-
constructor({ connectionString, tableNamePrefix }) {
|
|
7
|
+
constructor({ connectionString, tableNamePrefix, sslCa, sslCert, sslKey }) {
|
|
8
8
|
super();
|
|
9
|
-
|
|
9
|
+
const config = { connectionString };
|
|
10
|
+
config.ssl = sslCa || sslCert || sslKey ? {} : undefined;
|
|
11
|
+
if (sslCa) {
|
|
12
|
+
config.ssl.ca = sslCa;
|
|
13
|
+
}
|
|
14
|
+
if (sslCert && sslKey) {
|
|
15
|
+
config.ssl.cert = sslCert;
|
|
16
|
+
config.ssl.key = sslKey;
|
|
17
|
+
}
|
|
18
|
+
this.pool = new pg_1.Pool(config);
|
|
10
19
|
this.configTable = (0, pg_1.escapeIdentifier)(`${tableNamePrefix}_test_runs`);
|
|
11
20
|
this.testsTable = (0, pg_1.escapeIdentifier)(`${tableNamePrefix}_tests`);
|
|
12
21
|
}
|
|
@@ -28,7 +37,7 @@ class PostgreSQLAdapter extends core_1.Adapter {
|
|
|
28
37
|
FROM next_test
|
|
29
38
|
WHERE t.run_id = $1 AND t.order_num = next_test.order_num
|
|
30
39
|
RETURNING *`,
|
|
31
|
-
values: [runId, core_1.TestStatus.Ready, core_1.TestStatus.
|
|
40
|
+
values: [runId, core_1.TestStatus.Ready, core_1.TestStatus.Ongoing],
|
|
32
41
|
});
|
|
33
42
|
await client.query('COMMIT');
|
|
34
43
|
if (result.rowCount === 0)
|
|
@@ -103,35 +112,59 @@ class PostgreSQLAdapter extends core_1.Adapter {
|
|
|
103
112
|
updated TIMESTAMP NOT NULL DEFAULT NOW(),
|
|
104
113
|
PRIMARY KEY (run_id, order_num),
|
|
105
114
|
FOREIGN KEY (run_id) REFERENCES ${this.configTable}(id)
|
|
106
|
-
)
|
|
115
|
+
);
|
|
116
|
+
CREATE INDEX IF NOT EXISTS status_idx ON ${this.testsTable}(status);`);
|
|
107
117
|
}
|
|
108
118
|
async startShard(runId) {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
119
|
+
const client = await this.pool.connect();
|
|
120
|
+
try {
|
|
121
|
+
await client.query('BEGIN');
|
|
122
|
+
let result = await client.query({
|
|
123
|
+
text: `
|
|
124
|
+
SELECT *
|
|
125
|
+
FROM ${this.configTable}
|
|
126
|
+
WHERE id = $1
|
|
127
|
+
FOR UPDATE`,
|
|
128
|
+
values: [runId],
|
|
129
|
+
});
|
|
130
|
+
if (result.rowCount === 0) {
|
|
131
|
+
throw new Error(`Run ${runId} not found`);
|
|
132
|
+
}
|
|
133
|
+
const { updated: updatedBefore, status: statusBefore } = result.rows[0];
|
|
134
|
+
if (statusBefore === core_1.RunStatus.Created || statusBefore === core_1.RunStatus.Finished) {
|
|
135
|
+
await client.query({
|
|
136
|
+
text: `
|
|
137
|
+
UPDATE ${this.testsTable}
|
|
138
|
+
SET updated = NOW(), status = $3
|
|
139
|
+
WHERE run_id = $1 AND status = $2 AND updated <= $4;`,
|
|
140
|
+
values: [runId, core_1.TestStatus.Failed, core_1.TestStatus.Ready, updatedBefore],
|
|
141
|
+
});
|
|
142
|
+
// using str interpolation for case statement to avoid casting ints to strings
|
|
143
|
+
result = await client.query({
|
|
144
|
+
text: `
|
|
145
|
+
UPDATE ${this.configTable}
|
|
146
|
+
SET status = (CASE
|
|
147
|
+
WHEN status = $2 THEN ${core_1.RunStatus.Run}
|
|
148
|
+
ELSE ${core_1.RunStatus.RepeatRun}
|
|
149
|
+
END),
|
|
150
|
+
updated = NOW()
|
|
151
|
+
WHERE id = $1
|
|
152
|
+
RETURNING *;`,
|
|
153
|
+
values: [runId, core_1.RunStatus.Created],
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
await client.query('COMMIT');
|
|
157
|
+
const { updated, status, config } = result.rows[0];
|
|
158
|
+
const mappedConfig = { ...config, updated: updated.getTime(), status };
|
|
159
|
+
return mappedConfig;
|
|
160
|
+
}
|
|
161
|
+
catch (e) {
|
|
162
|
+
await client.query('ROLLBACK');
|
|
163
|
+
throw e;
|
|
164
|
+
}
|
|
165
|
+
finally {
|
|
166
|
+
client.release();
|
|
124
167
|
}
|
|
125
|
-
const { updated, status, config } = result.rows[0];
|
|
126
|
-
const mappedConfig = { ...config, updated: updated.getTime(), status };
|
|
127
|
-
await this.pool.query({
|
|
128
|
-
name: 'update-tests-status',
|
|
129
|
-
text: `UPDATE ${this.testsTable}
|
|
130
|
-
SET status = $1
|
|
131
|
-
WHERE run_id = $2 AND status = $3 AND updated < $4`,
|
|
132
|
-
values: [core_1.TestStatus.Ready, runId, core_1.TestStatus.Failed, updated],
|
|
133
|
-
});
|
|
134
|
-
return mappedConfig;
|
|
135
168
|
}
|
|
136
169
|
async finishShard(runId) {
|
|
137
170
|
// set 'updated' field to current time as test run exhausted all tests
|