UNPKG

@clickup/pg-microsharding

Version:
267 lines (242 loc) 7.33 kB
import flatten from "lodash/flatten"; import sum from "lodash/sum"; import sumBy from "lodash/sumBy"; import { sprintf } from "sprintf-js"; import { pluralize } from "../../internal/pluralize"; import { rebalance } from "../rebalance"; test("real-life", async () => { runSnapshot("real-life", { m1: [], m2: [ 3102510, 2310389, 3431636, 2812913, 2809915, 3373267, 3533675, 2904572, 3028968, 3763126, 3330395, 5513279, 4499457, 2620674, 4204222, 3068099, 4044060, 2590400, 3398307, 3549054, 2705941, 2446029, 2543947, 3043896, 3185788, 3687653, 3011137, 3123301, 2968407, 2878138, 4008534, 2606604, 3583219, 3103622, 3296268, 2898755, 3429745, 2704922, 3047716, 4353234, 2977721, 2952326, 3165026, 5621594, 2866982, 2963043, 3029183, 3165786, ], m3: [], m4: [ 2941652, 2259896, 2897068, 2441056, 2173301, 2557906, 3189854, 3262413, 3596507, 2850071, 2742650, 3007119, 3146139, 2732076, 2782602, 2843946, 2971959, 2650268, 4630436, 2509163, 2823596, 2496160, 4094308, 3715544, 3780254, 2473756, 3902806, 3177622, 2752508, 2610157, 2460287, 3588799, 3315124, 3386548, 2841916, 3389682, 2882752, 2721151, 2898093, 2891522, 3063611, 2924353, 3016623, 2736916, 2567722, 2250799, 3290465, 2302616, 3266051, 2737137, 3368923, 2739823, 2457847, 2588240, 3388789, 3253895, 2748270, 2490298, 3042848, 2685534, 2657002, ], m5: [ 2402111, 3635241, 3494375, 4003589, 2644282, 3792954, 3031608, 2736750, 11682545, 2537989, 2789315, 3576189, 2573423, 2999839, 3195822, 2850765, 3003699, 2800095, 3373183, 3192320, 2466714, 3070357, 2320580, 2835098, 3759990, 2856268, 2578693, 2924938, 4521645, 2940125, 3526950, 2532835, 2867802, 2786013, 3572643, 3286283, 4558305, 6562024, 3357344, 2560850, 3622079, 2700293, 2638270, 2358971, 2690906, 2737271, 2679169, 2896335, 5173294, 3241496, 2641623, 2708660, 3026319, 3018266, 2776485, 3897435, 3933529, 2839020, 3071322, 4652406, 3633723, 3720616, 3242648, 2349381, 2801277, 3116048, 3872269, 3145946, 2958505, 3479378, 4414286, 3757053, 2871581, 2612754, 2440424, 2705234, 3717549, 4245181, 3699579, 2762198, 2877770, 2926338, 3206583, 3513134, 2683638, 2673500, 2367037, 2968401, 3413508, 2307521, 3420950, 2500139, 2308110, 2532689, 2875158, 3639822, 2573277, 2886183, 3512852, 3652854, 3666576, 2831328, ], m6: [ 3210829, 2599238, 3261651, 3013344, 2994142, 2817397, 2914849, 3466772, 2798274, 3160658, 4189071, 60846732, 2774519, 2921195, 3273649, 2762413, 3398789, 5174865, 3458114, 3212180, 3243874, 2420268, 2914613, 3460018, 3238051, 3099167, 3156420, 3208024, 3609000, 3743240, 3784360, 2959994, 2997000, 3412687, 2478898, 3143575, 3009686, 3180545, 3334735, 3322849, 3031021, 2760785, 3364934, 2902034, 2752392, 3147604, 2464625, 2488516, 2844696, 3120980, 2783978, 3106528, 2295123, 3116163, 2671385, 2900650, 2700870, 2613138, 2724027, 3489817, 3009028, 3005714, 2825044, 2761433, 2746928, 4153615, 3035247, 3166575, 3125205, 3486267, 3436957, 2730814, 3037462, 3305552, 2706198, 2957812, 3715174, 3008117, 3177874, 2779452, 3149109, 2842873, 3746175, 3403372, 2711371, 3976340, 3468210, 3180945, ], }); }); test("synthetic", async () => { runSnapshot("empty", {}); runSnapshot("no-op 1", { m1: [1], }); runSnapshot("no-op 2", { m1: [1], m2: [], }); runSnapshot("no-op 2", { m1: [], m2: [1], }); runSnapshot("move smallest out", { m1: [1, 2], m2: [], }); runSnapshot("move largest out", { m1: [1, 2, 3, 6], m2: [], }); runSnapshot("move many small out", { m1: [1, 2, 3, 7], m2: [], }); runSnapshot("huge microshards", { m1: [10000, 100, 1, 2, 3, 4, 5], m2: [], m3: [], m4: [], m5: [], }); runSnapshot("zero-weight microshards only", { m1: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], m2: [], m3: [], m4: [], }); runSnapshot("zero-weight microshards and non-empty", { m1: [1, 2, 3, 4, 5, 6, 0, 0, 0, 0, 0], m2: [], m3: [], m4: [], }); runSnapshot( "decommission of m2", { m1: [1, 2], m2: [3, 4], m3: [5, 6], }, ["m2"], ); runSnapshot( "decommission of m1 and m2", { m1: [1, 2], m2: [3, 4], m3: [5, 6], }, ["m1", "m2"], ); runSnapshot( "decommission of m1 while adding an empty m4", { m1: [101, 103], m2: [102, 102], m3: [103, 101], m4: [], }, ["m1"], ); runSnapshot( "decommission of m1 while adding empty m4 and m5", { m1: [101, 103], m2: [102, 102], m3: [103, 101], m4: [], m5: [], }, ["m1"], ); runSnapshot( "decommission of m1 and m2 while adding empty m4 and m5", { m1: [101, 103], m2: [102, 102], m3: [103, 101], m4: [], m5: [], }, ["m1", "m2"], ); runSnapshot( "decommission of m1 and m2 while adding an empty m4", { m1: [101, 103], m2: [102, 102], m3: [103, 101], m4: [], }, ["m1", "m2"], ); expect(() => runSnapshot( "bad decommission of all", { m1: [1, 2], m2: [3, 4], m3: [5, 6], }, ["m1", "m2", "m3"], ), ).toThrow(/all islands/); runSnapshot("two zero weight and two equal weight", { m1: [0, 134, 134, 0], m2: [], m3: [], m4: [], }); }); let counter = 0; function runSnapshot( name: string, islandsFrom: Record<string, number[]>, decommissionNames: string[] = [], ): void { const islandNames = Object.keys(islandsFrom); const islands = new Map( Object.values(islandsFrom).map((weights, islandNo) => [ islandNo, weights.map((weight) => ({ weight })), ]), ); const moves = rebalance( islands, decommissionNames.map((name) => islandNames.indexOf(name)), ); const islandsTo = Object.fromEntries( [...islands.entries()].map( ([islandNo, shards]) => [islandNames[islandNo], shards.map(({ weight }) => weight)] as const, ), ); const desiredWeight = islandNames.length > 0 ? sum(flatten(Object.values(islandsFrom))) / islandNames.length : 0; expect( "\n" + ` desiredWeight=${desiredWeight}\n` + "===\n" + inspectIslands(islandsFrom) + "==>\n" + inspectIslands(islandsTo) + "===\n" + " " + pluralize( sumBy(moves, ({ shards }) => shards.length), "move", ) + ":\n" + moves .map( ({ from, to, shards }) => ` - ${islandNames[from]}->${islandNames[to]}: [` + shards.map(({ weight }) => weight) + "]\n", ) .join(""), ).toMatchSnapshot(`${sprintf("%02d", counter++)}: ${name}`); } function inspectIslands(islands: Record<string, number[]>): string { const totalWeight = sum(flatten(Object.values(islands))) || 1; return Object.entries(islands) .map( ([islandName, weights]) => ` ${islandName}: sum=${sprintf("%-10d", sum(weights))} ` + `(${sprintf("%.2f", (sum(weights) / totalWeight) * 100)}%) ` + `[${weights}]\n`, ) .join(""); }