import { env } from "cloudflare:workers";
/**
* Artifacts rate-limits control-plane calls per namespace, so repositories can be spread over several
* namespaces, one binding each: shard 0 is `ARTIFACTS`, shard k is `ARTIFACTS_<k>`. The shard is encoded
* in the repository name (`r-<id>` for shard 0, `r<k>-<id>` otherwise), so existing repositories keep
* resolving no matter how many shards are configured. `ARTIFACTS_SHARDS` only decides where new
* repositories go; never remove a binding that still holds repositories.
*/
const NAME_PATTERN = /^r(\d*)-(.+)$/;
const FNV_OFFSET = 0x811c9dc5;
const FNV_PRIME = 0x01000193;
export function shardOfName(artifactsName: string): number {
const match = NAME_PATTERN.exec(artifactsName);
if (!match) return 0;
return match[1] ? Number(match[1]) : 0;
}
export function nameInShard(repoId: string, shard: number): string {
return shard === 0 ? `r-${repoId}` : `r${shard}-${repoId}`;
}
export function bindingNameForShard(shard: number): string {
return shard === 0 ? "ARTIFACTS" : `ARTIFACTS_${shard}`;
}
/** A stable shard for a new repository id, spread over `count` shards. */
export function pickShard(repoId: string, count: number): number {
if (count <= 1) return 0;
let hash = FNV_OFFSET;
for (let index = 0; index < repoId.length; index++) {
hash ^= repoId.charCodeAt(index);
hash = Math.imul(hash, FNV_PRIME) >>> 0;
}
return hash % count;
}
export function configuredShardCount(raw: string | undefined): number {
const count = Number(raw ?? "1");