Skip to content

Commit

Permalink
feat(deployment): ensure user can re-send manifest
Browse files Browse the repository at this point in the history
after creating a lease and initial send failure
  • Loading branch information
ygrishajev committed Sep 20, 2024
1 parent a0013d8 commit 0db3775
Showing 1 changed file with 69 additions and 60 deletions.
129 changes: 69 additions & 60 deletions apps/deploy-web/src/components/new-deployment/CreateLease.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"use client";
import React, { useEffect, useState } from "react";
import React, { useCallback, useEffect, useMemo, useState } from "react";
import {
Alert,
Button,
Expand All @@ -21,6 +21,7 @@ import { useSnackbar } from "notistack";
import { LocalCert } from "@src/context/CertificateProvider/CertificateProviderContext";
import { useWallet } from "@src/context/WalletProvider";
import { useManagedDeploymentConfirm } from "@src/hooks/useManagedDeploymentConfirm";
import { useWhen } from "@src/hooks/useWhen";
import { useBidList } from "@src/queries/useBidQuery";
import { useDeploymentDetail } from "@src/queries/useDeploymentQuery";
import { useProviderList } from "@src/queries/useProvidersQuery";
Expand Down Expand Up @@ -58,6 +59,7 @@ export const CreateLease: React.FunctionComponent<Props> = ({ dseq }) => {
const [isFilteringFavorites, setIsFilteringFavorites] = useState(false);
const [isFilteringAudited, setIsFilteringAudited] = useState(false);
const [isCreatingLeases, setIsCreatingLeases] = useState(false);
const [isLeaseCreated, setIsLeaseCreated] = useState(false);
const [selectedBids, setSelectedBids] = useState<{ [gseq: string]: BidDto }>({});
const [filteredBids, setFilteredBids] = useState<Array<string>>([]);
const [search, setSearch] = useState("");
Expand All @@ -77,6 +79,8 @@ export const CreateLease: React.FunctionComponent<Props> = ({ dseq }) => {
},
enabled: !maxRequestsReached && !isSendingManifest
});
const activeBid = useMemo(() => bids?.find(bid => bid.state === "active"), [bids]);
const hasActiveBid = !!activeBid;
const { data: deploymentDetail, refetch: getDeploymentDetail } = useDeploymentDetail(address, dseq, { refetchOnMount: false, enabled: false });
const groupedBids =
bids
Expand All @@ -86,6 +90,7 @@ export const CreateLease: React.FunctionComponent<Props> = ({ dseq }) => {
return a as { [key: number]: BidDto };
}, {} as any) || {};
const dseqList = Object.keys(groupedBids).map(group => parseInt(group));

const allClosed = (bids?.length || 0) > 0 && bids?.every(bid => bid.state === "closed");
const { enqueueSnackbar, closeSnackbar } = useSnackbar();
const wallet = useWallet();
Expand All @@ -96,6 +101,58 @@ export const CreateLease: React.FunctionComponent<Props> = ({ dseq }) => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

useWhen(hasActiveBid, () => selectBid(activeBid));

const sendManifest = useCallback(async () => {
setIsSendingManifest(true);
const bidKeys = Object.keys(selectedBids);

const localDeploymentData = getDeploymentLocalData(dseq);

event(AnalyticsEvents.SEND_MANIFEST, {
category: "deployments",
label: "Send manifest after creating lease"
});

if (!localDeploymentData || !localDeploymentData.manifest) {
return;
}

const sendManifestNotification =
!wallet.isManaged &&
enqueueSnackbar(<Snackbar title="Deploying! 🚀" subTitle="Please wait a few seconds..." showLoading />, {
variant: "info",
autoHideDuration: null
});

try {
const yamlJson = yaml.load(localDeploymentData.manifest);
const mani = deploymentData.getManifest(yamlJson, true);

for (let i = 0; i < bidKeys.length; i++) {
const currentBid = selectedBids[bidKeys[i]];
const provider = providers?.find(x => x.owner === currentBid.provider);

if (!provider) {
throw new Error("Provider not found");
}
await sendManifestToProvider(provider, mani, dseq, localCert as LocalCert);
}
router.replace(UrlService.deploymentDetails(dseq, "EVENTS", "events"));
} catch (err) {
enqueueSnackbar(<ManifestErrorSnackbar err={err} />, { variant: "error", autoHideDuration: null });
console.error(err);
} finally {
if (sendManifestNotification) {
closeSnackbar(sendManifestNotification);
}

setIsSendingManifest(false);
}
}, [selectedBids, dseq, providers, localCert, wallet.isManaged, enqueueSnackbar, closeSnackbar, router]);

useWhen(isLeaseCreated, sendManifest);

// Filter bids
useEffect(() => {
if ((search || isFilteringFavorites || isFilteringAudited) && providers) {
Expand Down Expand Up @@ -124,25 +181,14 @@ export const CreateLease: React.FunctionComponent<Props> = ({ dseq }) => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [search, bids, providers, isFilteringFavorites, isFilteringAudited, favoriteProviders]);

const handleBidSelected = bid => {
setSelectedBids({ ...selectedBids, [bid.gseq]: bid });
const selectBid = bid => {
setSelectedBids(prev => ({ ...prev, [bid.gseq]: bid }));
};

async function sendManifest(providerInfo, manifest) {
try {
const response = await sendManifestToProvider(providerInfo, manifest, dseq, localCert as LocalCert);

return response;
} catch (err) {
enqueueSnackbar(<ManifestErrorSnackbar err={err} />, { variant: "error", autoHideDuration: null });
throw err;
}
}

/**
* Create the leases
*/
async function handleNext() {
async function createLease() {
setIsCreatingLeases(true);

const bidKeys = Object.keys(selectedBids);
Expand All @@ -159,48 +205,10 @@ export const CreateLease: React.FunctionComponent<Props> = ({ dseq }) => {
category: "deployments",
label: "Create lease"
});
} catch (error) {
// Rejected transaction
setIsLeaseCreated(true);
} finally {
setIsCreatingLeases(false);
return;
}

setIsSendingManifest(true);

const localDeploymentData = getDeploymentLocalData(dseq);
if (localDeploymentData && localDeploymentData.manifest) {
// Send the manifest
const sendManifestNotification =
!wallet.isManaged &&
enqueueSnackbar(<Snackbar title="Deploying! 🚀" subTitle="Please wait a few seconds..." showLoading />, {
variant: "info",
autoHideDuration: null
});

try {
const yamlJson = yaml.load(localDeploymentData.manifest);
const mani = deploymentData.getManifest(yamlJson, true);

for (let i = 0; i < bidKeys.length; i++) {
const currentBid = selectedBids[bidKeys[i]];
const provider = providers?.find(x => x.owner === currentBid.provider);
await sendManifest(provider, mani);
}
} catch (err) {
console.error(err);
}

if (sendManifestNotification) {
closeSnackbar(sendManifestNotification);
}
}

event(AnalyticsEvents.SEND_MANIFEST, {
category: "deployments",
label: "Send manifest after creating lease"
});

router.replace(UrlService.deploymentDetails(dseq, "EVENTS", "events"));
}

async function handleCloseDeployment() {
Expand Down Expand Up @@ -275,15 +283,16 @@ export const CreateLease: React.FunctionComponent<Props> = ({ dseq }) => {
<Button
variant="default"
color="secondary"
onClick={handleNext}
onClick={hasActiveBid ? sendManifest : createLease}
className="w-full whitespace-nowrap md:w-auto"
disabled={dseqList.some(gseq => !selectedBids[gseq]) || isSendingManifest || isCreatingLeases}
disabled={hasActiveBid ? false : dseqList.some(gseq => !selectedBids[gseq]) || isSendingManifest || isCreatingLeases}
>
{isCreatingLeases ? (
{isCreatingLeases || isSendingManifest ? (
<Spinner size="small" />
) : (
<>
Accept Bid{dseqList.length > 1 ? "s" : ""}
{hasActiveBid ? "Re-send Manifest" : "Accept Bid"}
{dseqList.length > 1 ? "s" : ""}
<span className="ml-2 flex items-center">
<ArrowRight className="text-xs" />
</span>
Expand Down Expand Up @@ -389,7 +398,7 @@ export const CreateLease: React.FunctionComponent<Props> = ({ dseq }) => {
key={gseq}
gseq={gseq}
bids={groupedBids[gseq]}
handleBidSelected={handleBidSelected}
handleBidSelected={selectBid}
selectedBid={selectedBids[gseq]}
disabled={isSendingManifest}
providers={providers}
Expand Down

0 comments on commit 0db3775

Please sign in to comment.