Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/hot read models #1910

Merged
merged 5 commits into from
Jun 24, 2021
Merged
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import type {
CommonAdapterPool,
CommonAdapterOptions,
AdapterImplementation,
BaseAdapterImports,
BaseAdapterPool,
AdapterOperations,
AdapterApi,
ObjectKeys,
StoreApi,
} from './types'

const createAdapter = <
AdapterPool extends CommonAdapterPool,
AdapterOptions extends CommonAdapterOptions
>(
imports: BaseAdapterImports,
implementation: AdapterImplementation<AdapterPool, AdapterOptions>,
options: AdapterOptions
): AdapterApi<AdapterPool> => {
const {
splitNestedPath,
checkEventsContinuity,
withPerformanceTracer,
wrapConnect,
wrapDisconnect,
wrapDispose,
wrapOperation,
} = imports

const {
connect,
disconnect,
subscribe,
unsubscribe,
resubscribe,
resume,
pause,
reset,
status,
build,
defineTable,
findOne,
find,
count,
insert,
update,
delete: del,
...restApi
} = implementation

if (Object.keys(restApi).length > 0) {
throw new Error(
`Read model adapter implementation should not provide extra methods: ${JSON.stringify(
Object.keys(restApi)
)}`
)
}

const storeApi: StoreApi<AdapterPool> = {
defineTable,
findOne,
find,
count,
insert,
update,
delete: del,
}

const adapterOperations: AdapterOperations<AdapterPool> = {
subscribe,
unsubscribe,
resubscribe,
resume,
pause,
reset,
status,
build,
}

for (const key of Object.keys(storeApi) as ObjectKeys<
StoreApi<AdapterPool>
>) {
if (typeof storeApi[key] !== 'function') {
throw new Error(`Store API method ${key} should be a function`)
}
}

for (const key of Object.keys(adapterOperations) as ObjectKeys<
AdapterOperations<AdapterPool>
>) {
if (typeof adapterOperations[key] !== 'function') {
throw new Error(`Adapter operation method ${key} should be a function`)
}
}

const { performanceTracer, monitoring, ...adapterOptions } = options

const pool: BaseAdapterPool<AdapterPool> = {
commonAdapterPool: {
performanceTracer,
checkEventsContinuity,
splitNestedPath,
monitoring,
},
adapterPoolMap: new Map(),
withPerformanceTracer,
performanceTracer,
monitoring,
}

const adapter: AdapterApi<AdapterPool> = {
connect: wrapConnect(pool, connect, storeApi, adapterOptions),
disconnect: wrapDisconnect(pool, disconnect),
dispose: wrapDispose(pool, disconnect),
subscribe: wrapOperation(pool, 'subscribe', subscribe),
unsubscribe: wrapOperation(pool, 'unsubscribe', unsubscribe),
resubscribe: wrapOperation(pool, 'resubscribe', resubscribe),
resume: wrapOperation(pool, 'resume', resume),
pause: wrapOperation(pool, 'pause', pause),
reset: wrapOperation(pool, 'reset', reset),
status: wrapOperation(pool, 'status', status),
build: wrapOperation(pool, 'build', build),
}

return Object.freeze(adapter)
}

export default createAdapter
Original file line number Diff line number Diff line change
@@ -1,124 +1,31 @@
import type {
CommonAdapterPool,
CommonAdapterOptions,
AdapterImplementation,
BaseAdapterImports,
BaseAdapterPool,
AdapterOperations,
AdapterApi,
ObjectKeys,
StoreApi,
} from './types'

const createAdapter = <
AdapterPool extends CommonAdapterPool,
AdapterOptions extends CommonAdapterOptions
>(
imports: BaseAdapterImports,
implementation: AdapterImplementation<AdapterPool, AdapterOptions>,
options: AdapterOptions
): AdapterApi<AdapterPool> => {
const {
makeSplitNestedPath,
withPerformanceTracer,
wrapConnect,
wrapDisconnect,
wrapDispose,
wrapOperation,
} = imports
const splitNestedPath = makeSplitNestedPath(imports)

const {
connect,
disconnect,
subscribe,
unsubscribe,
resubscribe,
resume,
pause,
reset,
status,
build,
defineTable,
findOne,
find,
count,
insert,
update,
delete: del,
...restApi
} = implementation

if (Object.keys(restApi).length > 0) {
throw new Error(
`Read model adapter implementation should not provide extra methods: ${JSON.stringify(
Object.keys(restApi)
)}`
)
}

const storeApi: StoreApi<AdapterPool> = {
defineTable,
findOne,
find,
count,
insert,
update,
delete: del,
}

const adapterOperations: AdapterOperations<AdapterPool> = {
subscribe,
unsubscribe,
resubscribe,
resume,
pause,
reset,
status,
build,
}

for (const key of Object.keys(storeApi) as ObjectKeys<
StoreApi<AdapterPool>
>) {
if (typeof storeApi[key] !== 'function') {
throw new Error(`Store API method ${key} should be a function`)
}
}

for (const key of Object.keys(adapterOperations) as ObjectKeys<
AdapterOperations<AdapterPool>
>) {
if (typeof adapterOperations[key] !== 'function') {
throw new Error(`Adapter operation method ${key} should be a function`)
}
}

const { performanceTracer, monitoring, ...adapterOptions } = options

const pool: BaseAdapterPool<AdapterPool> = {
commonAdapterPool: { performanceTracer, splitNestedPath, monitoring },
adapterPoolMap: new Map(),
withPerformanceTracer,
performanceTracer,
monitoring,
}

const adapter: AdapterApi<AdapterPool> = {
connect: wrapConnect(pool, connect, storeApi, adapterOptions),
disconnect: wrapDisconnect(pool, disconnect),
dispose: wrapDispose(pool, disconnect),
subscribe: wrapOperation(pool, 'subscribe', subscribe),
unsubscribe: wrapOperation(pool, 'unsubscribe', unsubscribe),
resubscribe: wrapOperation(pool, 'resubscribe', resubscribe),
resume: wrapOperation(pool, 'resume', resume),
pause: wrapOperation(pool, 'pause', pause),
reset: wrapOperation(pool, 'reset', reset),
status: wrapOperation(pool, 'status', status),
build: wrapOperation(pool, 'build', build),
}

return Object.freeze(adapter)
//eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import PathToolkit from 'path-toolkit'
import { checkEventsContinuity } from '@resolve-js/eventstore-base'

import _createAdapter from './create-adapter-factory'
import makeSplitNestedPath from './make-split-nested-path'
import withPerformanceTracer from './with-performance-tracer'
import wrapConnect from './wrap-connect'
import wrapDisconnect from './wrap-disconnect'
import wrapDispose from './wrap-dispose'
import wrapOperation from './wrap-operation'
import { CreateAdapterMethod } from './types'

const baseAdapterImports = {
splitNestedPath: makeSplitNestedPath(PathToolkit),
checkEventsContinuity,
makeSplitNestedPath,
withPerformanceTracer,
wrapConnect,
wrapDisconnect,
wrapDispose,
wrapOperation,
}

const createAdapter = _createAdapter.bind(
null,
baseAdapterImports
) as CreateAdapterMethod

export default createAdapter
Original file line number Diff line number Diff line change
@@ -1,34 +1,3 @@
//eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import PathToolkit from 'path-toolkit'

import _createAdapter from './create-adapter'
import makeSplitNestedPath from './make-split-nested-path'
import withPerformanceTracer from './with-performance-tracer'
import wrapConnect from './wrap-connect'
import wrapDisconnect from './wrap-disconnect'
import wrapDispose from './wrap-dispose'
import wrapOperation from './wrap-operation'
import { CreateAdapterMethod } from './types'
export { default as default } from './create-adapter'
export { default as splitNestedPath } from './split-nested-path'
export * from './types'

const baseAdapterImports = {
PathToolkit,
makeSplitNestedPath,
withPerformanceTracer,
wrapConnect,
wrapDisconnect,
wrapDispose,
wrapOperation,
}

const createAdapter = _createAdapter.bind(
null,
baseAdapterImports
) as CreateAdapterMethod

const splitNestedPath = makeSplitNestedPath(baseAdapterImports)

export default createAdapter

export { splitNestedPath }
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { MakeSplitNestedPathMethod, SplitNestedPathMethod } from './types'

const makeSplitNestedPath: MakeSplitNestedPathMethod = (imports) => {
const pathToolkit = new imports.PathToolkit()
const makeSplitNestedPath: MakeSplitNestedPathMethod = (PathToolkit) => {
const pathToolkit = new PathToolkit()
pathToolkit.setOptions({
cache: false,
force: false,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
//eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import PathToolkit from 'path-toolkit'
import makeSplitNestedPath from './make-split-nested-path'

const splitNestedPath = makeSplitNestedPath(PathToolkit)

export default splitNestedPath
Loading