.ts
TypeScript
(application/typescript)
// 1st-party
import { InMemoryCacheAdapter } from "@ethicdevs/fastify-stream-react-views";
import type { ServiceMethodFactory } from "@ethicdevs/react-monolith";
// app
import { RepositoryCountersDTO } from "../../types";
// service
import type { RepositoryServiceDeps } from "./types";

const CACHE = new InMemoryCacheAdapter();
const CACHE_TTL = 30 * 1000; // 30s before cache expires

const makeGetRepositoryCounters: ServiceMethodFactory<
  RepositoryServiceDeps,
  [string, string],
  Promise<RepositoryCountersDTO | null>
> = ({ request }) => {
  return async (orgSlug, repoSlug) => {
    const cacheKey = `${orgSlug}/${repoSlug}/counters`;
    const lastRefresh = await CACHE.get(
      `${orgSlug}/${repoSlug}/counters/lastRefresh`,
    );

    let isFreshCache = (request.params as any)["refetch"] != null || false;

    // when last refresh is more than 30s ago, bypass the cache.
    if (
      lastRefresh != null &&
      new Date(lastRefresh).getTime() > Date.now() - CACHE_TTL
    ) {
      isFreshCache = true;
    }

    // when cache is fresh, return it.
    if (isFreshCache === false && (await CACHE.has(cacheKey))) {
      const value = await CACHE.get(cacheKey);
      if (value) return JSON.parse(value);
      return DEFAULT_COUNTERS;
    }

    // retrieve open pulls count in repository (PRs targeting this repo)
    const openPulls = await request.prisma.pullRequest.count({
      where: {
        targetRepository: {
          organization: { slug: orgSlug },
          slug: repoSlug,
        },
        state: "OPEN",
        closedAt: null,
      },
    });

    // for now provide pulls and zeros
    const counters: RepositoryCountersDTO = {
      files: 0,
      forks: 0,
      branches: 0,
      tags: 0,
      commits: 0,
      pulls: openPulls,
      tests: 0,
      builds: 0,
      issues: 0,
      apiRefSymbols: 0,
      helpCenterNotifs: 0,
    };

    await CACHE.set(cacheKey, JSON.stringify(counters));
    return counters;
  };
};

const DEFAULT_COUNTERS: RepositoryCountersDTO = {
  files: 0,
  forks: 0,
  branches: 0,
  tags: 0,
  commits: 0,
  pulls: 0,
  tests: 0,
  builds: 0,
  issues: 0,
  apiRefSymbols: 0,
  helpCenterNotifs: 0,
};

export default makeGetRepositoryCounters;