chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
import { redisTest } from "@internal/testcontainers";
|
||||
import { subDays } from "date-fns";
|
||||
import Redis from "ioredis";
|
||||
import { describe, expect, vi } from "vitest";
|
||||
import { DevPresence } from "~/presenters/v3/DevPresence.server";
|
||||
|
||||
vi.setConfig({ testTimeout: 30_000 });
|
||||
|
||||
let seq = 0;
|
||||
function ids() {
|
||||
seq += 1;
|
||||
return { userId: `user_${seq}`, projectId: `proj_${seq}` };
|
||||
}
|
||||
const recentKey = (userId: string, projectId: string) => `dev-recent:${userId}:${projectId}`;
|
||||
|
||||
describe("DevPresence — recency ZSET", () => {
|
||||
redisTest(
|
||||
"getRecentBranchIds returns an empty map when nothing has pinged",
|
||||
async ({ redisOptions }) => {
|
||||
const presence = new DevPresence(redisOptions);
|
||||
const { userId, projectId } = ids();
|
||||
|
||||
const result = await presence.getRecentBranchIds(userId, projectId);
|
||||
expect(result.size).toBe(0);
|
||||
}
|
||||
);
|
||||
|
||||
redisTest("a ping records the branch as recently active", async ({ redisOptions }) => {
|
||||
const presence = new DevPresence(redisOptions);
|
||||
const { userId, projectId } = ids();
|
||||
|
||||
await presence.setConnected({ userId, projectId, environmentId: "env_a", ttl: 60 });
|
||||
|
||||
const result = await presence.getRecentBranchIds(userId, projectId);
|
||||
expect([...result.keys()]).toEqual(["env_a"]);
|
||||
expect(result.get("env_a")).toBeInstanceOf(Date);
|
||||
});
|
||||
|
||||
redisTest("debounces to at most one ZADD per env per minute", async ({ redisOptions }) => {
|
||||
const presence = new DevPresence(redisOptions);
|
||||
const redis = new Redis(redisOptions);
|
||||
const { userId, projectId } = ids();
|
||||
|
||||
// First ping records env_a.
|
||||
await presence.setConnected({ userId, projectId, environmentId: "env_a", ttl: 60 });
|
||||
|
||||
// Simulate the entry being removed (e.g. another reader pruned it) while the
|
||||
// 60s debounce touch key is still live.
|
||||
await redis.zrem(recentKey(userId, projectId), "env_a");
|
||||
|
||||
// A second ping within the debounce window must NOT re-add it.
|
||||
await presence.setConnected({ userId, projectId, environmentId: "env_a", ttl: 60 });
|
||||
|
||||
const result = await presence.getRecentBranchIds(userId, projectId);
|
||||
expect(result.has("env_a")).toBe(false);
|
||||
|
||||
await redis.quit();
|
||||
});
|
||||
|
||||
redisTest("does not return entries older than the recency window", async ({ redisOptions }) => {
|
||||
const presence = new DevPresence(redisOptions);
|
||||
const redis = new Redis(redisOptions);
|
||||
const { userId, projectId } = ids();
|
||||
const key = recentKey(userId, projectId);
|
||||
|
||||
const fourDaysAgo = subDays(Date.now(), 4).getTime();
|
||||
const oneHourAgo = Date.now() - 60 * 60 * 1000;
|
||||
await redis.zadd(key, fourDaysAgo, "env_stale", oneHourAgo, "env_fresh");
|
||||
|
||||
const result = await presence.getRecentBranchIds(userId, projectId);
|
||||
expect([...result.keys()]).toEqual(["env_fresh"]);
|
||||
|
||||
await redis.quit();
|
||||
});
|
||||
|
||||
redisTest("physically prunes stale entries on the next ping", async ({ redisOptions }) => {
|
||||
const presence = new DevPresence(redisOptions);
|
||||
const redis = new Redis(redisOptions);
|
||||
const { userId, projectId } = ids();
|
||||
const key = recentKey(userId, projectId);
|
||||
|
||||
await redis.zadd(key, subDays(Date.now(), 4).getTime(), "env_stale");
|
||||
|
||||
// A fresh ping triggers the ZREMRANGEBYSCORE cleanup for this user/project.
|
||||
await presence.setConnected({ userId, projectId, environmentId: "env_fresh", ttl: 60 });
|
||||
|
||||
expect(await redis.zscore(key, "env_stale")).toBeNull();
|
||||
expect(await redis.zcard(key)).toBe(1);
|
||||
|
||||
await redis.quit();
|
||||
});
|
||||
|
||||
redisTest(
|
||||
"caps cardinality at 50 even under a flood of distinct branches",
|
||||
async ({ redisOptions }) => {
|
||||
const presence = new DevPresence(redisOptions);
|
||||
const redis = new Redis(redisOptions);
|
||||
const { userId, projectId } = ids();
|
||||
|
||||
// 60 distinct envs, each with its own debounce key, so each performs a ZADD.
|
||||
for (let i = 0; i < 60; i++) {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await presence.setConnected({ userId, projectId, environmentId: `env_${i}`, ttl: 60 });
|
||||
}
|
||||
|
||||
expect(await redis.zcard(recentKey(userId, projectId))).toBe(50);
|
||||
|
||||
await redis.quit();
|
||||
}
|
||||
);
|
||||
|
||||
redisTest("returns recent branches in most-recent-first order", async ({ redisOptions }) => {
|
||||
const presence = new DevPresence(redisOptions);
|
||||
const redis = new Redis(redisOptions);
|
||||
const { userId, projectId } = ids();
|
||||
const key = recentKey(userId, projectId);
|
||||
|
||||
const now = Date.now();
|
||||
await redis.zadd(
|
||||
key,
|
||||
now - 3000,
|
||||
"env_oldest",
|
||||
now - 2000,
|
||||
"env_middle",
|
||||
now - 1000,
|
||||
"env_newest"
|
||||
);
|
||||
|
||||
const result = await presence.getRecentBranchIds(userId, projectId);
|
||||
expect([...result.keys()]).toEqual(["env_newest", "env_middle", "env_oldest"]);
|
||||
|
||||
await redis.quit();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user