Skip to content

Commit 2ece99b

Browse files
authored
fix: Increment race condition (#182)
1 parent 2126de8 commit 2ece99b

File tree

3 files changed

+52
-3
lines changed

3 files changed

+52
-3
lines changed

docs/useRebar/document/document-global.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,27 @@ async function doSomething() {
6767
document.setBulk({ totalMoneyCreated: 200, totalMoneyDestroyed: 200 });
6868
}
6969
```
70+
71+
72+
### unset
73+
74+
Delete a specific field from the document.
75+
76+
```ts
77+
async function doSomething() {
78+
const document = await Rebar.document.global.useGlobal<MyDataType>('my-identifier-goes-here-for-my-document');
79+
document.unset('totalMoneyCreated');
80+
}
81+
```
82+
83+
### increment
84+
85+
Increment a specific field by a specific amount. It uses 1 as default amount.
86+
87+
```ts
88+
async function doSomething() {
89+
const document = await Rebar.document.global.useGlobal<MyDataType>('my-identifier-goes-here-for-my-document');
90+
document.increment('totalMoneyCreated'); // Increment by 1
91+
document.increment('totalMoneyCreated', 200); // Increment by 200
92+
}
93+
```

src/main/server/document/global.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,16 +61,43 @@ export async function useGlobal<T extends Object = Object>(identifier: string) {
6161
return await db.update({ _id: data[identifier]._id, ...newData }, CollectionNames.Global);
6262
}
6363

64+
/**
65+
* Unset a field from your global document
66+
*
67+
* @param {string} fieldName
68+
* @returns {Promise<boolean>}
69+
*/
6470
async function unset(fieldName: string): Promise<boolean> {
6571
delete data[identifier][fieldName];
6672
return await db.unset(identifier, [fieldName], CollectionNames.Global);
6773
}
6874

75+
/**
76+
* Increment a field in your global document
77+
*
78+
* @param {string} fieldName Field to increment
79+
* @param {number} value Value to increment by, defaults to 1
80+
* @returns {number} The new value of the field
81+
*/
82+
async function increment(fieldName: string, value: number = 1): Promise<number> {
83+
const client = await db.getClient();
84+
const updatedValue = await client
85+
.collection(CollectionNames.Global)
86+
.findOneAndUpdate(
87+
{ _id: data[identifier]._id },
88+
{ $inc: { [fieldName]: value } },
89+
{ upsert: true, returnDocument: 'after' },
90+
);
91+
data[identifier][fieldName] = updatedValue.value[fieldName];
92+
return data[identifier][fieldName];
93+
}
94+
6995
return {
7096
get,
7197
getField,
7298
set,
7399
setBulk,
74100
unset,
101+
increment,
75102
};
76103
}

src/main/server/document/increment.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,7 @@ async function init() {
1010

1111
export function useIncrementalId(key: string) {
1212
async function getNext() {
13-
const value: number = incremental.getField(key) ?? 0;
14-
await incremental.set(key, value + 1);
15-
return value + 1;
13+
return await incremental.increment(key);
1614
}
1715

1816
return {

0 commit comments

Comments
 (0)