Skip to content

Commit 6f0040e

Browse files
committed
spicedb timeout
1 parent ce8f9a9 commit 6f0040e

File tree

1 file changed

+50
-22
lines changed

1 file changed

+50
-22
lines changed

components/server/src/authorization/spicedb-authorizer.ts

Lines changed: 50 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ export class SpiceDBAuthorizer {
4343
const timer = spicedbClientLatency.startTimer();
4444
let error: Error | undefined;
4545
try {
46-
const response = await this.client.checkPermission(req);
46+
const response = await timeout(this.client.checkPermission(req), 5000);
4747
const permitted = response.permissionship === v1.CheckPermissionResponse_Permissionship.HAS_PERMISSION;
4848

4949
return permitted;
@@ -68,10 +68,13 @@ export class SpiceDBAuthorizer {
6868
const timer = spicedbClientLatency.startTimer();
6969
let error: Error | undefined;
7070
try {
71-
const response = await this.client.writeRelationships(
72-
v1.WriteRelationshipsRequest.create({
73-
updates,
74-
}),
71+
const response = await timeout(
72+
this.client.writeRelationships(
73+
v1.WriteRelationshipsRequest.create({
74+
updates,
75+
}),
76+
),
77+
5000,
7578
);
7679
log.info("[spicedb] Successfully wrote relationships.", { response, updates });
7780

@@ -86,28 +89,34 @@ export class SpiceDBAuthorizer {
8689
}
8790

8891
async deleteRelationships(req: v1.DeleteRelationshipsRequest): Promise<v1.ReadRelationshipsResponse[]> {
89-
if (!this.client) {
92+
const client = this.client;
93+
if (!client) {
9094
return [];
9195
}
9296
const timing = startTimer();
9397

9498
const timer = spicedbClientLatency.startTimer();
9599
let error: Error | undefined;
96100
try {
97-
const existing = await this.client.readRelationships(v1.ReadRelationshipsRequest.create(req));
98-
if (existing.length > 0) {
99-
const response = await this.client.deleteRelationships(req);
100-
const after = await this.client.readRelationships(v1.ReadRelationshipsRequest.create(req));
101-
if (after.length > 0) {
102-
log.error("[spicedb] Failed to delete relationships.", { existing, after, request: req });
103-
}
104-
log.info(`[spicedb] Successfully deleted ${existing.length} relationships.`, {
105-
response,
106-
request: req,
107-
existing,
108-
});
109-
}
110-
return existing;
101+
return await timeout(
102+
(async () => {
103+
const existing = await client.readRelationships(v1.ReadRelationshipsRequest.create(req));
104+
if (existing.length > 0) {
105+
const response = await client.deleteRelationships(req);
106+
const after = await client.readRelationships(v1.ReadRelationshipsRequest.create(req));
107+
if (after.length > 0) {
108+
log.error("[spicedb] Failed to delete relationships.", { existing, after, request: req });
109+
}
110+
log.info(`[spicedb] Successfully deleted ${existing.length} relationships.`, {
111+
response,
112+
request: req,
113+
existing,
114+
});
115+
}
116+
return existing;
117+
})(),
118+
5000,
119+
);
111120
} catch (err) {
112121
error = err;
113122
// While in we're running two authorization systems in parallel, we do not hard fail on writes.
@@ -132,6 +141,25 @@ function startTimer() {
132141
}
133142

134143
function stopTimer(method: string, hrtime: [number, number]) {
135-
const seconds = (hrtime[0] + hrtime[1] / 1e6).toFixed(3);
136-
log.info(`[SPICEDB] ${method} (${seconds} ms)`);
144+
const endTime = process.hrtime(hrtime);
145+
const ms = (endTime[0] * 1000 + endTime[1] / 1e6).toFixed(3);
146+
log.info(`[SPICEDB] ${method} (${ms} ms)`);
147+
}
148+
149+
async function timeout<T>(code: Promise<T>, ms: number): Promise<T> {
150+
return new Promise<T>((resolve, reject) => {
151+
const timer = setTimeout(() => {
152+
reject(new Error(`[spicedb] timed out after ${ms}ms`));
153+
}, ms);
154+
code.then(
155+
(res) => {
156+
clearTimeout(timer);
157+
resolve(res);
158+
},
159+
(err) => {
160+
clearTimeout(timer);
161+
reject(err);
162+
},
163+
);
164+
});
137165
}

0 commit comments

Comments
 (0)