diff --git a/.changeset/brown-rings-buy.md b/.changeset/brown-rings-buy.md new file mode 100644 index 000000000..babcee79f --- /dev/null +++ b/.changeset/brown-rings-buy.md @@ -0,0 +1,7 @@ +--- +'@siafoundation/renterd-js': minor +'@siafoundation/renterd-react': minor +'@siafoundation/renterd-types': minor +--- + +The host scanning API was moved from the worker to the bus. Closes https://github.com/SiaFoundation/renterd/issues/1644 diff --git a/apps/renterd/components/Hosts/HostContextMenu.tsx b/apps/renterd/components/Hosts/HostContextMenu.tsx index be7c964e5..59ff3bc10 100644 --- a/apps/renterd/components/Hosts/HostContextMenu.tsx +++ b/apps/renterd/components/Hosts/HostContextMenu.tsx @@ -20,7 +20,7 @@ import { useHostResetLostSectorCount, useHostsAllowlist, useHostsBlocklist, - useRhpScan, + useHostScan, } from '@siafoundation/renterd-react' import { routes } from '../../config/routes' import { useRouter } from 'next/router' @@ -86,7 +86,7 @@ export function HostContextMenuContent({ const allowlist = useHostsAllowlist() const blocklistUpdate = useBlocklistUpdate() const allowlistUpdate = useAllowlistUpdate() - const rescan = useRhpScan() + const rescan = useHostScan() const resetLostSectors = useHostResetLostSectorCount() return ( <> @@ -164,9 +164,10 @@ export function HostContextMenuContent({ return } rescan.post({ + params: { + hostkey: publicKey, + }, payload: { - hostKey: publicKey, - hostIP: address, timeout: secondsInMilliseconds(30), }, }) diff --git a/apps/renterd/contexts/hosts/columns.tsx b/apps/renterd/contexts/hosts/columns.tsx index 53bb8fbef..9301886c7 100644 --- a/apps/renterd/contexts/hosts/columns.tsx +++ b/apps/renterd/contexts/hosts/columns.tsx @@ -21,8 +21,8 @@ import { format, formatDistance, formatRelative } from 'date-fns' import { HostContextMenu } from '../../components/Hosts/HostContextMenu' import { useWorkflows } from '@siafoundation/react-core' import { - RhpScanPayload, - workerRhpScanRoute, + HostScanPayload, + busHostHostKeyScanRoute, } from '@siafoundation/renterd-types' import { HostPriceTable, HostSettings } from '@siafoundation/types' import { useHostsAllowlist } from '@siafoundation/renterd-react' @@ -218,10 +218,9 @@ export const columns: HostsTableColumn[] = ( render: function LastScan({ data }) { const { workflows } = useWorkflows() const isPending = workflows.find((w) => { - const rhpw = w as { route?: string; payload?: RhpScanPayload } - return ( - rhpw.route?.startsWith(workerRhpScanRoute) && - rhpw.payload?.hostKey === data.publicKey + const rhpw = w as { route?: string; payload?: HostScanPayload } + return rhpw.route?.startsWith( + busHostHostKeyScanRoute.replace(':hostkey', data.publicKey) ) }) if (isPending) { diff --git a/libs/react-core/README.md b/libs/react-core/README.md index 8c5094084..547b02141 100644 --- a/libs/react-core/README.md +++ b/libs/react-core/README.md @@ -101,18 +101,19 @@ The lifecycle of imperative methods are tracked by a workflow ID. Workflows allo ```ts // Hook -export function useRhpScan( - args?: HookArgsCallback +export function useHostScan( + args?: HookArgsCallback ) { - return usePostFunc({ ...args, route: workerRhpScanRoute }) + return usePostFunc({ ...args, route: busHostScanRoute }) } // Usage -const rescan = useRhpScan() +const rescan = useHostScan() await rescan.post({ + params: { + hostkey: publicKey, + }, payload: { - hostKey: publicKey, - hostIP: address, timeout: secondsInMilliseconds(30), }, }) diff --git a/libs/renterd-js/src/bus.ts b/libs/renterd-js/src/bus.ts index e52e659f9..1b39aef4e 100644 --- a/libs/renterd-js/src/bus.ts +++ b/libs/renterd-js/src/bus.ts @@ -256,6 +256,10 @@ import { ConsensusNetworkPayload, ConsensusNetworkResponse, busConsensusNetworkRoute, + HostScanParams, + HostScanPayload, + HostScanResponse, + busHostHostKeyScanRoute, } from '@siafoundation/renterd-types' import { buildRequestHandler, initAxios } from '@siafoundation/request' @@ -393,6 +397,11 @@ export function Bus({ api, password }: { api: string; password?: string }) { HostResetLostSectorCountPayload, HostResetLostSectorCountResponse >(axios, 'post', busHostPublicKeyResetlostsectorsRoute), + hostScan: buildRequestHandler< + HostScanParams, + HostScanPayload, + HostScanResponse + >(axios, 'post', busHostHostKeyScanRoute), contracts: buildRequestHandler< ContractsParams, ContractsPayload, diff --git a/libs/renterd-js/src/worker.ts b/libs/renterd-js/src/worker.ts index 98b548640..f8d02bc84 100644 --- a/libs/renterd-js/src/worker.ts +++ b/libs/renterd-js/src/worker.ts @@ -11,16 +11,12 @@ import { ObjectUploadParams, ObjectUploadPayload, ObjectUploadResponse, - RhpScanParams, - RhpScanPayload, - RhpScanResponse, WorkerStateParams, WorkerStatePayload, WorkerStateResponse, workerAccountIdResetdriftRoute, workerMultipartKeyRoute, workerObjectKeyRoute, - workerRhpScanRoute, workerStateRoute, } from '@siafoundation/renterd-types' import { buildRequestHandler, initAxios } from '@siafoundation/request' @@ -65,11 +61,6 @@ export function Worker({ api, password }: { api: string; password?: string }) { }, }, }), - rhpScan: buildRequestHandler< - RhpScanParams, - RhpScanPayload, - RhpScanResponse - >(axios, 'post', workerRhpScanRoute), accountResetDrift: buildRequestHandler< AccountResetDriftParams, AccountResetDriftPayload, diff --git a/libs/renterd-react/src/bus.ts b/libs/renterd-react/src/bus.ts index 57d96f468..456e06aba 100644 --- a/libs/renterd-react/src/bus.ts +++ b/libs/renterd-react/src/bus.ts @@ -1,4 +1,5 @@ import useSWR from 'swr' +import { debounce } from '@technically/lodash' import { useDeleteFunc, useGetSwr, @@ -244,6 +245,11 @@ import { ConsensusNetworkParams, ConsensusNetworkResponse, busConsensusNetworkRoute, + HostScanParams, + HostScanPayload, + HostScanResponse, + busHostHostKeyScanRoute, + Host, } from '@siafoundation/renterd-types' // state @@ -464,6 +470,8 @@ export function useWalletPrepareRenew( return usePostFunc({ ...args, route: busWalletPrepareRenewRoute }) } +// host + export function useHosts( args: HookArgsWithPayloadSwr ) { @@ -559,6 +567,53 @@ export function useHostResetLostSectorCount( }) } +const debouncedListRevalidate = debounce((func: () => void) => func(), 5_000) + +export function useHostScan( + args?: HookArgsCallback +) { + return usePostFunc( + { ...args, route: busHostHostKeyScanRoute }, + async (mutate, { params: { hostkey } }, response) => { + // Fetching immediately after the response returns stale data so + // we optimistically update without triggering revalidation, + // and then revalidate after a 5s delay. The list revalidation + // is debounced so if the user rescans multiple hosts in quick + // succession the list is optimistically updated n times followed + // by a single network revalidate. + mutate( + (key) => key.startsWith(busHostsRoute), + (data) => + data?.map((h) => { + if (h.publicKey === hostkey) { + return { + ...h, + host: { + ...h, + interactions: { + ...h.interactions, + lastScan: new Date().toISOString(), + lastScanSuccess: !response.data.scanError, + }, + settings: response.data.settings, + }, + } + } + return h + }), + false + ) + debouncedListRevalidate(() => { + mutate( + (key) => key.startsWith(busHostsRoute), + (d) => d, + true + ) + }) + } + ) +} + // contracts export function useContracts( diff --git a/libs/renterd-react/src/worker.ts b/libs/renterd-react/src/worker.ts index bdb3927a1..6a0a025dc 100644 --- a/libs/renterd-react/src/worker.ts +++ b/libs/renterd-react/src/worker.ts @@ -1,4 +1,3 @@ -import { debounce } from '@technically/lodash' import { useGetDownloadFunc, usePutFunc, @@ -20,19 +19,13 @@ import { ObjectUploadParams, ObjectUploadPayload, ObjectUploadResponse, - RhpScanParams, - RhpScanPayload, - RhpScanResponse, WorkerStateParams, WorkerStateResponse, busObjectsRoute, - busHostsRoute, workerAccountIdResetdriftRoute, workerMultipartKeyRoute, workerObjectKeyRoute, - workerRhpScanRoute, workerStateRoute, - Host, } from '@siafoundation/renterd-types' // state @@ -105,53 +98,6 @@ export function useMultipartUploadPart( }) } -const debouncedListRevalidate = debounce((func: () => void) => func(), 5_000) - -export function useRhpScan( - args?: HookArgsCallback -) { - return usePostFunc( - { ...args, route: workerRhpScanRoute }, - async (mutate, { payload: { hostKey } }, response) => { - // Fetching immediately after the response returns stale data so - // we optimistically update without triggering revalidation, - // and then revalidate after a 5s delay. The list revalidation - // is debounced so if the user rescans multiple hosts in quick - // succession the list is optimistically updated n times followed - // by a single network revalidate. - mutate( - (key) => key.startsWith(busHostsRoute), - (data) => - data?.map((h) => { - if (h.publicKey === hostKey) { - return { - ...h, - host: { - ...h, - interactions: { - ...h.interactions, - lastScan: new Date().toISOString(), - lastScanSuccess: !response.data.scanError, - }, - settings: response.data.settings, - }, - } - } - return h - }), - false - ) - debouncedListRevalidate(() => { - mutate( - (key) => key.startsWith(busHostsRoute), - (d) => d, - true - ) - }) - } - ) -} - // accounts export function useAccountResetDrift( diff --git a/libs/renterd-types/src/bus.ts b/libs/renterd-types/src/bus.ts index 4decddfac..a799a9a71 100644 --- a/libs/renterd-types/src/bus.ts +++ b/libs/renterd-types/src/bus.ts @@ -1,6 +1,7 @@ import { Block, Currency, + HostPriceTable, HostSettings, FileContractID, FileContractRevision, @@ -44,6 +45,7 @@ export const busWalletPrepareFormRoute = '/bus/wallet/prepare/form' export const busWalletPrepareRenewRoute = '/bus/wallet/prepare/renew' export const busHostsRoute = '/bus/hosts' export const busHostHostKeyRoute = '/bus/host/:hostkey' +export const busHostHostKeyScanRoute = '/bus/host/:hostkey/scan' export const busHostsHostKeyRoute = '/bus/hosts/:hostkey' export const busHostsBlocklistRoute = '/bus/hosts/blocklist' export const busHostsAllowlistRoute = '/bus/hosts/allowlist' @@ -282,6 +284,19 @@ export type HostResetLostSectorCountParams = { export type HostResetLostSectorCountPayload = void export type HostResetLostSectorCountResponse = void +export type HostScanParams = { + hostkey: string +} +export type HostScanPayload = { + timeout: number +} +export type HostScanResponse = { + ping: string + scanError?: string + settings?: HostSettings + priceTable?: HostPriceTable +} + // contracts export type ContractsParams = void diff --git a/libs/renterd-types/src/worker.ts b/libs/renterd-types/src/worker.ts index f4ac3c7af..8e1206b54 100644 --- a/libs/renterd-types/src/worker.ts +++ b/libs/renterd-types/src/worker.ts @@ -1,10 +1,8 @@ -import { HostSettings } from '@siafoundation/types' import { BusStateResponse } from './bus' export const workerStateRoute = '/worker/state' export const workerObjectKeyRoute = '/worker/object/:key' export const workerMultipartKeyRoute = '/worker/multipart/:key' -export const workerRhpScanRoute = '/worker/rhp/scan' export const workerAccountIdResetdriftRoute = '/worker/account/:id/resetdrift' // state @@ -45,20 +43,6 @@ export type MultipartUploadPartParams = { export type MultipartUploadPartPayload = Blob | Buffer | ArrayBuffer | string export type MultipartUploadPartResponse = void -// rhp - -export type RhpScanParams = void -export type RhpScanPayload = { - hostKey: string - hostIP: string - timeout: number -} -export type RhpScanResponse = { - ping: string - scanError?: string - settings?: HostSettings -} - // accounts export type AccountResetDriftParams = { id: string }