Skip to content
Draft
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
19 changes: 6 additions & 13 deletions app/(protected)/deeploys/monitor/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ const widthClasses = [
export default function Monitor() {
const { watchTx } = useBlockchainContext() as BlockchainContextType;
const { confirm } = useInteractionContext() as InteractionContextType;
const { escrowContractAddress, fetchRunningJobsWithDetails, setProjectOverviewTab, hasEscrowPermission } =
const { escrowContractAddress, getRunningJobsWithDetails, setProjectOverviewTab, hasEscrowPermission } =
useDeploymentContext() as DeploymentContextType;

const [isLoading, setLoading] = useState(true);
Expand All @@ -69,18 +69,11 @@ export default function Monitor() {
}>(null);

const getJobs = useCallback(
async (paidDraftJobs: PaidDraftJob[]) => {
if (!publicClient || !escrowContractAddress) {
toast.error('Please connect your wallet.');
return;
}

console.log('Fetching running jobs...');

(paidDraftJobs: PaidDraftJob[]) => {
setLoading(true);

try {
const { runningJobs, runningJobsWithDetails } = await fetchRunningJobsWithDetails();
const { runningJobs, runningJobsWithDetails } = getRunningJobsWithDetails();

// The IDs of the jobs that were successfully deployed by the pipeline
const deployedJobIds: bigint[] = runningJobsWithDetails.map((job) => job.id);
Expand Down Expand Up @@ -113,7 +106,7 @@ export default function Monitor() {
setLoading(false);
}
},
[publicClient, escrowContractAddress, fetchRunningJobsWithDetails],
[getRunningJobsWithDetails],
);

const onClaimFunds = async (job: MonitoredJob) => {
Expand Down Expand Up @@ -190,12 +183,12 @@ export default function Monitor() {
}, [draftJobs]);

useEffect(() => {
if (!publicClient || draftJobs === undefined) {
if (draftJobs === undefined) {
return;
}

getJobs(paidDraftJobsRef.current);
}, [publicClient, draftJobs, getJobs]);
}, [draftJobs, getJobs]);

if (!hasEscrowPermission('redeemUnused')) {
return (
Expand Down
41 changes: 18 additions & 23 deletions app/(protected)/deeploys/project/[projectHash]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { routePath } from '@lib/routes/route-paths';
import db from '@lib/storage/db';
import { isValidProjectHash } from '@lib/utils';
import { DetailedAlert } from '@shared/DetailedAlert';
import ProjectIdentity from '@shared/jobs/projects/ProjectIdentity';
import ProjectIdentity, { ProjectRuntimeStatus } from '@shared/jobs/projects/ProjectIdentity';
import Payment from '@shared/projects/Payment';
import { Apps } from '@typedefs/deeployApi';
import { DraftJob, ProjectPage, RunningJobWithDetails } from '@typedefs/deeploys';
Expand All @@ -17,28 +17,17 @@ import { useParams, useRouter } from 'next/navigation';
import { useEffect, useState } from 'react';
import toast from 'react-hot-toast';
import { RiAlertLine } from 'react-icons/ri';
import { usePublicClient } from 'wagmi';

export default function Project() {
const router = useRouter();

const {
escrowContractAddress,
jobType,
setJobType,
projectPage,
setProjectPage,
getProjectName,
fetchRunningJobsWithDetails,
hasEscrowPermission,
} = useDeploymentContext() as DeploymentContextType;
const { jobType, setJobType, projectPage, setProjectPage, getProjectName, getRunningJobsWithDetails, hasEscrowPermission } =
useDeploymentContext() as DeploymentContextType;

const [isLoading, setLoading] = useState(true);
const [projectName, setProjectName] = useState<string | undefined>();
const [runningJobsWithDetails, setRunningJobsWithDetails] = useState<RunningJobWithDetails[]>([]);

const publicClient = usePublicClient();

const { projectHash } = useParams<{ projectHash?: string }>();

// Used to display a message with the successfully deployed jobs right after deployment
Expand All @@ -57,10 +46,10 @@ export default function Project() {
}, []);

useEffect(() => {
if (publicClient && isValidProjectHash(projectHash)) {
if (isValidProjectHash(projectHash)) {
fetchRunningJobs();
}
}, [publicClient, projectHash]);
}, [projectHash]);

useEffect(() => {
if (!isValidProjectHash(projectHash)) {
Expand All @@ -71,15 +60,10 @@ export default function Project() {
}, [getProjectName, projectHash, router]);

const fetchRunningJobs = async (appsOverride?: Apps) => {
if (!publicClient || !escrowContractAddress) {
toast.error('Please connect your wallet.');
return;
}

setLoading(true);

try {
const { runningJobsWithDetails } = await fetchRunningJobsWithDetails(appsOverride);
const { runningJobsWithDetails } = getRunningJobsWithDetails(appsOverride);
const projectJobs = runningJobsWithDetails.filter((job) => job.projectHash === projectHash);

setRunningJobsWithDetails(projectJobs);
Expand Down Expand Up @@ -113,7 +97,18 @@ export default function Project() {
return <></>;
}

const getProjectIdentity = () => <ProjectIdentity projectName={projectName} />;
const totalInstancesCount = runningJobsWithDetails.reduce((count, job) => count + job.instances.length, 0);
const offlineInstancesCount = runningJobsWithDetails.reduce(
(count, job) => count + job.instances.filter((instance) => instance.isOnline === false).length,
0,
);

let projectRuntimeStatus: ProjectRuntimeStatus = 'running';
if (totalInstancesCount > 0 && offlineInstancesCount > 0) {
projectRuntimeStatus = offlineInstancesCount === totalInstancesCount ? 'down' : 'degraded';
}

const getProjectIdentity = () => <ProjectIdentity projectName={projectName} runtimeStatus={projectRuntimeStatus} />;

return !jobType ? (
<>
Expand Down
9 changes: 1 addition & 8 deletions app/(protected)/home/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { getShortAddressOrHash } from '@lib/utils';
import { BigCard } from '@shared/cards/BigCard';
import { CopyableValue } from '@shared/CopyableValue';
import { formatDistanceToNow } from 'date-fns';
import { uniq } from 'lodash';
import React from 'react';
import { RiTimeLine } from 'react-icons/ri';

Expand All @@ -33,13 +32,7 @@ export default function Home() {

<Card
title="Running Jobs"
value={
uniq(
Object.values(apps)
.map((app) => Object.keys(app))
.flat(),
).length
}
value={Object.keys(apps).length}
/>

<Card
Expand Down
15 changes: 5 additions & 10 deletions src/components/deeploys/Running.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import _ from 'lodash';
import { forwardRef, useEffect, useImperativeHandle, useState } from 'react';
import toast from 'react-hot-toast';
import { RiDraftLine } from 'react-icons/ri';
import { usePublicClient } from 'wagmi';
import RunningCard from './RunningCard';

export interface RunningRef {
Expand All @@ -26,20 +25,16 @@ const Running = forwardRef<
clearSuccessfulJobsFromLocation: () => void;
}
>(({ setProjectsCount, successfulJobs, setSuccessfulJobs, clearSuccessfulJobsFromLocation }, ref) => {
const { apps, fetchRunningJobsWithDetails, fetchApps } = useDeploymentContext() as DeploymentContextType;
const { apps, getRunningJobsWithDetails, fetchApps } = useDeploymentContext() as DeploymentContextType;

const [isLoading, setLoading] = useState(true);

const [projects, setProjects] = useState<Record<string, RunningJobWithDetails[]>>({});
const [expanded, setExpanded] = useState<Record<string, boolean>>({});

const publicClient = usePublicClient();

useEffect(() => {
if (publicClient) {
getProjectsWithJobs();
}
}, [publicClient, apps]);
getProjectsWithJobs();
}, [apps]);

useEffect(() => {
if (projects) {
Expand All @@ -53,11 +48,11 @@ const Running = forwardRef<
}
}, [projects]);

const getProjectsWithJobs = async () => {
const getProjectsWithJobs = () => {
setLoading(true);

try {
const { runningJobsWithDetails } = await fetchRunningJobsWithDetails();
const { runningJobsWithDetails } = getRunningJobsWithDetails();
const projectsWithJobs = _.groupBy(runningJobsWithDetails, 'projectHash');

setProjects(projectsWithJobs);
Expand Down
33 changes: 30 additions & 3 deletions src/components/deeploys/RunningCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,21 @@ export default function RunningCard({
);
};

const getHealthColorClass = (offlineCount: number, totalCount: number): string => {
if (offlineCount === 0) {
return 'bg-emerald-500';
}

return totalCount > 0 && offlineCount === totalCount ? 'bg-red-500' : 'bg-yellow-500';
};

const totalProjectInstancesCount = jobs.reduce((count, job) => count + job.instances.length, 0);
const offlineProjectInstancesCount = jobs.reduce(
(count, job) => count + job.instances.filter((instance) => instance.isOnline === false).length,
0,
);
const projectHealthColorClass = getHealthColorClass(offlineProjectInstancesCount, totalProjectInstancesCount);

const getProjectIdentity = (): React.ReactNode => {
const job = jobs.find((job) => !!job.projectName);

Expand All @@ -73,9 +88,16 @@ export default function RunningCard({
<div className="row gap-2">
<Expander expanded={expanded} onToggle={toggle} />

<Link href={`${routePath.deeploys}/${routePath.project}/${projectHash}`} className="hover:opacity-75">
{getProjectIdentity()}
</Link>
<div className="row items-center gap-1.5">
<div className={`h-2.5 w-2.5 rounded-full ${projectHealthColorClass}`}></div>

<Link
href={`${routePath.deeploys}/${routePath.project}/${projectHash}`}
className="hover:opacity-75"
>
{getProjectIdentity()}
</Link>
</div>
</div>
</div>

Expand Down Expand Up @@ -132,6 +154,9 @@ export default function RunningCard({
) as JobTypeOption;

const targetNodes = Number(job.numberOfNodesRequested);
const totalJobInstancesCount = job.instances.length;
const offlineJobInstancesCount = job.instances.filter((instance) => instance.isOnline === false).length;
const jobHealthColorClass = getHealthColorClass(offlineJobInstancesCount, totalJobInstancesCount);

const requestDate = new Date(Number(job.requestTimestamp) * 1000);
const expirationDate = addTimeFn(config.genesisDate, Number(job.lastExecutionEpoch));
Expand All @@ -153,6 +178,8 @@ export default function RunningCard({
)}
</div>

<div className={`h-2.5 w-2.5 rounded-full ${jobHealthColorClass}`}></div>

<div className={`text-[17px] ${jobTypeOption.textColorClass}`}>
{jobTypeOption.icon}
</div>
Expand Down
8 changes: 6 additions & 2 deletions src/components/job/JobBreadcrumbs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ export default function JobBreadcrumbs({
job: RunningJobWithResources;
jobTypeOption: JobTypeOption | undefined;
}) {
const totalInstancesCount = job.instances.length;
const offlineInstancesCount = job.instances.filter((instance) => instance.isOnline === false).length;
const allInstancesOffline = totalInstancesCount > 0 && offlineInstancesCount === totalInstancesCount;

return (
<div className="row gap-1.5">
<Link href={`${routePath.deeploys}/${routePath.project}/${job.projectHash}`} className="hover:underline">
Expand All @@ -24,8 +28,8 @@ export default function JobBreadcrumbs({
<div className="text-xl font-semibold">{job.alias}</div>
<div className="text-xl font-semibold text-slate-500">#{job.id.toString()}</div>

<SmallTag variant="green" isLarge>
Running
<SmallTag variant={offlineInstancesCount > 0 ? (allInstancesOffline ? 'red' : 'yellow') : 'green'} isLarge>
{offlineInstancesCount > 0 ? `${offlineInstancesCount}/${totalInstancesCount} offline` : 'Running'}
</SmallTag>
</div>
</div>
Expand Down
Loading
Loading