|
| 1 | +import { delay, mapEntries } from '@seedcompany/common'; |
| 2 | +import { $, Client } from 'edgedb'; |
| 3 | +import { KNOWN_TYPENAMES } from 'edgedb/dist/codecs/consts.js'; |
| 4 | +import LRU from 'edgedb/dist/primitives/lru.js'; |
| 5 | +import { retry } from '~/common/retry'; |
| 6 | +import { ScalarCodecClass } from './type.util'; |
| 7 | + |
| 8 | +export const registerCustomScalarCodecs = async ( |
| 9 | + client: Client, |
| 10 | + codecs: readonly ScalarCodecClass[], |
| 11 | +) => { |
| 12 | + async function registerWithServerSchema() { |
| 13 | + const introspected = await $.introspect.scalars(client); |
| 14 | + const scalarIdsByName = mapEntries(introspected, ([_, scalar]) => [ |
| 15 | + scalar.name, |
| 16 | + scalar.id.replaceAll('-', ''), |
| 17 | + ]).asMap; |
| 18 | + register(client, codecs, scalarIdsByName); |
| 19 | + } |
| 20 | + |
| 21 | + const connectedFast = await Promise.race([ |
| 22 | + client.ensureConnected(), |
| 23 | + delay({ seconds: 2 }), // don't wait full 30 seconds with retries |
| 24 | + ]); |
| 25 | + // If connection was established fast, register with schema info, and wait for completion |
| 26 | + if (connectedFast) { |
| 27 | + await registerWithServerSchema(); |
| 28 | + } else { |
| 29 | + // Otherwise, register statically known codecs immediately |
| 30 | + register(client, codecs); |
| 31 | + // And then keep trying to connect in the background, and register on successful connection. |
| 32 | + void retry( |
| 33 | + async () => { |
| 34 | + if (client.isClosed()) { |
| 35 | + return; |
| 36 | + } |
| 37 | + await client.ensureConnected(); |
| 38 | + await registerWithServerSchema(); |
| 39 | + }, |
| 40 | + { |
| 41 | + forever: true, |
| 42 | + unref: true, |
| 43 | + maxTimeout: { seconds: 10 }, |
| 44 | + }, |
| 45 | + ); |
| 46 | + } |
| 47 | +}; |
| 48 | + |
| 49 | +const register = ( |
| 50 | + client: Client, |
| 51 | + scalarCodecs: readonly ScalarCodecClass[], |
| 52 | + scalarIdsByName?: ReadonlyMap<string, string>, |
| 53 | +) => { |
| 54 | + const registry = (client as any).pool._codecsRegistry; |
| 55 | + const codecs: LRU<string, InstanceType<ScalarCodecClass>> = registry.codecs; |
| 56 | + |
| 57 | + for (const scalarCodec of scalarCodecs) { |
| 58 | + const typeName = `${scalarCodec.info.module}::${scalarCodec.info.type}`; |
| 59 | + const uuid = |
| 60 | + KNOWN_TYPENAMES.get(typeName) ?? scalarIdsByName?.get(typeName); |
| 61 | + if (!uuid) { |
| 62 | + continue; |
| 63 | + } |
| 64 | + codecs.set(uuid, new scalarCodec(uuid)); |
| 65 | + } |
| 66 | +}; |
0 commit comments