Skip to content

Commit

Permalink
feat: allowing defining mode and profiler for a query client
Browse files Browse the repository at this point in the history
  • Loading branch information
thetutlage committed Aug 18, 2019
1 parent c6621ff commit 0896fe2
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 38 deletions.
24 changes: 20 additions & 4 deletions adonis-typings/database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ declare module '@ioc:Adonis/Addons/Database' {
import { Pool } from 'tarn'
import * as knex from 'knex'
import { EventEmitter } from 'events'
import { ProfilerRowContract } from '@poppinss/profiler'

import {
RawContract,
Expand Down Expand Up @@ -389,12 +390,27 @@ declare module '@ioc:Adonis/Addons/Database' {
getRawConnection: ConnectionManagerContract['get']
manager: ConnectionManagerContract,

connection (connectionName: string): QueryClientContract
query (mode?: 'read' | 'write'): DatabaseQueryBuilderContract
insertQuery (): InsertQueryBuilderContract
connection (
connectionName: string,
options?: Partial<{ mode: 'read' | 'write', profiler: ProfilerRowContract }>,
): QueryClientContract

query (
options?: Partial<{ mode: 'read' | 'write', profiler: ProfilerRowContract }>,
): DatabaseQueryBuilderContract

insertQuery (
options?: Partial<{ profiler: ProfilerRowContract }>,
): InsertQueryBuilderContract

from (table: string): DatabaseQueryBuilderContract
table (table: string): InsertQueryBuilderContract
transaction (): Promise<TransactionClientContract>
raw (sql: string, bindings?: any, mode?: 'read' | 'write'): RawContract

raw (
sql: string,
bindings?: any,
options?: Partial<{ mode: 'read' | 'write', profiler: ProfilerRowContract }>,
): RawContract
}
}
3 changes: 2 additions & 1 deletion providers/DatabaseProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ export class DatabaseServiceProvider {
this.$container.singleton('Adonis/Addons/Database', () => {
const config = this.$container.use('Adonis/Core/Config').get('database', {})
const Logger = this.$container.use('Adonis/Core/Logger')
return new Database(config, Logger)
const Profiler = this.$container.use('Adonis/Core/Profiler')
return new Database(config, Logger, Profiler)
})
}
}
69 changes: 50 additions & 19 deletions src/Database/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

import { Exception } from '@poppinss/utils'
import { LoggerContract } from '@poppinss/logger'
import { ProfilerContract, ProfilerRowContract } from '@poppinss/profiler'

import {
ConnectionManagerContract,
Expand All @@ -35,7 +36,11 @@ export class Database implements DatabaseContract {
*/
public primaryConnectionName = this._config.connection

constructor (private _config: DatabaseConfigContract, private _logger: LoggerContract) {
constructor (
private _config: DatabaseConfigContract,
private _logger: LoggerContract,
private _profiler: ProfilerContract,
) {
this.manager = new ConnectionManager(this._logger)
this._registerConnections()
}
Expand All @@ -53,48 +58,72 @@ export class Database implements DatabaseContract {
/**
* Returns the connection node from the connection manager
*/
public getRawConnection (name) {
public getRawConnection (name: string) {
return this.manager.get(name)
}

/**
* Returns the query client for a given connection
*/
public connection (connection: string = this.primaryConnectionName) {
const [name, mode] = connection.split('::')
public connection (
connection: string = this.primaryConnectionName,
options?: Partial<{ mode: 'read' | 'write', profiler: ProfilerRowContract }>,
) {
options = options || {}

if (!options.profiler) {
options.profiler = this._profiler.create('')
}

/**
* Connect is noop when already connected
*/
this.manager.connect(name)
this.manager.connect(connection)

/**
* Disallow modes other than `read` or `write`
*/
if (mode && !['read', 'write'].includes(mode)) {
throw new Exception(`Invalid mode ${mode}. Must be read or write`)
if (options.mode && !['read', 'write'].includes(options.mode)) {
throw new Exception(`Invalid mode ${options.mode}. Must be read or write`)
}

/**
* Fetching connection for the given name
*/
const rawConnection = this.manager.get(connection)!.connection!

/**
* Generating query client for a given connection and setting appropriate
* mode on it
*/
const queryClient = options.mode
? rawConnection.getClient(options.mode as ('read' | 'write'))
: rawConnection.getClient()

/**
* Passing profiler to the query client for profiling queries
*/
if (options.profiler) {
queryClient.profiler = options.profiler
}

const rawConnection = this.manager.get(name)!.connection!
return mode ? rawConnection.getClient(mode as ('read' | 'write')) : rawConnection.getClient()
return queryClient
}

/**
* Returns query builder. Optionally one can define the mode as well
*/
public query (mode?: 'read' | 'write') {
return mode
? this.connection(`${this.primaryConnectionName}::${mode}`).query()
: this.connection().query()
public query (options?: Partial<{ mode: 'read' | 'write', profiler: ProfilerRowContract }>) {
return this.connection(this.primaryConnectionName, options).query()
}

/**
* Returns insert query builder. Always has to be dual or write mode and
* hence it doesn't matter, since in both `dual` and `write` mode,
* the `write` connection is always used.
*/
public insertQuery () {
return this.connection().insertQuery()
public insertQuery (options?: Partial<{ mode: 'read' | 'write', profiler: ProfilerRowContract }>) {
return this.connection(this.primaryConnectionName, options).insertQuery()
}

/**
Expand Down Expand Up @@ -124,9 +153,11 @@ export class Database implements DatabaseContract {
* defined the `read/write` mode in which to execute the
* query
*/
public raw (sql: string, bindings?: any, mode?: 'read' | 'write') {
return mode
? this.connection(`${this.primaryConnectionName}::${mode}`).raw(sql, bindings)
: this.connection().raw(sql, bindings)
public raw (
sql: string,
bindings?: any,
options?: Partial<{ mode: 'read' | 'write', profiler: ProfilerRowContract }>,
) {
return this.connection(this.primaryConnectionName, options).raw(sql, bindings)
}
}
8 changes: 8 additions & 0 deletions test-helpers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { join } from 'path'
import * as knex from 'knex'
import * as dotenv from 'dotenv'
import { FakeLogger } from '@poppinss/logger'
import { Profiler } from '@poppinss/profiler'
import { Filesystem } from '@poppinss/dev-utils'

import { ConnectionConfigContract } from '@ioc:Adonis/Addons/Database'
Expand Down Expand Up @@ -157,3 +158,10 @@ export function getLogger () {
level: 'info',
})
}

/**
* Returns profiler instance
*/
export function getProfiler () {
return new Profiler({ enabled: false })
}
28 changes: 14 additions & 14 deletions test/database.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import * as test from 'japa'

import { Database } from '../src/Database'
import { getConfig, setup, cleanup, getLogger } from '../test-helpers'
import { getConfig, setup, cleanup, getLogger, getProfiler } from '../test-helpers'

test.group('Database', (group) => {
group.before(async () => {
Expand All @@ -29,7 +29,7 @@ test.group('Database', (group) => {
connections: { primary: getConfig() },
}

const db = new Database(config, getLogger())
const db = new Database(config, getLogger(), getProfiler())

assert.isDefined(db.manager.connections.get('primary'))
assert.equal(db.manager.connections.get('primary')!.state, 'idle')
Expand All @@ -44,7 +44,7 @@ test.group('Database', (group) => {
connections: { primary: getConfig() },
}

const db = new Database(config, getLogger())
const db = new Database(config, getLogger(), getProfiler())
db.manager.on('connect', (connection) => {
assert.equal(connection.name, 'primary')
})
Expand All @@ -61,7 +61,7 @@ test.group('Database', (group) => {
connections: { primary: getConfig() },
}

const db = new Database(config, getLogger())
const db = new Database(config, getLogger(), getProfiler())
db.manager.on('connect', (connection) => {
assert.equal(connection.name, 'primary')
})
Expand All @@ -78,8 +78,8 @@ test.group('Database', (group) => {
connections: { primary: getConfig() },
}

const db = new Database(config, getLogger())
const client = db.connection('primary::write')
const db = new Database(config, getLogger(), getProfiler())
const client = db.connection('primary', { mode: 'write' })

assert.equal(client.mode, 'write')
await db.manager.closeAll()
Expand All @@ -93,8 +93,8 @@ test.group('Database', (group) => {
connections: { primary: getConfig() },
}

const db = new Database(config, getLogger())
const client = db.connection('primary::read')
const db = new Database(config, getLogger(), getProfiler())
const client = db.connection('primary', { mode: 'read' })

assert.equal(client.mode, 'read')
await db.manager.closeAll()
Expand All @@ -106,7 +106,7 @@ test.group('Database', (group) => {
connections: { primary: getConfig() },
}

const db = new Database(config, getLogger())
const db = new Database(config, getLogger(), getProfiler())
const trx = await db.transaction()

assert.equal(trx.mode, 'dual')
Expand All @@ -122,7 +122,7 @@ test.group('Database', (group) => {
connections: { primary: getConfig() },
}

const db = new Database(config, getLogger())
const db = new Database(config, getLogger(), getProfiler())
const result = await db.raw('select 1 + 1')
assert.isDefined(result)
await db.manager.closeAll()
Expand All @@ -134,8 +134,8 @@ test.group('Database', (group) => {
connections: { primary: getConfig() },
}

const db = new Database(config, getLogger())
const result = await db.raw('select 1 + 1', [], 'read')
const db = new Database(config, getLogger(), getProfiler())
const result = await db.raw('select 1 + 1', [], { mode: 'read' })
assert.isDefined(result)
await db.manager.closeAll()
})
Expand All @@ -146,8 +146,8 @@ test.group('Database', (group) => {
connections: { primary: getConfig() },
}

const db = new Database(config, getLogger())
const result = await db.raw('select 1 + 1', [], 'write')
const db = new Database(config, getLogger(), getProfiler())
const result = await db.raw('select 1 + 1', [], { mode: 'write' })
assert.isDefined(result)
await db.manager.closeAll()
})
Expand Down

0 comments on commit 0896fe2

Please sign in to comment.