-
Notifications
You must be signed in to change notification settings - Fork 344
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
89b5289
commit dbf5a10
Showing
15 changed files
with
409 additions
and
64 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
93 changes: 93 additions & 0 deletions
93
apps/segment/src/lib/dynamodb/segment-config-repository.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
import { GetItemCommand, PutItemCommand } from "dynamodb-toolbox"; | ||
import { err, ok, ResultAsync } from "neverthrow"; | ||
|
||
import { BaseError } from "@/errors"; | ||
import { createLogger } from "@/logger"; | ||
|
||
import { SegmentConfigEntity, SegmentConfigTable } from "./segment-config-table"; | ||
|
||
export class SegmentConfigRepository { | ||
private logger = createLogger("SegmentConfigRepository"); | ||
|
||
static ReadEntityError = BaseError.subclass("ReadEntityError"); | ||
static WriteEntityError = BaseError.subclass("WriteEntityError"); | ||
|
||
constructor( | ||
private deps: { | ||
segmentConfigEntity: SegmentConfigEntity; | ||
}, | ||
) {} | ||
|
||
async getConfig(args: { appId: string; saleorApiUrl: string; configKey: string }) { | ||
const getEntryResult = await ResultAsync.fromPromise( | ||
this.deps.segmentConfigEntity | ||
.build(GetItemCommand) | ||
.key({ | ||
PK: SegmentConfigTable.getConfigPrimaryKey({ | ||
saleorApiUrl: args.saleorApiUrl, | ||
appId: args.appId, | ||
}), | ||
SK: SegmentConfigTable.getConfigSortKey({ | ||
configKey: args.configKey, | ||
}), | ||
}) | ||
.send(), | ||
(error) => | ||
new SegmentConfigRepository.ReadEntityError("Failed to read APL entity", { cause: error }), | ||
); | ||
|
||
if (getEntryResult.isErr()) { | ||
this.logger.error("Error while reading config entity from DynamoDB", { | ||
error: getEntryResult.error, | ||
}); | ||
|
||
return err(getEntryResult.error); | ||
} | ||
|
||
if (!getEntryResult.value.Item) { | ||
this.logger.warn("Config entry not found", { args }); | ||
|
||
return err(new SegmentConfigRepository.ReadEntityError("Config entry not found")); | ||
} | ||
|
||
return ok(getEntryResult.value.Item); | ||
} | ||
|
||
async setConfig(args: { | ||
appId: string; | ||
saleorApiUrl: string; | ||
configKey: string; | ||
configValue: string; | ||
}) { | ||
const setEntryResult = await ResultAsync.fromPromise( | ||
this.deps.segmentConfigEntity | ||
.build(PutItemCommand) | ||
.item({ | ||
PK: SegmentConfigTable.getConfigPrimaryKey({ | ||
saleorApiUrl: args.saleorApiUrl, | ||
appId: args.appId, | ||
}), | ||
SK: SegmentConfigTable.getConfigSortKey({ | ||
configKey: args.configKey, | ||
}), | ||
// TODO: encrypt this value | ||
value: args.configValue, | ||
}) | ||
.send(), | ||
(error) => | ||
new SegmentConfigRepository.WriteEntityError("Failed to write config entity", { | ||
cause: error, | ||
}), | ||
); | ||
|
||
if (setEntryResult.isErr()) { | ||
this.logger.error("Error while putting config into DynamoDB", { | ||
error: setEntryResult.error, | ||
}); | ||
|
||
return err(setEntryResult.error); | ||
} | ||
|
||
return ok(undefined); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
68 changes: 68 additions & 0 deletions
68
apps/segment/src/modules/configuration/dynamodb-config-manager.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import { DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb"; | ||
|
||
import { BaseError } from "@/errors"; | ||
import { SegmentConfigRepository } from "@/lib/dynamodb/segment-config-repository"; | ||
import { | ||
SegmentConfigTable, | ||
SegmentConfigTableEntityFactory, | ||
} from "@/lib/dynamodb/segment-config-table"; | ||
|
||
import { AppConfig } from "./app-config"; | ||
|
||
export interface UpdatedAppConfigMetadataManager { | ||
// TODO: add get and create or get - to be discussed | ||
get(args: { saleorApiUrl: string; appId: string }): Promise<AppConfig>; | ||
set(args: { config: AppConfig; saleorApiUrl: string; appId: string }): Promise<void>; | ||
} | ||
|
||
export class DynamoDBConfigManager implements UpdatedAppConfigMetadataManager { | ||
private segmentConfigRepository: SegmentConfigRepository; | ||
|
||
public readonly configKey = "app-config-v1"; | ||
|
||
constructor({ | ||
documentClient, | ||
tableName, | ||
}: { | ||
documentClient: DynamoDBDocumentClient; | ||
tableName: string; | ||
}) { | ||
const table = SegmentConfigTable.create({ | ||
tableName, | ||
documentClient, | ||
}); | ||
|
||
const segmentConfigEntity = SegmentConfigTableEntityFactory.createConfigEntity(table); | ||
|
||
this.segmentConfigRepository = new SegmentConfigRepository({ segmentConfigEntity }); | ||
} | ||
|
||
async get(args: { saleorApiUrl: string; appId: string }): Promise<AppConfig> { | ||
const possibleResult = await this.segmentConfigRepository.getConfig({ | ||
saleorApiUrl: args.saleorApiUrl, | ||
appId: args.appId, | ||
configKey: this.configKey, | ||
}); | ||
|
||
if (possibleResult.isErr()) { | ||
// TODO: what do there? | ||
return new AppConfig(); | ||
} | ||
|
||
return AppConfig.parse(possibleResult.value.value); | ||
} | ||
async set(args: { config: AppConfig; saleorApiUrl: string; appId: string }): Promise<void> { | ||
const possibleResult = await this.segmentConfigRepository.setConfig({ | ||
appId: args.appId, | ||
saleorApiUrl: args.saleorApiUrl, | ||
configKey: this.configKey, | ||
configValue: args.config.serialize(), | ||
}); | ||
|
||
if (possibleResult.isErr()) { | ||
throw new BaseError("Failed to set config entry"); | ||
} | ||
|
||
return undefined; | ||
} | ||
} |
Oops, something went wrong.