unique constraint for registry_item - fixes #1121

we remove all duplicate items from the registry, keeping the
most-recently updated one (which presumably is the one that the users
expect to be used)

then we use `upsert` instead of the more complicated previous logic,
which was subject to races
This commit is contained in:
dakkar 2025-06-22 13:05:40 +01:00
parent a4c0ef824c
commit 3aa5ec713c
3 changed files with 32 additions and 29 deletions

View file

@ -27,34 +27,18 @@ export class RegistryApiService {
public async set(userId: MiUser['id'], domain: string | null, scope: string[], key: string, value: any) {
// TODO: 作成できるキーの数を制限する
const query = this.registryItemsRepository.createQueryBuilder('item');
if (domain) {
query.where('item.domain = :domain', { domain: domain });
} else {
query.where('item.domain IS NULL');
}
query.andWhere('item.userId = :userId', { userId: userId });
query.andWhere('item.key = :key', { key: key });
query.andWhere('item.scope = :scope', { scope: scope });
const existingItem = await query.getOne();
if (existingItem) {
await this.registryItemsRepository.update(existingItem.id, {
updatedAt: new Date(),
value: value,
});
} else {
await this.registryItemsRepository.insert({
id: this.idService.gen(),
updatedAt: new Date(),
userId: userId,
domain: domain,
scope: scope,
key: key,
value: value,
});
}
await this.registryItemsRepository.upsert({
id: this.idService.gen(),
updatedAt: new Date(),
userId: userId,
domain: domain,
scope: scope,
key: key,
value: value,
}, {
conflictPaths: ['userId', 'key', 'scope', 'domain'],
upsertType: 'on-conflict-do-update',
});
if (domain == null) {
// TODO: サードパーティアプリが傍受出来てしまうのでどうにかする