From bd231a3d63310049c2467fff15670f351cec3e41 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Sun, 4 Apr 2021 19:45:23 +0200 Subject: [PATCH 1/2] catalog-backend/next: add Context Signed-off-by: Patrik Oldsberg --- .../src/next/Context/BaseContext.ts | 26 ++++++++++++ .../src/next/Context/ContextWithValue.ts | 40 +++++++++++++++++++ .../src/next/Context/TransactionContext.ts | 40 +++++++++++++++++++ .../catalog-backend/src/next/Context/index.ts | 21 ++++++++++ .../catalog-backend/src/next/Context/types.ts | 23 +++++++++++ 5 files changed, 150 insertions(+) create mode 100644 plugins/catalog-backend/src/next/Context/BaseContext.ts create mode 100644 plugins/catalog-backend/src/next/Context/ContextWithValue.ts create mode 100644 plugins/catalog-backend/src/next/Context/TransactionContext.ts create mode 100644 plugins/catalog-backend/src/next/Context/index.ts create mode 100644 plugins/catalog-backend/src/next/Context/types.ts diff --git a/plugins/catalog-backend/src/next/Context/BaseContext.ts b/plugins/catalog-backend/src/next/Context/BaseContext.ts new file mode 100644 index 0000000000..c9553cffd5 --- /dev/null +++ b/plugins/catalog-backend/src/next/Context/BaseContext.ts @@ -0,0 +1,26 @@ +/* + * Copyright 2021 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Context, ContextKey } from './types'; + +/** + * A base Context implementation that does not hold any value. + */ +export class BaseContext implements Context { + getContextValue(key: ContextKey): T { + return key.defaultValue; + } +} diff --git a/plugins/catalog-backend/src/next/Context/ContextWithValue.ts b/plugins/catalog-backend/src/next/Context/ContextWithValue.ts new file mode 100644 index 0000000000..8e61e2c6f2 --- /dev/null +++ b/plugins/catalog-backend/src/next/Context/ContextWithValue.ts @@ -0,0 +1,40 @@ +/* + * Copyright 2021 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { BaseContext } from './BaseContext'; +import { Context, ContextKey } from './types'; + +/** + * A Context implementation that holds a single value, optionally extending an existing context. + */ +export class ContextWithValue implements Context { + static create(key: ContextKey, value: unknown, parent?: Context) { + return new ContextWithValue(parent ?? new BaseContext(), key, value); + } + + private constructor( + private readonly parent: Context, + private readonly key: ContextKey, + private readonly value: unknown, + ) {} + + getContextValue(key: ContextKey): T { + if (this.key === key) { + return this.value as T; + } + return this.parent.getContextValue(key); + } +} diff --git a/plugins/catalog-backend/src/next/Context/TransactionContext.ts b/plugins/catalog-backend/src/next/Context/TransactionContext.ts new file mode 100644 index 0000000000..6ac50fbc07 --- /dev/null +++ b/plugins/catalog-backend/src/next/Context/TransactionContext.ts @@ -0,0 +1,40 @@ +/* + * Copyright 2021 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Context, ContextKey } from './types'; +import { Knex } from 'knex'; +import { ContextWithValue } from './ContextWithValue'; + +const transactionContextKey = new ContextKey( + undefined, +); + +/** + * TransactionContext handles the wrapping of a knex transaction in a Context. + */ +export class TransactionContext { + static create(tx: Knex.Transaction, parent?: Context) { + return ContextWithValue.create(transactionContextKey, tx, parent); + } + + static getTransaction(context: Context): Knex.Transaction { + const transaction = context.getContextValue(transactionContextKey); + if (!transaction) { + throw new Error(`No transaction available in context`); + } + return transaction; + } +} diff --git a/plugins/catalog-backend/src/next/Context/index.ts b/plugins/catalog-backend/src/next/Context/index.ts new file mode 100644 index 0000000000..992f5e89a6 --- /dev/null +++ b/plugins/catalog-backend/src/next/Context/index.ts @@ -0,0 +1,21 @@ +/* + * Copyright 2021 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { BaseContext } from './BaseContext'; +export { ContextWithValue } from './ContextWithValue'; +export { TransactionContext } from './TransactionContext'; +export { ContextKey } from './types'; +export type { Context } from './types'; diff --git a/plugins/catalog-backend/src/next/Context/types.ts b/plugins/catalog-backend/src/next/Context/types.ts new file mode 100644 index 0000000000..0973b83515 --- /dev/null +++ b/plugins/catalog-backend/src/next/Context/types.ts @@ -0,0 +1,23 @@ +/* + * Copyright 2021 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class ContextKey { + constructor(readonly defaultValue: T) {} +} + +export interface Context { + getContextValue(key: ContextKey): T; +} From 065e532aade1047d3d06a0d6a308091e63e6eb06 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 28 Apr 2021 10:30:03 +0200 Subject: [PATCH 2/2] catalog-backend: tweak Context API Signed-off-by: Patrik Oldsberg --- .../Context/{BaseContext.ts => BackgroundContext.ts} | 2 +- .../src/next/Context/ContextWithValue.ts | 5 ++--- .../{TransactionContext.ts => TransactionValue.ts} | 10 +++++----- plugins/catalog-backend/src/next/Context/index.ts | 4 ++-- 4 files changed, 10 insertions(+), 11 deletions(-) rename plugins/catalog-backend/src/next/Context/{BaseContext.ts => BackgroundContext.ts} (93%) rename plugins/catalog-backend/src/next/Context/{TransactionContext.ts => TransactionValue.ts} (77%) diff --git a/plugins/catalog-backend/src/next/Context/BaseContext.ts b/plugins/catalog-backend/src/next/Context/BackgroundContext.ts similarity index 93% rename from plugins/catalog-backend/src/next/Context/BaseContext.ts rename to plugins/catalog-backend/src/next/Context/BackgroundContext.ts index c9553cffd5..72b9a3b1ed 100644 --- a/plugins/catalog-backend/src/next/Context/BaseContext.ts +++ b/plugins/catalog-backend/src/next/Context/BackgroundContext.ts @@ -19,7 +19,7 @@ import { Context, ContextKey } from './types'; /** * A base Context implementation that does not hold any value. */ -export class BaseContext implements Context { +export class BackgroundContext implements Context { getContextValue(key: ContextKey): T { return key.defaultValue; } diff --git a/plugins/catalog-backend/src/next/Context/ContextWithValue.ts b/plugins/catalog-backend/src/next/Context/ContextWithValue.ts index 8e61e2c6f2..e8f94fd922 100644 --- a/plugins/catalog-backend/src/next/Context/ContextWithValue.ts +++ b/plugins/catalog-backend/src/next/Context/ContextWithValue.ts @@ -14,15 +14,14 @@ * limitations under the License. */ -import { BaseContext } from './BaseContext'; import { Context, ContextKey } from './types'; /** * A Context implementation that holds a single value, optionally extending an existing context. */ export class ContextWithValue implements Context { - static create(key: ContextKey, value: unknown, parent?: Context) { - return new ContextWithValue(parent ?? new BaseContext(), key, value); + static create(parent: Context, key: ContextKey, value: unknown) { + return new ContextWithValue(parent, key, value); } private constructor( diff --git a/plugins/catalog-backend/src/next/Context/TransactionContext.ts b/plugins/catalog-backend/src/next/Context/TransactionValue.ts similarity index 77% rename from plugins/catalog-backend/src/next/Context/TransactionContext.ts rename to plugins/catalog-backend/src/next/Context/TransactionValue.ts index 6ac50fbc07..6959d13a18 100644 --- a/plugins/catalog-backend/src/next/Context/TransactionContext.ts +++ b/plugins/catalog-backend/src/next/Context/TransactionValue.ts @@ -23,14 +23,14 @@ const transactionContextKey = new ContextKey( ); /** - * TransactionContext handles the wrapping of a knex transaction in a Context. + * TransactionValue handles the wrapping of a knex transaction in a Context. */ -export class TransactionContext { - static create(tx: Knex.Transaction, parent?: Context) { - return ContextWithValue.create(transactionContextKey, tx, parent); +export class TransactionValue { + static in(parent: Context, tx: Knex.Transaction) { + return ContextWithValue.create(parent, transactionContextKey, tx); } - static getTransaction(context: Context): Knex.Transaction { + static from(context: Context): Knex.Transaction { const transaction = context.getContextValue(transactionContextKey); if (!transaction) { throw new Error(`No transaction available in context`); diff --git a/plugins/catalog-backend/src/next/Context/index.ts b/plugins/catalog-backend/src/next/Context/index.ts index 992f5e89a6..61dd4a2958 100644 --- a/plugins/catalog-backend/src/next/Context/index.ts +++ b/plugins/catalog-backend/src/next/Context/index.ts @@ -14,8 +14,8 @@ * limitations under the License. */ -export { BaseContext } from './BaseContext'; +export { BackgroundContext } from './BackgroundContext'; export { ContextWithValue } from './ContextWithValue'; -export { TransactionContext } from './TransactionContext'; +export { TransactionValue } from './TransactionValue'; export { ContextKey } from './types'; export type { Context } from './types';