1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-09-05 17:53:12 +02:00

feat: transaction grouping, use ulids and strings (#10230)

Replace generating random number id based on timestamp and now use
ulids.
This commit is contained in:
Jaanus Sellin 2025-06-27 11:45:17 +03:00 committed by GitHub
parent 8c1c9076b3
commit c5b6ee75f3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 20 additions and 16 deletions

View File

@ -88,8 +88,8 @@ describe('transaction utilities', () => {
expect(mockTransaction.userParams).toBeDefined(); expect(mockTransaction.userParams).toBeDefined();
expect(mockTransaction.userParams.type).toBe('transaction'); expect(mockTransaction.userParams.type).toBe('transaction');
expect(mockTransaction.userParams.value).toBeDefined(); expect(mockTransaction.userParams.id).toBeDefined();
expect(typeof mockTransaction.userParams.value).toBe('number'); expect(typeof mockTransaction.userParams.id).toBe('string');
}); });
it('should use provided transactionContext when given', async () => { it('should use provided transactionContext when given', async () => {
@ -99,7 +99,7 @@ describe('transaction utilities', () => {
); );
const customContext: TransactionUserParams = { const customContext: TransactionUserParams = {
type: 'change-request', type: 'change-request',
value: 42, id: '01HQVX5K8P9EXAMPLE123456',
}; };
await serviceWithTransactional.transactional((service) => { await serviceWithTransactional.transactional((service) => {
@ -108,28 +108,33 @@ describe('transaction utilities', () => {
expect(mockTransaction.userParams).toEqual(customContext); expect(mockTransaction.userParams).toEqual(customContext);
expect(mockTransaction.userParams.type).toBe('change-request'); expect(mockTransaction.userParams.type).toBe('change-request');
expect(mockTransaction.userParams.value).toBe(42); expect(mockTransaction.userParams.id).toBe(
'01HQVX5K8P9EXAMPLE123456',
);
}); });
it('should generate unique numeric IDs for default context', async () => { it('should generate unique ULID strings for default context', async () => {
const serviceWithTransactional = withTransactional( const serviceWithTransactional = withTransactional(
mockServiceFactory, mockServiceFactory,
mockDb, mockDb,
); );
const userParamsValues: number[] = []; const userParamsIds: string[] = [];
for (let i = 0; i < 3; i++) { for (let i = 0; i < 3; i++) {
await serviceWithTransactional.transactional((service) => { await serviceWithTransactional.transactional((service) => {
userParamsValues.push(mockTransaction.userParams.value); userParamsIds.push(mockTransaction.userParams.id);
return service.getData(); return service.getData();
}); });
} }
expect(userParamsValues).toHaveLength(3); expect(userParamsIds).toHaveLength(3);
expect(userParamsValues.every((id) => typeof id === 'number')).toBe( expect(userParamsIds.every((id) => typeof id === 'string')).toBe(
true, true,
); );
expect(new Set(userParamsValues).size).toBe(3); expect(new Set(userParamsIds).size).toBe(3);
userParamsIds.forEach((id) => {
expect(id).toMatch(/^[0-9A-HJKMNP-TV-Z]{26}$/);
});
}); });
it('should create transactional service with transaction instance', async () => { it('should create transactional service with transaction instance', async () => {

View File

@ -1,15 +1,14 @@
import type { Knex } from 'knex'; import type { Knex } from 'knex';
import type { IUnleashConfig } from '../types/index.ts'; import type { IUnleashConfig } from '../types/index.ts';
import { ulid } from 'ulidx';
export interface TransactionUserParams { export interface TransactionUserParams {
type: 'change-request' | 'transaction'; type: 'change-request' | 'transaction';
value: number; id: string;
} }
function generateNumericTransactionId(): number { function generateTransactionId(): string {
const timestamp = Date.now(); return ulid();
const random = Math.floor(Math.random() * 1000);
return timestamp * 1000 + random;
} }
export type KnexTransaction = Knex.Transaction; export type KnexTransaction = Knex.Transaction;
@ -96,7 +95,7 @@ export function withTransactional<S>(
db.transaction(async (trx: Knex.Transaction) => { db.transaction(async (trx: Knex.Transaction) => {
const defaultContext: TransactionUserParams = { const defaultContext: TransactionUserParams = {
type: 'transaction', type: 'transaction',
value: generateNumericTransactionId(), id: generateTransactionId(),
}; };
trx.userParams = transactionContext || defaultContext; trx.userParams = transactionContext || defaultContext;