Skip to content

Commit 19b41ea

Browse files
committed
Rewrite Gel currentUser global provider logic to use SessionHost
The former impl was nice because it was decoupled from Gel driver logic. But it was a lot of logic to figure out this "current user" from the `ExecutionContext`, and that would've felt really bad to couple to the DB layer. Mainly the former impl doesn't work going forward, because it assumed the session would not change within the GQL operation. This is one of the main features we're making room for. So now that the session can change, we don't know when to read what the current user should be. We need to take the current ALS value right when the query is being executed. Now that we're slicing the layers differently, giving the session/"current user" its own holder (ALS), we don't have to "dig deep" into the `ExecutionContext` to pull out this value. Coupling this `SessionHost` to the `Gel` service is less painful than it would've been previously and allows us to read the current ALS value right when needed. Perhaps there is another way to decouple this later. Maybe with some query events/hooks?
1 parent c19fd70 commit 19b41ea

File tree

3 files changed

+21
-90
lines changed

3 files changed

+21
-90
lines changed

src/components/authentication/authentication.module.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import { AuthenticationGelRepository } from './authentication.gel.repository';
88
import { AuthenticationRepository } from './authentication.repository';
99
import { AuthenticationService } from './authentication.service';
1010
import { CryptoService } from './crypto.service';
11-
import { GelCurrentUserProvider } from './current-user.provider';
1211
import {
1312
LoginExtraInfoResolver,
1413
RegisterExtraInfoResolver,
@@ -41,8 +40,6 @@ import { SessionResolver } from './session.resolver';
4140
CryptoService,
4241
SessionInterceptor,
4342
{ provide: APP_INTERCEPTOR, useExisting: SessionInterceptor },
44-
GelCurrentUserProvider,
45-
{ provide: APP_INTERCEPTOR, useExisting: GelCurrentUserProvider },
4643
{ provide: SessionHost, useClass: SessionHostImpl },
4744
SessionPipe,
4845
],

src/components/authentication/current-user.provider.ts

Lines changed: 0 additions & 85 deletions
This file was deleted.

src/core/gel/gel.service.ts

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
/* eslint-disable @typescript-eslint/unified-signatures */
22
import { Injectable, Optional } from '@nestjs/common';
3+
import { isUUID } from 'class-validator';
34
import { type $, type Executor } from 'gel';
45
import { type QueryArgs } from 'gel/dist/ifaces';
56
import { TraceLayer } from '~/common';
67
import { retry, type RetryOptions } from '~/common/retry';
78
import { TracingService } from '~/core/tracing';
9+
import { SessionHost } from '../../components/authentication/session.host';
810
import { TypedEdgeQL } from './edgeql';
911
import { cleanError } from './errors';
1012
import { InlineQueryRuntimeMap } from './generated-client/inline-queries';
@@ -21,6 +23,7 @@ export class Gel {
2123
private readonly transactionContext: TransactionContext,
2224
private readonly optionsContext: OptionsContext,
2325
private readonly tracing: TracingService,
26+
private readonly sessionHost: SessionHost,
2427
@Optional() private readonly childOptions: ApplyOptions[] = [],
2528
@Optional() private childExecutor?: Executor,
2629
) {}
@@ -31,6 +34,7 @@ export class Gel {
3134
this.transactionContext,
3235
this.optionsContext,
3336
this.tracing,
37+
this.sessionHost,
3438
[...this.childOptions],
3539
this.childExecutor,
3640
);
@@ -111,6 +115,11 @@ export class Gel {
111115
const queryNames = getCurrentQueryNames();
112116
const traceName = queryNames?.xray ?? 'Query';
113117

118+
let currentActorId = this.sessionHost.current$.value?.userId;
119+
// TODO temporarily check if UUID before applying global.
120+
// Once migration is complete this can be removed.
121+
currentActorId = isUUID(currentActorId) ? currentActorId : undefined;
122+
114123
return await this.tracing.capture(traceName, async (segment) => {
115124
// Show this segment separately in the service map
116125
segment.namespace = 'remote';
@@ -122,8 +131,18 @@ export class Gel {
122131
};
123132

124133
return await this.usingOptions(
125-
(opts) =>
126-
opts.tag || !queryNames ? opts : opts.withQueryTag(queryNames.gel),
134+
(opts) => {
135+
if (queryNames && !opts.tag) {
136+
opts = opts.withQueryTag(queryNames.gel);
137+
}
138+
// TODO sync caching strategy with the solution that resolves
139+
// https://github.com/geldata/gel-js/issues/1280
140+
if (currentActorId && !opts.globals.get('currentActorId')) {
141+
opts = opts.withGlobals({ currentActorId });
142+
}
143+
144+
return opts;
145+
},
127146
() => this.doRun(query, args),
128147
);
129148
});

0 commit comments

Comments
 (0)