Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions dbsync-api/src/health/healthCheck.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { Request, Response, Router } from "express";
import { prisma } from "../config/db";
import { handlerWrapper } from "../errors/AppError";

const router = Router();

export const secondsSince = (
dateIsoString: string,
inMilliseconds?: boolean
): number => {
const parsedDate = new Date(dateIsoString);
const currentDate = new Date();
const timeDifferenceMs = currentDate.getTime() - parsedDate.getTime();
return inMilliseconds ? timeDifferenceMs : timeDifferenceMs / 1000;
};

const getBlockInfo = async (req: Request, res: Response) => {
try {
const latestBlock = await prisma.block.findFirst({
orderBy: {
time: "desc",
},
});

if (!latestBlock) {
return res.status(500).json({
message:
"Unable to retrieve the latest block information from the database.",
});
}

const latestBlockTime = latestBlock.time.toISOString();
const timeDiff = secondsSince(latestBlockTime);

if (timeDiff > 300) {
return res.status(503).json({
status: "Service Unavailable",
details: {
currentTime: new Date().toISOString(),
latestBlockTime,
secondsSinceLastUpdate: timeDiff,
},
});
}

return res.status(200).json({
status: "Healthy",
details: {
currentTime: new Date().toISOString(),
latestBlockTime,
secondsSinceLastUpdate: timeDiff,
},
});
} catch (error: any) {
console.log(`Error performing health-check: ${error.message || error}`);

return res.status(500).json({
message: "An error occurred while checking the DbSync status.",
});
}
};

router.get("/", handlerWrapper(getBlockInfo));

export default router;
2 changes: 2 additions & 0 deletions dbsync-api/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import delegationRoute from "./controllers/delegation";
import drepRoute from "./controllers/drep";
import addressRoute from "./controllers/address";
import proposalRoute from "./controllers/proposal";
import healthCheckRoute from "./health/healthCheck"
import { errorHandler } from "./errors/AppError";
import path from "path";
import setupSwaggerUi from "./swagger-loader";
Expand Down Expand Up @@ -45,6 +46,7 @@ app.use('/api/stake-address', stakeAddrRoute);
app.use('/api/drep',drepRoute)
app.use('/api/address',addressRoute)
app.use('/api/proposal',proposalRoute)
app.use('/api/health', healthCheckRoute)

setupSwaggerUi(app)
const indexFile = path.resolve('.','./index.html')
Expand Down
65 changes: 64 additions & 1 deletion dbsync-api/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -481,4 +481,67 @@ paths:
description: Invalid address provided
'500':
description: Internal server error

/api/health:
get:
summary: Check DBSync health status
description: Retrieves the latest block and checks if it was updated within the last 5 minutes.
operationId: getBlockInfo
responses:
'200':
description: DBSync service is healthy.
content:
application/json:
schema:
type: object
properties:
status:
type: string
example: "Healthy"
details:
type: object
properties:
currentTime:
type: string
format: date-time
example: "2024-12-03T12:34:56.789Z"
latestBlockTime:
type: string
format: date-time
example: "2024-12-03T12:30:00.123Z"
secondsSinceLastUpdate:
type: number
example: 296
'503':
description: DBSync service is unavailable due to a delay in block updates.
content:
application/json:
schema:
type: object
properties:
status:
type: string
example: "Service Unavailable"
details:
type: object
properties:
currentTime:
type: string
format: date-time
example: "2024-12-03T12:34:56.789Z"
latestBlockTime:
type: string
format: date-time
example: "2024-12-03T12:25:00.123Z"
secondsSinceLastUpdate:
type: number
example: 596
'500':
description: An error occurred while performing the health check.
content:
application/json:
schema:
type: object
properties:
message:
type: string
example: "An error occurred while checking the DbSync status."