diff --git a/src/internal/sharding/sharder.ts b/src/internal/sharding/sharder.ts index 71200fa52..0ba6bde59 100644 --- a/src/internal/sharding/sharder.ts +++ b/src/internal/sharding/sharder.ts @@ -1,4 +1,4 @@ -import { ResourceKind, ShardRow, ShardStatus } from './store' +import { ResourceKind, ShardRow, ShardStats, ShardStatus } from './store' export interface ShardResource { kind: ResourceKind @@ -7,6 +7,14 @@ export interface ShardResource { logicalName: string } +export interface ReservationResult { + reservationId: string + shardId: string + shardKey: string + slotNo: number + leaseExpiresAt: string +} + export interface Sharder { createShard(opts: { kind: ResourceKind @@ -17,26 +25,13 @@ export interface Sharder { setShardStatus(shardId: string | number, status: ShardStatus): Promise - reserve( - opts: ShardResource & { - kind: ResourceKind - tenantId: string - bucketName: string - logicalName: string - } - ): Promise<{ - reservationId: string - shardId: string - shardKey: string - slotNo: number - leaseExpiresAt: string - }> + reserve(opts: ShardResource): Promise confirm(reservationId: string, resource: ShardResource): Promise cancel(reservationId: string): Promise expireLeases(): Promise freeByLocation(shardId: string | number, slotNo: number): Promise freeByResource(shardId: string | number, resource: ShardResource): Promise - shardStats(kind?: ResourceKind): Promise + shardStats(kind?: ResourceKind): Promise findShardByResourceId(param: ShardResource): Promise listShardByKind(icebergTables: ResourceKind): Promise diff --git a/src/internal/sharding/store.ts b/src/internal/sharding/store.ts index dacd7b364..ff152db2b 100644 --- a/src/internal/sharding/store.ts +++ b/src/internal/sharding/store.ts @@ -25,6 +25,14 @@ export type ReservationRow = { created_at: string } +export type ShardStats = Array<{ + shardId: string + shardKey: string + capacity: number + used: number + free: number +}> + /** Factory that opens a transaction and passes a store bound to that tx */ export interface ShardStoreFactory { withTransaction(fn: (store: ShardStore) => Promise): Promise @@ -101,11 +109,7 @@ export interface ShardStore { findShardByResourceId(tenantId: string, resourceId: string): Promise // Stats - shardStats( - kind?: ResourceKind - ): Promise< - Array<{ shardId: string; shardKey: string; capacity: number; used: number; free: number }> - > + shardStats(kind?: ResourceKind): Promise findShardById(shardId: number): Promise } diff --git a/src/internal/sharding/strategy/single-shard.ts b/src/internal/sharding/strategy/single-shard.ts index 21fa49ea6..1b8e8345d 100644 --- a/src/internal/sharding/strategy/single-shard.ts +++ b/src/internal/sharding/strategy/single-shard.ts @@ -1,5 +1,5 @@ -import { ResourceKind, ShardRow, ShardStatus } from '@internal/sharding/store' -import { Sharder, ShardResource } from '../sharder' +import { ResourceKind, ShardRow, ShardStats, ShardStatus } from '@internal/sharding/store' +import { ReservationResult, Sharder, ShardResource } from '../sharder' export class SingleShard implements Sharder { constructor( @@ -9,7 +9,7 @@ export class SingleShard implements Sharder { } ) {} - listShardByKind(): Promise { + listShardByKind(_kind: ResourceKind): Promise { return Promise.resolve([ { id: 1, @@ -23,32 +23,34 @@ export class SingleShard implements Sharder { ]) } - shardStats(): Promise { - return Promise.resolve({ - shardId: 1, - shardKey: this.singleShard.shardKey, - capacity: this.singleShard.capacity, - used: -1, - free: -1, - }) + shardStats(_kind?: ResourceKind): Promise { + return Promise.resolve([ + { + shardId: '1', + shardKey: this.singleShard.shardKey, + capacity: this.singleShard.capacity, + used: -1, + free: -1, + }, + ]) } - withTnx(): Sharder { + withTnx(_tnx: unknown): Sharder { return new SingleShard({ shardKey: this.singleShard.shardKey, capacity: this.singleShard.capacity, }) } - freeByResource(): Promise { + freeByResource(_shardId: string | number, _resource: ShardResource): Promise { return Promise.resolve() } - cancel(): Promise { + cancel(_reservationId: string): Promise { return Promise.resolve(undefined) } - confirm(): Promise { + confirm(_reservationId: string, _resource: ShardResource): Promise { return Promise.resolve(undefined) } @@ -85,31 +87,21 @@ export class SingleShard implements Sharder { }) } - freeByLocation(): Promise { + freeByLocation(_shardId: string | number, _slotNo: number): Promise { return Promise.resolve(undefined) } - reserve(): Promise<{ - reservationId: string - shardId: string - shardKey: string - slotNo: number - leaseExpiresAt: string - }> { + reserve(_opts: ShardResource): Promise { return Promise.resolve({ leaseExpiresAt: '', reservationId: '', - shardId: this.singleShard.shardKey, + shardId: '1', shardKey: this.singleShard.shardKey, slotNo: 0, }) } - setShardStatus(): Promise { - return Promise.resolve(undefined) - } - - shardStatsByKind(): Promise { + setShardStatus(_shardId: string | number, _status: ShardStatus): Promise { return Promise.resolve(undefined) } } diff --git a/src/test/sharding.test.ts b/src/test/sharding.test.ts index cd8921b5e..d0e76e6f5 100644 --- a/src/test/sharding.test.ts +++ b/src/test/sharding.test.ts @@ -2,7 +2,7 @@ import { multitenantKnex } from '@internal/database' import { runMultitenantMigrations } from '@internal/database/migrations' -import { KnexShardStoreFactory, ShardCatalog } from '@internal/sharding' +import { KnexShardStoreFactory, ShardCatalog, SingleShard } from '@internal/sharding' import { ExpiredReservationError, NoActiveShardError, @@ -798,3 +798,22 @@ describe('Sharding System', () => { }) }) }) + +describe('SingleShard', () => { + it('returns shard stats in the canonical array shape', async () => { + const sharder = new SingleShard({ + shardKey: 'single-shard-key', + capacity: 25, + }) + + await expect(sharder.shardStats()).resolves.toEqual([ + { + shardId: '1', + shardKey: 'single-shard-key', + capacity: 25, + used: -1, + free: -1, + }, + ]) + }) +})