Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 14 additions & 12 deletions packages/backend/src/db/database.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { create } from 'anydb-sql-2';
import * as migrations from 'anydb-sql-2-migrations';
import { anydbSQL, createMigration, MigrationTask } from 'anydb-sql-3';
import * as Promise from 'bluebird';
import { AppSingleton } from '@h4bff/core';

Expand All @@ -9,17 +8,17 @@ import { AppSingleton } from '@h4bff/core';
* Additionally, it stores the db migration tasks and provides API for migrations.
*/
export class Database extends AppSingleton {
private migrations: migrations.MigrationTask[] = [];
private migrations: MigrationTask[] = [];

db = create({
db = anydbSQL({
url: process.env['POSTGRES_URL'],
connections: { min: 2, max: Number(process.env['DB_MAX_CONNS'] || '20') },
});

/**
* Ads new migration task.
*/
addMigrations(mig: migrations.MigrationTask[]) {
addMigrations(mig: MigrationTask[]) {
this.migrations.push(...mig);
}

Expand All @@ -34,23 +33,26 @@ export class Database extends AppSingleton {
* Runs the migrations stored in the migration list.
*/
runMigrations(): void | Promise<void> {
const sequence = migrations.create(this.db, this.migrations);
return sequence.run();
const sequence = createMigration(this.db, this.migrations);
// TODO: Remove cast to any
return sequence.run() as any;
}

/**
* Runs "UP" database migration.
*/
upMigrations(opts: { silent: boolean }): Promise<void> {
const sequence = migrations.create(this.db, this.migrations);
return sequence.migrate(opts);
upMigrations(_opts: { silent: boolean }): Promise<void> {
const sequence = createMigration(this.db, this.migrations);
// TODO: Remove cast to any
return sequence.migrate() as any;
}

/**
* Runs "DOWN" database migration.
*/
downMigrations(): Promise<void> {
const sequence = migrations.create(this.db, this.migrations);
return sequence.drop();
const sequence = createMigration(this.db, this.migrations);
// TODO: Remove cast to any
return sequence.drop() as any;
}
}
66 changes: 5 additions & 61 deletions packages/backend/src/db/transactionProvider.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { App } from '@h4bff/core';
import { TransactionProvider } from './transactionProvider';
import { Database } from './database';
import { AnydbSql, Transaction, AnyDBPool } from 'anydb-sql-2';
import { AnydbSql, Transaction } from 'anydb-sql-3';

describe('TransactionProvider', () => {
describe('Transaction and connection getters', () => {
Expand All @@ -10,15 +10,13 @@ describe('TransactionProvider', () => {
process.env.POSTGRES_URL = 'postgres://user:password@localhost:5432/database';

// prepare Database mock
let pool = {} as AnyDBPool;
let transaction = {} as Transaction;
app.overrideSingleton(
Database,
class MockDatabase extends Database {
db = ({
getPool: jest.fn(() => pool),
begin: jest.fn(() => transaction),
} as any) as AnydbSql;
} as any) as AnydbSql<any>;
},
);

Expand All @@ -27,54 +25,6 @@ describe('TransactionProvider', () => {

expect(transactionProvider.tx).toEqual(transaction);
});

it(`should return existing transaction as connection`, () => {
let app = new App();
process.env.POSTGRES_URL = 'postgres://user:password@localhost:5432/database';

// prepare Database mock
let pool = {} as AnyDBPool;
let transaction = {} as Transaction;
app.overrideSingleton(
Database,
class MockDatabase extends Database {
db = ({
getPool: jest.fn(() => pool),
begin: jest.fn(() => transaction),
} as any) as AnydbSql;
},
);

let sCtx = app.createServiceContext();
let transactionProvider = new TransactionProvider(sCtx);
transactionProvider.tx;

expect(transactionProvider.conn).toEqual(transaction);
});

it(`should return the pool as connection if there is not transaction created yet`, () => {
let app = new App();
process.env.POSTGRES_URL = 'postgres://user:password@localhost:5432/database';

// prepare Database mock
let pool = {} as AnyDBPool;
let transaction = {} as Transaction;
app.overrideSingleton(
Database,
class MockDatabase extends Database {
db = ({
getPool: jest.fn(() => pool),
begin: jest.fn(() => transaction),
} as any) as AnydbSql;
},
);

let sCtx = app.createServiceContext();
let transactionProvider = new TransactionProvider(sCtx);
transactionProvider.tx;

expect(transactionProvider.conn).toEqual(pool);
});
});

describe('onDispose', () => {
Expand All @@ -83,7 +33,6 @@ describe('TransactionProvider', () => {
process.env.POSTGRES_URL = 'postgres://user:password@localhost:5432/database';

// prepare Database mock
let pool = {} as AnyDBPool;
let transaction = ({
rollbackAsync: jest.fn(() => Promise.resolve()),
commitAsync: jest.fn(() => Promise.resolve()),
Expand All @@ -92,9 +41,8 @@ describe('TransactionProvider', () => {
Database,
class MockDatabase extends Database {
db = ({
getPool: jest.fn(() => pool),
begin: jest.fn(() => transaction),
} as any) as AnydbSql;
} as any) as AnydbSql<any>;
},
);

Expand All @@ -111,7 +59,6 @@ describe('TransactionProvider', () => {
process.env.POSTGRES_URL = 'postgres://user:password@localhost:5432/database';

// prepare Database mock
let pool = {} as AnyDBPool;
let transaction = ({
rollbackAsync: jest.fn(() => Promise.resolve()),
commitAsync: jest.fn(() => Promise.resolve()),
Expand All @@ -120,9 +67,8 @@ describe('TransactionProvider', () => {
Database,
class MockDatabase extends Database {
db = ({
getPool: jest.fn(() => pool),
begin: jest.fn(() => transaction),
} as any) as AnydbSql;
} as any) as AnydbSql<any>;
},
);

Expand All @@ -140,7 +86,6 @@ describe('TransactionProvider', () => {
process.env.POSTGRES_URL = 'postgres://user:password@localhost:5432/database';

// prepare Database mock
let pool = {} as AnyDBPool;
let transaction = ({
rollbackAsync: jest.fn(() => Promise.resolve()),
commitAsync: jest.fn(() => Promise.resolve()),
Expand All @@ -149,9 +94,8 @@ describe('TransactionProvider', () => {
Database,
class MockDatabase extends Database {
db = ({
getPool: jest.fn(() => pool),
begin: jest.fn(() => transaction),
} as any) as AnydbSql;
} as any) as AnydbSql<any>;
},
);

Expand Down
15 changes: 5 additions & 10 deletions packages/backend/src/db/transactionProvider.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as Promise from 'bluebird';
import { Transaction } from 'anydb-sql-2';
import { Transaction } from 'anydb-sql-3';
import { BaseService, ServiceContext } from '@h4bff/core';
import { Database } from './database';
import { TransactionCleaner } from './transactionCleaner';
Expand All @@ -11,7 +11,6 @@ import { TransactionCleaner } from './transactionCleaner';
*/
export class TransactionProvider extends BaseService {
private db = this.getSingleton(Database).db;
private pool = this.db.getPool();
private _tx: Transaction | null = null;

constructor(context: ServiceContext) {
Expand All @@ -24,25 +23,21 @@ export class TransactionProvider extends BaseService {
return this._tx;
}

get conn() {
if (this._tx) return this._tx;
return this.pool;
}

/**
* Gets called on context disposal and makes sure that the transaction
* is disposed properly. If an error occured it rollbacks the transaction,
* otherwise it commits it.
*/
onDispose(error: Error | null) {
onDispose(error: Error | null): Promise<any> {
if (this._tx) {
let tx = this._tx;
this._tx = null;

// TODO: get logger singleton in this TX provider, and log that the rollback could
// not be performend (unless its "method rollback unavailable in state closed")
if (error) return tx.rollbackAsync().catch(() => {});
else return tx.commitAsync();
// TODO: Remove cast as any
if (error) return tx.rollbackAsync().catch(() => {}) as any;
else return tx.commitAsync() as any;
}
return Promise.resolve();
}
Expand Down
7 changes: 4 additions & 3 deletions packages/example/src/files-plugin.spec.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import * as fp from './files-plugin';
import { Transaction } from 'anydb-sql-3';
import { TransactionProvider } from '@h4bff/backend';
import { App, BaseService } from '@h4bff/core';

import * as Bromise from 'bluebird';
import { UserService } from './files-plugin';

class TxMock extends BaseService {
get tx() {
get tx(): Transaction {
return {
queryAsync: (<T>(query: { text: string; arguments: any[] }) => {
console.log('TX QUERYASYNC', query);
Expand All @@ -18,9 +19,9 @@ class TxMock extends BaseService {
commitAsync() {
return null as any;
},
};
} as any;
}
conn: any;

onDispose() {
return Bromise.resolve();
}
Expand Down
4 changes: 2 additions & 2 deletions packages/example/src/files-plugin.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { mapSeries } from 'bluebird';
import * as Promise from 'bluebird';
import { Table } from 'anydb-sql-2';
import { Table } from 'anydb-sql-3';
import { v4 as uuid } from 'uuid';
import { Database, TransactionProvider, RPCServiceRegistry } from '@h4bff/backend';
import { BaseService, App, AppSingleton } from '@h4bff/core';
Expand Down Expand Up @@ -69,7 +69,7 @@ export class Files extends BaseService {
return this.db.filesTbl
.insert(record)
.execWithin(this.tx)
.thenReturn(record);
.thenReturn(record) as any; // TODO: Remove cast as any
}

/**
Expand Down