fix: 原子化NapCat WebUI票据兑换
This commit is contained in:
parent
6f23db64be
commit
8ee7866afe
@ -35,14 +35,13 @@ export class NapcatWebuiGatewayTicketService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Redeems a ticket once by deleting the Redis key before returning the session id.
|
||||
* Redeems a ticket once with Redis GETDEL so deletion happens before returning.
|
||||
* @param ticket - Opaque ticket from the bootstrap iframe URL.
|
||||
* @returns Session id when the ticket existed, otherwise undefined.
|
||||
*/
|
||||
async redeem(ticket: string) {
|
||||
const key = this.ticketKey(ticket);
|
||||
const sessionId = await this.redis.get(key);
|
||||
await this.redis.del(key);
|
||||
const sessionId = await this.redis.getdel(key);
|
||||
return sessionId || undefined;
|
||||
}
|
||||
|
||||
|
||||
@ -116,6 +116,19 @@ class FakeRedis {
|
||||
return this.values.get(key) ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically reads and deletes one key from the fake Redis store.
|
||||
* @param key - Redis key to consume.
|
||||
* @returns Stored value before deletion or null.
|
||||
*/
|
||||
async getdel(key: string) {
|
||||
this.calls.push(`getdel:${key}`);
|
||||
const value = this.values.get(key) ?? null;
|
||||
this.values.delete(key);
|
||||
this.ttl.delete(key);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes one or more keys from the fake Redis store.
|
||||
* @param keys - Redis keys to delete.
|
||||
@ -318,13 +331,16 @@ describe('NapcatWebuiGatewayTicketService', () => {
|
||||
|
||||
expect(sessionId).toBe('session-1');
|
||||
expect(secondRedeem).toBeUndefined();
|
||||
expect(redis.values.get(`napcat:webui:ticket:${ticket}`)).toBeUndefined();
|
||||
expect(redis.calls).toEqual(
|
||||
expect.arrayContaining([
|
||||
`get:napcat:webui:ticket:${ticket}`,
|
||||
`del:napcat:webui:ticket:${ticket}`,
|
||||
]),
|
||||
);
|
||||
const ticketKey = `napcat:webui:ticket:${ticket}`;
|
||||
const ticketCalls = redis.calls.filter((call) => call.includes(ticketKey));
|
||||
expect(redis.values.get(ticketKey)).toBeUndefined();
|
||||
expect(ticketCalls).toEqual([
|
||||
`set:${ticketKey}:PX:60000`,
|
||||
`getdel:${ticketKey}`,
|
||||
`getdel:${ticketKey}`,
|
||||
]);
|
||||
expect(ticketCalls).not.toContain(`get:${ticketKey}`);
|
||||
expect(ticketCalls).not.toContain(`del:${ticketKey}`);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user