Skip to content

PostgresExternalService: open_instances tracking and error handling issues in subscribe() #1149

@hubyrod

Description

@hubyrod

Summary

PostgresExternalService.subscribe() in @skip-adapter/postgres has three related issues around error handling that can leave the adapter in an inconsistent state or crash the process.

Location

@skip-adapter/postgressrc/index.ts, class PostgresExternalService, subscribe() method

Issues

1. open_instances.add() called before queries succeed

The instance is added to open_instances before the trigger/function/listen queries run. If any query fails, the instance is marked as set up but the trigger was never created. Subsequent calls to subscribe skip setup because open_instances.has(instance) returns true.

// Current code (broken)
if (!this.open_instances.has(instance)) {
    this.open_instances.add(instance);       // ← marked before queries
    await this.client.query(/* CREATE FUNCTION ... */);
    await this.client.query(/* LISTEN ... */);
    await this.client.query(/* CREATE TRIGGER ... */);
}

Fix: move this.open_instances.add(instance) after all three queries succeed.

2. No error handler on pg.Client

If the Postgres connection emits an error event (e.g. server restart, network drop), node's pg.Client will crash the process with an unhandled error. Additionally, open_instances retains stale entries so the adapter won't re-create triggers after reconnection.

Fix: add this.client.on("error", ...) in the constructor that logs the error and clears open_instances.

3. No try-catch around setupPgNotify / initData

Both setupPgNotify() and initData() can throw (e.g. table doesn't exist yet, permission error). An unhandled error in setupPgNotify crashes the process. An unhandled error in initData propagates without context.

Fix: wrap both in try-catch with logging.

How to reproduce

For issue 1:

  1. Start a Skip service with a Postgres external service
  2. Make the CREATE TRIGGER query fail (e.g. the table doesn't exist yet at trigger creation time)
  3. Restart the service — subscribe() skips setup because open_instances still has the instance
  4. No trigger is ever created; real-time updates never arrive

For issue 2:

  1. Start a Skip service connected to Postgres
  2. Restart Postgres or drop the network connection
  3. The process crashes with an unhandled error event from pg.Client

Version

@skip-adapter/postgres@0.0.19

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions