Skip to content

Commit 076e740

Browse files
authored
fix: use a forked EntityManager for each transaction (#12)(@corbt)
Currently, a global EntityManager is used for every operation. This causes an error that can be resolved by setting `allowGlobalContext: true`. But that isn't a great fix, because if you ever make an edit to an entity that fails, you'll never be able to make another change because the global context caches the failed change and never releases it.
1 parent d7a704e commit 076e740

File tree

1 file changed

+13
-7
lines changed

1 file changed

+13
-7
lines changed

src/Resource.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ export class Resource extends BaseResource {
7474
}
7575

7676
public async count(filter: Filter): Promise<number> {
77-
return this.orm.em.getRepository(this.model).count(
77+
return this.orm.em.fork().getRepository(this.model).count(
7878
convertFilter(filter),
7979
);
8080
}
@@ -84,6 +84,7 @@ export class Resource extends BaseResource {
8484
const { direction, sortBy } = sort as { direction: 'asc' | 'desc', sortBy: string };
8585

8686
const results = await this.orm.em
87+
.fork()
8788
.getRepository(this.model)
8889
.find(
8990
convertFilter(filter), {
@@ -100,6 +101,7 @@ export class Resource extends BaseResource {
100101

101102
public async findOne(id: string | number): Promise<BaseRecord | null> {
102103
const result = await this.orm.em
104+
.fork()
103105
.getRepository(this.model)
104106
.findOne(id as any); // mikroorm has incorrect types for `findOne`
105107

@@ -115,34 +117,37 @@ export class Resource extends BaseResource {
115117
if (!pk) return [];
116118

117119
const results = await this.orm.em
120+
.fork()
118121
.getRepository(this.model)
119122
.find({ [pk]: { $in: ids } });
120123

121124
return results.map((result) => new BaseRecord(wrap(result).toJSON(), this));
122125
}
123126

124127
public async create(params: Record<string, any>): Promise<Record<string, any>> {
125-
const instance = this.orm.em
128+
const em = this.orm.em.fork();
129+
const instance = em
126130
.getRepository(this.model)
127131
.create(flat.unflatten(params));
128132

129-
await this.validateAndSave(instance);
133+
await this.validateAndSave(instance, em);
130134

131135
const returnedParams: Record<string, any> = flat.flatten(wrap(instance).toJSON());
132136

133137
return returnedParams;
134138
}
135139

136140
public async update(pk: string | number, params: Record<string, any> = {}): Promise<Record<string, any>> {
137-
const instance = await this.orm.em
141+
const em = this.orm.em.fork();
142+
const instance = await em
138143
.getRepository(this.model)
139144
.findOne(pk as any); // mikroorm has incorrect types for findOneOrFail
140145

141146
if (!instance) throw new Error('Record to update not found');
142147

143148
const updatedInstance = wrap(instance).assign(flat.unflatten(params));
144149

145-
await this.validateAndSave(updatedInstance);
150+
await this.validateAndSave(updatedInstance, em);
146151

147152
const returnedParams: Record<string, any> = flat.flatten(wrap(updatedInstance).toJSON());
148153

@@ -151,6 +156,7 @@ export class Resource extends BaseResource {
151156

152157
public async delete(id: string | number): Promise<void> {
153158
await this.orm.em
159+
.fork()
154160
.getRepository(this.model)
155161
.nativeDelete(id as any); // mikroorm has incorrect types for nativeDelete
156162
}
@@ -161,7 +167,7 @@ export class Resource extends BaseResource {
161167
return !!model?.name && !!orm?.getMetadata?.().find?.(model.name);
162168
}
163169

164-
async validateAndSave(instance: Loaded<AnyEntity>): Promise<void> {
170+
async validateAndSave(instance: Loaded<AnyEntity>, em: EntityManager): Promise<void> {
165171
if (Resource.validate) {
166172
const errors = await Resource.validate(instance);
167173
if (errors && errors.length) {
@@ -179,7 +185,7 @@ export class Resource extends BaseResource {
179185
}
180186
}
181187
try {
182-
await this.orm.em.persistAndFlush(instance);
188+
await em.persistAndFlush(instance);
183189
} catch (error) {
184190
// TODO: figure out how to get column name from MikroORM's error metadata
185191
// It currently seems to return only whole Entity

0 commit comments

Comments
 (0)