Skip to content

Commit a09f473

Browse files
darkyjaredwray
andauthored
feat: ability to use unlogged table on Postgres (#1290)
* feat: ability to use unlogged table on Postgres * feat: ability to use unlogged table on Postgres * updating documentation --------- Co-authored-by: Jared Wray <me@jaredwray.com>
1 parent 0693e29 commit a09f473

File tree

4 files changed

+58
-9
lines changed

4 files changed

+58
-9
lines changed

packages/postgres/README.md

+28-3
Original file line numberDiff line numberDiff line change
@@ -32,25 +32,50 @@ You can specify the `table` option.
3232
e.g:
3333

3434
```js
35-
const keyv = new Keyv(new KeyvPostgres('postgresql://user:pass@localhost:5432/dbname'), { table: 'cache' });
35+
const keyvPostgres = new KeyvPostgres({ uri: 'postgresql://user:pass@localhost:5432/dbname', table: 'cache' });
36+
const keyv = new Keyv(keyvPostgres);
3637
```
3738

3839
You can specify the `schema` option (default is `public`).
3940

4041
e.g:
4142

4243
```js
43-
const keyv = new Keyv(new KeyvPostgres('postgresql://user:pass@localhost:5432/dbname'), { schema: 'keyv' });
44+
const keyvPostgres = new KeyvPostgres({ uri: 'postgresql://user:pass@localhost:5432/dbname', schema: 'keyv' });
45+
const keyv = new Keyv(keyvPostgres);
4446
```
4547

46-
You can also use a helper function to create `Keyv` with `KeyvPostgres` store.
48+
You can also use the `createKeyv` helper function to create `Keyv` with `KeyvPostgres` store.
4749

4850
```js
4951
import {createKeyv} from '@keyv/postgres';
5052

5153
const keyv = createKeyv({ uri: 'postgresql://user:pass@localhost:5432/dbname', table: 'cache', schema: 'keyv' });
5254
```
5355

56+
## Using an Unlogged Table for Performance
57+
58+
By default, the adapter creates a logged table. If you want to use an unlogged table for performance, you can pass the `useUnloggedTable` option to the constructor.
59+
60+
```js
61+
const keyvPostgres = new KeyvPostgres({ uri: 'postgresql://user:pass@localhost:5432/dbname', useUnloggedTable: true });
62+
const keyv = new Keyv(keyvPostgres);
63+
```
64+
65+
From the [PostgreSQL documentation](https://www.postgresql.org/docs/current/sql-createtable.html#SQL-CREATETABLE-UNLOGGED):
66+
67+
If specified, the table is created as an unlogged table. Data written to unlogged tables is not written to the write-ahead log (see Chapter 28), which makes them considerably faster than ordinary tables. However, they are not crash-safe: an unlogged table is automatically truncated after a crash or unclean shutdown. The contents of an unlogged table are also not replicated to standby servers. Any indexes created on an unlogged table are automatically unlogged as well.
68+
69+
If this is specified, any sequences created together with the unlogged table (for identity or serial columns) are also created as unlogged.
70+
71+
## Connection pooling
72+
73+
The adapter automatically uses the default settings on the `pg` package for connection pooling. You can override these settings by passing the options to the constructor such as setting the `max` pool size.
74+
75+
```js
76+
const keyv = new Keyv(new KeyvPostgres({ uri: 'postgresql://user:pass@localhost:5432/dbname', max: 20 }));
77+
```
78+
5479
## Testing
5580

5681
When testing you can use our `docker compose` postgresql instance by having docker installed and running. This will start a postgres server, run the tests, and stop the server:

packages/postgres/src/index.ts

+17-6
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,24 @@ export class KeyvPostgres extends EventEmitter implements KeyvStoreAdapter {
1212
opts: KeyvPostgresOptions;
1313
query: Query;
1414
namespace?: string;
15-
constructor(options?: KeyvPostgresOptions) {
15+
constructor(options?: KeyvPostgresOptions | string) {
1616
super();
1717
this.ttlSupport = false;
18-
options = {
19-
dialect: 'postgres',
20-
uri: 'postgresql://localhost:5432', ...options,
21-
};
18+
19+
if (typeof options === 'string') {
20+
const uri = options;
21+
options = {
22+
dialect: 'postgres',
23+
uri,
24+
};
25+
console.log('options', options);
26+
} else {
27+
options = {
28+
dialect: 'postgres',
29+
uri: 'postgresql://localhost:5432',
30+
...options,
31+
};
32+
}
2233

2334
const connect = async () => {
2435
const conn = pool(options!.uri!, options);
@@ -35,7 +46,7 @@ export class KeyvPostgres extends EventEmitter implements KeyvStoreAdapter {
3546
...options,
3647
};
3748

38-
let createTable = `CREATE TABLE IF NOT EXISTS ${this.opts.schema!}.${this.opts.table!}(key VARCHAR(${Number(this.opts.keySize!)}) PRIMARY KEY, value TEXT )`;
49+
let createTable = `CREATE${this.opts.useUnloggedTable ? ' UNLOGGED ' : ' '}TABLE IF NOT EXISTS ${this.opts.schema!}.${this.opts.table!}(key VARCHAR(${Number(this.opts.keySize!)}) PRIMARY KEY, value TEXT )`;
3950

4051
if (this.opts.schema !== 'public') {
4152
createTable = `CREATE SCHEMA IF NOT EXISTS ${this.opts.schema!}; ${createTable}`;

packages/postgres/src/types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export type KeyvPostgresOptions = {
2727
ssl?: any;
2828
dialect?: string;
2929
iterationLimit?: number;
30+
useUnloggedTable?: boolean;
3031
} & PoolConfig;
3132

3233
export type Query = (sqlString: string, values?: any) => Promise<any[]>;

packages/postgres/test/test.ts

+12
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@ test.beforeEach(async () => {
1414
await keyv.clear();
1515
});
1616

17+
test.it('should be able to pass in just uri as string', async t => {
18+
const keyv = new KeyvPostgres(postgresUri);
19+
await keyv.set('foo', 'bar');
20+
t.expect(await keyv.get('foo')).toBe('bar');
21+
});
22+
1723
test.it('test schema as non public', async t => {
1824
const keyv1 = new KeyvPostgres({uri: 'postgresql://postgres:postgres@localhost:5432/keyv_test', schema: 'keyvtest1'});
1925
const keyv2 = new KeyvPostgres({uri: 'postgresql://postgres:postgres@localhost:5432/keyv_test', schema: 'keyvtest2'});
@@ -83,3 +89,9 @@ test.it('helper to create Keyv instance with postgres', async t => {
8389
t.expect(await keyv.set('foo', 'bar')).toBe(true);
8490
t.expect(await keyv.get('foo')).toBe('bar');
8591
});
92+
93+
test.it('test unlogged table', async t => {
94+
const keyv = createKeyv({uri: postgresUri, useUnloggedTable: true});
95+
t.expect(await keyv.set('foo', 'bar')).toBe(true);
96+
t.expect(await keyv.get('foo')).toBe('bar');
97+
});

0 commit comments

Comments
 (0)