SPB Git forge
38commits 1branches 0releases
338.7 MBsize
maindefault branch
4 h agolast push
HTML 53.9% TypeScript 44.5% JavaScript 0.6% SQL 0.5%
7.2 KB · 116 lines typescript
Raw Blame History
1/** Cloud regions: provider operator (hyperscaler/cloud) + unique (provider, code). Launch/announce/update events. */2import { sql } from "@dci/db";3import { cleanText, newId, slugify, type NormalizedCloudRegion } from "@dci/core";4import { addRef, bump, safeCountry, uniqueSlug, type IngestContext, type Tx } from "./common.js";5import { recordEvent } from "./events.js";6import { validGeo } from "./geo.js";7import { upsertKey } from "./keys.js";8import { assignMetro } from "./metros.js";9import { resolveOperator } from "./operators.js";10import { writeProvenance } from "./provenance.js";1112export async function ingestCloudRegion(tx: Tx, ctx: IngestContext, cr: NormalizedCloudRegion): Promise<void> {13  const code = cleanText(cr.code);14  const name = cleanText(cr.name) ?? code;15  if (!code || !name) throw new Error(`cloud_region ${cr.key}: code and name are required`);16  const url = cr.provenance.url || cr.sourceUrl || ctx.doc?.url || "";17  if (!url) throw new Error(`cloud_region ${cr.key}: provenance url is required`);18  const provider = await resolveOperator(tx, ctx, { name: cr.providerName, roleHint: "cloud" });19  const country = await safeCountry(tx, ctx, cr.countryIso2);20  const geo = validGeo(cr.geo) ? cr.geo : null;21  const metro = await assignMetro(tx, { lat: geo?.lat, lng: geo?.lng, city: cr.city, countryIso2: country });22  const status = cr.status ?? "operational";2324  const existing = (await tx.execute(sql`select * from cloud_regions where provider_id = ${provider.id} and lower(code) = lower(${code}) limit 1`))[0] ?? null;25  const id = existing ? String(existing.id) : newId("cloud_region");26  if (!existing) {27    const providerSlug = (await tx.execute(sql`select slug from operators where id = ${provider.id}`))[0]?.slug;28    const slug = await uniqueSlug(tx, "cloud_regions", `${String(providerSlug ?? slugify(provider.name))}-${code}`);29    await tx.execute(sql`insert into cloud_regions (id, slug, provider_id, code, name, city, region_name, country_iso2, metro_id, lat, lng, geo_precision, availability_zones, launched_on, status, is_sovereign, source_url, external_ids)30      values (${id}, ${slug}, ${provider.id}, ${code}, ${name}, ${cleanText(cr.city)}, ${cleanText(cr.regionName)}, ${country ?? metro.countryIso2}, ${metro.metroId}, ${geo?.lat ?? null}, ${geo?.lng ?? null}, ${geo?.precision ?? "city"},31        ${cr.availabilityZones ?? null}, ${cr.launchedOn ?? null}, ${status}, ${!!cr.isSovereign}, ${cr.sourceUrl ?? null}, ${JSON.stringify(cr.externalIds ?? {})}::jsonb)`);32    ctx.stats.created++;33    await recordEvent(tx, ctx, {34      entityType: "cloud_region",35      entityId: id,36      eventType: status === "announced" ? "cloud_region_announced" : "cloud_region_launched",37      title: status === "announced" ? `${provider.name} announces ${name} (${code}) cloud region` : `${provider.name} ${name} (${code}) cloud region indexed`,38      summary: [cr.city ? `${cr.city}${country ? `, ${country}` : ""}.` : null, cr.availabilityZones ? `${cr.availabilityZones} availability zones.` : null, cr.launchedOn ? `Launched ${cr.launchedOn}.` : null].filter(Boolean).join(" ") || null,39      newValue: { code, name, status },40      significance: status === "announced" ? 70 : 45,41      confidence: cr.provenance.confidence,42      effectiveDate: cr.launchedOn ?? null,43      url,44      countryIso2: country ?? metro.countryIso2,45      operatorId: provider.id,46      metroId: metro.metroId,47    });48  } else {49    const prevStatus = String(existing.status);50    const changed = prevStatus !== status || (existing.availability_zones ?? null) !== (cr.availabilityZones ?? null) || (existing.launched_on ?? null) !== (cr.launchedOn ?? null) || String(existing.name) !== name;51    await tx.execute(sql`update cloud_regions set name = ${name}, city = coalesce(${cleanText(cr.city)}, city), region_name = coalesce(${cleanText(cr.regionName)}, region_name), country_iso2 = coalesce(${country}, country_iso2),52        metro_id = coalesce(${metro.metroId}, metro_id), lat = coalesce(${geo?.lat ?? null}, lat), lng = coalesce(${geo?.lng ?? null}, lng), geo_precision = case when ${geo != null} then ${geo?.precision ?? "city"} else geo_precision end,53        availability_zones = coalesce(${cr.availabilityZones ?? null}, availability_zones), launched_on = coalesce(${cr.launchedOn ?? null}, launched_on), status = ${status}, is_sovereign = is_sovereign or ${!!cr.isSovereign},54        source_url = coalesce(${cr.sourceUrl ?? null}, source_url), external_ids = external_ids || ${JSON.stringify(cr.externalIds ?? {})}::jsonb, updated_at = now()55      where id = ${id}`);56    if (changed) ctx.stats.updated++;57    else ctx.stats.unchanged++;58    if (prevStatus !== status) {59      await recordEvent(tx, ctx, {60        entityType: "cloud_region",61        entityId: id,62        eventType: status === "operational" && prevStatus === "announced" ? "cloud_region_launched" : "cloud_region_updated",63        title: status === "operational" && prevStatus === "announced" ? `${provider.name} ${name} (${code}) is now live` : `${provider.name} ${name} (${code}): status ${prevStatus} → ${status}`,64        summary: `Status changed from ${prevStatus} to ${status}.`,65        oldValue: prevStatus,66        newValue: status,67        significance: status === "operational" ? 80 : 60,68        confidence: cr.provenance.confidence,69        effectiveDate: cr.launchedOn ?? null,70        url,71        countryIso2: country ?? (existing.country_iso2 as string | null),72        operatorId: provider.id,73        metroId: metro.metroId ?? (existing.metro_id as string | null),74      });75    } else if (changed) {76      await recordEvent(tx, ctx, {77        entityType: "cloud_region",78        entityId: id,79        eventType: "cloud_region_updated",80        title: `${provider.name} ${name} (${code}) updated`,81        summary: `Availability zones: ${existing.availability_zones ?? "—"} → ${cr.availabilityZones ?? "—"}; launch: ${existing.launched_on ?? "—"} → ${cr.launchedOn ?? "—"}.`,82        oldValue: { availabilityZones: existing.availability_zones ?? null, launchedOn: existing.launched_on ?? null, name: existing.name },83        newValue: { availabilityZones: cr.availabilityZones ?? null, launchedOn: cr.launchedOn ?? null, name },84        significance: 25,85        confidence: cr.provenance.confidence,86        url,87        countryIso2: country ?? (existing.country_iso2 as string | null),88        operatorId: provider.id,89        metroId: metro.metroId ?? (existing.metro_id as string | null),90      });91    }92  }93  await upsertKey(tx, ctx, cr.key, "cloud_region", id);94  addRef(ctx, "cloud_region", id);95  bump(ctx, "cloud_region");96  await writeProvenance(97    tx,98    ctx,99    "cloud_region",100    id,101    [102      { field: "code", value: code },103      { field: "name", value: name },104      { field: "providerName", value: cr.providerName },105      { field: "city", value: cr.city ?? null },106      { field: "countryIso2", value: cr.countryIso2 ?? null },107      { field: "geo", value: geo ? { lat: geo.lat, lng: geo.lng, precision: geo.precision } : null },108      { field: "availabilityZones", value: cr.availabilityZones ?? null },109      { field: "launchedOn", value: cr.launchedOn ?? null },110      { field: "status", value: status },111      { field: "isSovereign", value: cr.isSovereign ?? null },112    ].map((f) => ({ ...f, provenance: cr.provenance })),113    cr.key,114  );115}116