• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

NodeBB / NodeBB / 23691623234

28 Mar 2026 06:32PM UTC coverage: 85.405% (-0.006%) from 85.411%
23691623234

push

github

barisusakli
fix: try upsert type if it fails

13478 of 18498 branches covered (72.86%)

5 of 8 new or added lines in 1 file covered. (62.5%)

28474 of 33340 relevant lines covered (85.4%)

3332.97 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

80.0
/src/database/postgres/helpers.js
1
'use strict';
2

3
const helpers = module.exports;
8✔
4

5
helpers.valueToString = function (value) {
8✔
6
        return String(value);
195,024✔
7
};
8

9
helpers.removeDuplicateValues = function (values, ...others) {
8✔
10
        for (let i = 0; i < values.length; i++) {
2,421✔
11
                if (values.lastIndexOf(values[i]) !== i) {
106,109✔
12
                        values.splice(i, 1);
1✔
13
                        for (let j = 0; j < others.length; j++) {
1✔
14
                                others[j].splice(i, 1);
1✔
15
                        }
16
                        i -= 1;
1✔
17
                }
18
        }
19
};
20

21
helpers.ensureLegacyObjectType = async function (db, key, type) {
8✔
22
        await db.query({
23,785✔
23
                name: 'ensureLegacyObjectTypeBefore',
24
                text: `
25
DELETE FROM "legacy_object"
26
 WHERE "expireAt" IS NOT NULL
27
   AND "expireAt" <= CURRENT_TIMESTAMP`,
28
        });
29

30
        const res = await tryUpsert(db, {
23,785✔
31
                name: 'ensureLegacyObjectType_upsert',
32
                text: `
33
                        INSERT INTO "legacy_object" ("_key", "type")
34
                        VALUES ($1::TEXT, $2::TEXT::LEGACY_OBJECT_TYPE)
35
                        ON CONFLICT ("_key")
36
                        DO UPDATE SET "type" = "legacy_object"."type"
37
                        RETURNING "type"`,
38
                values: [key, type],
39
        });
40

41
        if (res.rows[0].type !== type) {
23,785!
42
                throw new Error(`database: cannot insert ${JSON.stringify(key)} as ${type} because it already exists as ${res.rows[0].type}`);
×
43
        }
44
};
45

46
helpers.ensureLegacyObjectsType = async function (db, keys, type) {
8✔
47
        keys = [...new Set(keys)];
6,932✔
48

49
        await db.query({
6,932✔
50
                name: 'ensureLegacyObjectTypeBefore',
51
                text: `
52
DELETE FROM "legacy_object"
53
 WHERE "expireAt" IS NOT NULL
54
   AND "expireAt" <= CURRENT_TIMESTAMP`,
55
        });
56

57
        const res = await tryUpsert(db, {
6,932✔
58
                name: 'ensureLegacyObjectsType_upsert',
59
                text: `
60
INSERT INTO "legacy_object" ("_key", "type")
61
SELECT k, $2::TEXT::LEGACY_OBJECT_TYPE
62
FROM UNNEST($1::TEXT[]) k
63
        ON CONFLICT ("_key")
64
        DO UPDATE SET "type" = "legacy_object"."type"
65
        RETURNING "_key", "type"`,
66
                values: [keys, type],
67
        });
68

69
        const invalid = res.rows.filter(r => r.type !== type);
32,233✔
70

71
        if (invalid.length) {
6,932!
72
                const parts = invalid.map(r => `${JSON.stringify(r._key)} is ${r.type}`);
×
73
                throw new Error(`database: cannot insert multiple objects as ${type} because they already exist: ${parts.join(', ')}`);
×
74
        }
75
};
76

77
async function tryUpsert(db, queryConfig) {
78
        let res;
79
        try {
30,717✔
80
                res = await db.query(queryConfig);
30,717✔
81
        } catch (err) {
NEW
82
                if (err.code === '23505') { // retry if failed due to error: unique constraint
×
NEW
83
                        res = await db.query(queryConfig);
×
84
                } else {
NEW
85
                        throw err;
×
86
                }
87
        }
88
        return res;
30,717✔
89
}
90

91
helpers.noop = function () {};
8✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc