diff --git a/plugins/catalog-backend/src/next/Context/BackgroundContext.ts b/plugins/catalog-backend/src/next/Context/BackgroundContext.ts new file mode 100644 index 0000000000..72b9a3b1ed --- /dev/null +++ b/plugins/catalog-backend/src/next/Context/BackgroundContext.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 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 new file mode 100644 index 0000000000..e8f94fd922 --- /dev/null +++ b/plugins/catalog-backend/src/next/Context/ContextWithValue.ts @@ -0,0 +1,39 @@ +/* + * 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 Context implementation that holds a single value, optionally extending an existing context. + */ +export class ContextWithValue implements Context { + static create(parent: Context, key: ContextKey, value: unknown) { + return new ContextWithValue(parent, 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/TransactionValue.ts b/plugins/catalog-backend/src/next/Context/TransactionValue.ts new file mode 100644 index 0000000000..6959d13a18 --- /dev/null +++ b/plugins/catalog-backend/src/next/Context/TransactionValue.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, +); + +/** + * TransactionValue handles the wrapping of a knex transaction in a Context. + */ +export class TransactionValue { + static in(parent: Context, tx: Knex.Transaction) { + return ContextWithValue.create(parent, transactionContextKey, tx); + } + + static from(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..61dd4a2958 --- /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 { BackgroundContext } from './BackgroundContext'; +export { ContextWithValue } from './ContextWithValue'; +export { TransactionValue } from './TransactionValue'; +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; +}