Skip to content

Commit

Permalink
stats: fetch kv rest api with no-store
Browse files Browse the repository at this point in the history
  • Loading branch information
sehyunc committed Sep 30, 2024
1 parent 24c6f90 commit 49ebb83
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 29 deletions.
36 changes: 29 additions & 7 deletions app/api/stats/external-transfer-logs/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,36 @@ export async function GET(req: NextRequest) {

const transactionHashes = await getAllSetMembers(kv, INFLOWS_SET_KEY)

// Use pipelining to fetch all data in a single round-trip
const pipeline = kv.pipeline()
transactionHashes.forEach((hash) => pipeline.get(`${INFLOWS_KEY}:${hash}`))
const data = await pipeline.exec()
// Use fetch pipeline to get all data in a single round-trip
const pipelineBody = JSON.stringify(
transactionHashes.map((hash) => ["GET", `${INFLOWS_KEY}:${hash}`])
)

const pipelineResponse = await fetch(
`${process.env.KV_REST_API_URL}/pipeline`,
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.KV_REST_API_TOKEN}`,
},
body: pipelineBody,
cache: "no-store",
},
)

if (!pipelineResponse.ok) {
throw new Error(`HTTP error! status: ${pipelineResponse.status}`)
}

const pipelineResults = await pipelineResponse.json()

const buckets: Record<string, BucketData> = {}

data.forEach((item) => {
if (item && typeof item === "object" && "timestamp" in item) {
const transfer = item as ExternalTransferData
pipelineResults.forEach(({ result }: { result: string | null }) => {
if (result === null) return

try {
const transfer = JSON.parse(result) as ExternalTransferData
const bucketTimestamp = startOfPeriod(transfer.timestamp, intervalMs)
const bucketKey = bucketTimestamp.toString()

Expand All @@ -51,6 +71,8 @@ export async function GET(req: NextRequest) {
} else {
buckets[bucketKey].depositAmount += transfer.amount
}
} catch (error) {
console.error("Error parsing result:", error)
}
})

Expand Down
31 changes: 23 additions & 8 deletions app/api/stats/net-flow/route.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
import { NextRequest } from "next/server"

import { kv } from "@vercel/kv"

import { NET_FLOW_KEY } from "@/app/api/stats/constants"

Expand All @@ -12,28 +9,46 @@ export interface NetFlowResponse {
export const runtime = "edge"
export const dynamic = "force-dynamic"

export async function GET(req: NextRequest) {
export async function GET() {
try {
const data = await kv.get<NetFlowResponse>(NET_FLOW_KEY)
const response = await fetch(
`${process.env.KV_REST_API_URL}/get/${NET_FLOW_KEY}`,
{
method: "GET",
headers: {
Authorization: `Bearer ${process.env.KV_REST_API_TOKEN}`,
},
cache: "no-store",
}
)

if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`)
}

const data = await response.json()

if (data) {
return new Response(JSON.stringify(data), {
return new Response(data.result, {
headers: { "Content-Type": "application/json" },
})
}

return new Response(
JSON.stringify({ error: "Net flow data not available" }),
{
status: 404,
headers: { "Content-Type": "application/json" },
},
}
)
} catch (error) {
console.error("Error fetching net flow data:", error)
return new Response(
JSON.stringify({ error: "Failed to retrieve net flow data" }),
{
status: 500,
headers: { "Content-Type": "application/json" },
},
}
)
}
}
45 changes: 31 additions & 14 deletions app/api/stats/set-net-flow-kv/route.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { kv } from "@vercel/kv"

import {
INFLOWS_KEY,
INFLOWS_SET_KEY,
NET_FLOW_KEY,
} from "@/app/api/stats/constants"
import { NetFlowResponse } from "@/app/api/stats/net-flow/route"
import { getAllSetMembers } from "@/app/lib/kv-utils"
import { kv } from "@vercel/kv"

const TWENTY_FOUR_HOURS = 24 * 60 * 60 * 1000 // 24 hours in milliseconds

Expand All @@ -25,23 +24,39 @@ export async function GET() {
const transactionHashes = await getAllSetMembers(kv, INFLOWS_SET_KEY)
console.log(`Retrieved ${transactionHashes.length} transaction hashes`)

const pipeline = kv.pipeline()
transactionHashes.forEach((hash) => pipeline.get(`${INFLOWS_KEY}:${hash}`))
const data = await pipeline.exec()
console.log(`Fetched data for ${data.length} transactions`)
// Use fetch pipeline to get all data in a single round-trip
const pipelineBody = JSON.stringify(
transactionHashes.map((hash) => ["GET", `${INFLOWS_KEY}:${hash}`])
)

const pipelineResponse = await fetch(
`${process.env.KV_REST_API_URL}/pipeline`,
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.KV_REST_API_TOKEN}`,
},
body: pipelineBody,
cache: "no-store",
},
)

if (!pipelineResponse.ok) {
throw new Error(`HTTP error! status: ${pipelineResponse.status}`)
}

const pipelineResults = await pipelineResponse.json()
console.log(`Fetched data for ${pipelineResults.length} transactions`)

let netFlow = 0
let validTransactions = 0
let skippedTransactions = 0

data.forEach((item) => {
if (
item &&
typeof item === "object" &&
"timestamp" in item &&
"amount" in item
) {
const transfer = item as {
pipelineResults.forEach(({ result }: { result: string | null }) => {
if (result === null) return

try {
const transfer = JSON.parse(result) as {
timestamp: number
amount: number
isWithdrawal: boolean
Expand All @@ -52,6 +67,8 @@ export async function GET() {
} else {
skippedTransactions++
}
} catch (error) {
console.error("Error parsing result:", error)
}
})

Expand Down

0 comments on commit 49ebb83

Please sign in to comment.