💥 Atomic Writes

ACID compliant transactions

Query Records by Username

file_type_typescript main.ts
export async function storeShortLink(
  longUrl: string,
  shortCode: string,
  userId: string,
) {
  const shortLinkKey = ["shortlinks", shortCode];
  const data: ShortLink = {
    shortCode,
    longUrl,
    userId,
    createdAt: Date.now(),
    clickCount: 0,
  };

  const userKey = [userId, shortCode];
  
  const res = await kv.atomic()
    .set(shortLinkKey, data)
    .set(userKey, shortCode)
    .commit()


  return res;
}

export async function getUserLinks(userId: string) {

  const list = kv.list<string>({ prefix: [userId]});
  const res = await Array.fromAsync(list);
  const userShortLinkKeys = res.map((v) => ['shortlinks', v.value]);

  const userRes = await kv.getMany<ShortLink[]>(userShortLinkKeys)
  const userShortLinks = await Array.fromAsync(userRes)

  return userShortLinks.map(v => v.value);
}

Increment a Count

file_type_typescript main.ts
export async function incrementClickCount(
  shortCode: string,
  data?: Partial<ClickAnalytics>,
) {
  const shortLinkKey = ["shortlinks", shortCode];
  const shortLink = await kv.get(shortLinkKey);
  const shortLinkData = shortLink.value as ShortLink;

  const newClickCount = shortLinkData?.clickCount + 1;

  const analyicsKey = ["analytics", shortCode, newClickCount];
  const analyticsData = {
    shortCode,
    createdAt: Date.now(),
    ...data,
    // ipAddress: "192.168.1.1",
    // userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
    // country: "United States"
  };

  const res = await kv.atomic()
    .check(shortLink)
    .set(shortLinkKey, {
      ...shortLinkData,
      clickCount: shortLinkData?.clickCount + 1,
    })
    .set(analyicsKey, analyticsData)
    .commit();
  if (res.ok) {
    console.log("Logged click");
  } else {
    console.error("Not logged");
  }

  return res;
}

Questions? Let's chat

Open Discord