Skip to content

Commit

Permalink
Merge pull request #1252 from satoshipay/feature/add-horizon-scheduli…
Browse files Browse the repository at this point in the history
…ng-mechanism

Add horizon scheduling mechanism
  • Loading branch information
andywer authored Jun 2, 2021
2 parents 974ebb8 + 393ac1a commit cd4b436
Show file tree
Hide file tree
Showing 8 changed files with 159 additions and 116 deletions.
6 changes: 3 additions & 3 deletions src/Account/components/AccountTransactions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import UpdateIcon from "@material-ui/icons/Update"
import { Account } from "~App/contexts/accounts"
import { SettingsContext } from "~App/contexts/settings"
import { SignatureDelegationContext } from "~App/contexts/signatureDelegation"
import { useHorizonURL } from "~Generic/hooks/stellar"
import { useHorizonURLs } from "~Generic/hooks/stellar"
import {
useLiveRecentTransactions,
useLiveAccountData,
Expand Down Expand Up @@ -69,7 +69,7 @@ function AccountTransactions(props: { account: Account }) {
const { account } = props
const { t } = useTranslation()
const accountData = useLiveAccountData(account.accountID, account.testnet)
const horizonURL = useHorizonURL(account.testnet)
const horizonURLs = useHorizonURLs(account.testnet)
const isSmallScreen = useIsMobile()
const [moreTxsLoadingState, handleMoreTxsFetch] = useLoadingState()
const recentTxs = useLiveRecentTransactions(account.accountID, account.testnet)
Expand Down Expand Up @@ -113,7 +113,7 @@ function AccountTransactions(props: { account: Account }) {
>
{account.testnet ? (
<FriendbotButton
horizonURL={horizonURL}
horizonURL={horizonURLs[0]}
publicKey={account.publicKey}
style={{ marginBottom: isSmallScreen ? 16 : 32 }}
/>
Expand Down
14 changes: 7 additions & 7 deletions src/App/components/DesktopNotifications.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { TFunction } from "i18next"
import React from "react"
import { useTranslation } from "react-i18next"
import { Asset, Horizon, ServerApi } from "stellar-sdk"
import { useHorizonURL } from "~Generic/hooks/stellar"
import { useHorizonURLs } from "~Generic/hooks/stellar"
import { useLiveAccountEffects } from "~Generic/hooks/stellar-subscriptions"
import { useRouter } from "~Generic/hooks/userinterface"
import { useSingleton } from "~Generic/hooks/util"
Expand Down Expand Up @@ -42,8 +42,8 @@ const isPaymentEffect = (effect: ServerApi.EffectRecord) =>
function createEffectHandlers(
router: ReturnType<typeof useRouter>,
netWorker: NetWorker,
mainnetHorizonURL: string,
testnetHorizonURL: string,
mainnetHorizonURLs: string[],
testnetHorizonURLs: string[],
t: TFunction
) {
return {
Expand All @@ -57,7 +57,7 @@ function createEffectHandlers(
? new Asset(effect.sold_asset_code, effect.sold_asset_issuer)
: Asset.native()

const horizonURL = account.testnet ? testnetHorizonURL : mainnetHorizonURL
const horizonURL = account.testnet ? testnetHorizonURLs : mainnetHorizonURLs
const openOffers = await netWorker.fetchAccountOpenOrders(horizonURL, account.accountID)

const orderOnlyPartiallyExecuted = openOffers._embedded.records.find(
Expand Down Expand Up @@ -107,14 +107,14 @@ function DesktopNotifications() {
const { accounts } = React.useContext(AccountsContext)
const { subscribeToNewSignatureRequests } = React.useContext(SignatureDelegationContext)

const mainnetHorizonURL = useHorizonURL(false)
const testnetHorizonURL = useHorizonURL(true)
const mainnetHorizonURLs = useHorizonURLs(false)
const testnetHorizonURLs = useHorizonURLs(true)
const netWorker = useNetWorker()
const router = useRouter()
const { t } = useTranslation()

const effectHandlers = useSingleton(() =>
createEffectHandlers(router, netWorker, mainnetHorizonURL, testnetHorizonURL, t)
createEffectHandlers(router, netWorker, mainnetHorizonURLs, testnetHorizonURLs, t)
)

const handleNewSignatureRequest = React.useCallback(
Expand Down
45 changes: 28 additions & 17 deletions src/App/contexts/stellar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,29 +10,40 @@ interface Props {
interface ContextType {
isSelectionPending: boolean
pendingSelection: Promise<any>
pubnetHorizonURL: string
testnetHorizonURL: string
pubnetHorizonURLs: string[]
testnetHorizonURLs: string[]
}

const initialHorizonSelection = (async () => {
const initialHorizonSelection: Promise<[string[], string[]]> = (async () => {
const { netWorker } = await workers

return Promise.all([
netWorker.checkHorizonOrFailover("https://stellar-horizon.satoshipay.io/", "https://horizon.stellar.org"),
netWorker.checkHorizonOrFailover(
const pubnetHorizonURLs: string[] = Array.from(
new Set(
await Promise.all([
"https://horizon.stellar.org",
netWorker.checkHorizonOrFailover("https://horizon.stellarx.com", "https://horizon.stellar.org"),
netWorker.checkHorizonOrFailover("https://horizon.stellar.lobstr.co", "https://horizon.stellar.org")
])
)
)

const testnetHorizonURLs: string[] = [
await netWorker.checkHorizonOrFailover(
"https://stellar-horizon-testnet.satoshipay.io/",
"https://horizon-testnet.stellar.org"
)
])
]

return Promise.all([pubnetHorizonURLs, testnetHorizonURLs])
})()

initialHorizonSelection.catch(trackError)

const initialValues: ContextType = {
isSelectionPending: true,
pendingSelection: initialHorizonSelection,
pubnetHorizonURL: "https://stellar-horizon.satoshipay.io/",
testnetHorizonURL: "https://stellar-horizon-testnet.satoshipay.io/"
pubnetHorizonURLs: ["https://horizon.stellar.org"],
testnetHorizonURLs: ["https://stellar-horizon-testnet.satoshipay.io/"]
}

const StellarContext = React.createContext<ContextType>(initialValues)
Expand All @@ -48,28 +59,28 @@ export function StellarProvider(props: Props) {
const { netWorker } = await workers

setContextValue(prevState => ({ ...prevState, pendingSelection: initialHorizonSelection }))
const [pubnetHorizonURL, testnetHorizonURL] = await initialHorizonSelection
const [pubnetHorizonURLs, testnetHorizonURLs] = await initialHorizonSelection

if (!cancelled) {
setContextValue(prevState => ({
isSelectionPending: false,
pendingSelection: prevState.pendingSelection,
pubnetHorizonURL:
pubnetHorizonURL !== prevState.pubnetHorizonURL ? pubnetHorizonURL : prevState.pubnetHorizonURL,
testnetHorizonURL:
testnetHorizonURL !== prevState.testnetHorizonURL ? testnetHorizonURL : prevState.testnetHorizonURL
pubnetHorizonURLs:
pubnetHorizonURLs !== prevState.pubnetHorizonURLs ? pubnetHorizonURLs : prevState.pubnetHorizonURLs,
testnetHorizonURLs:
testnetHorizonURLs !== prevState.testnetHorizonURLs ? testnetHorizonURLs : prevState.testnetHorizonURLs
}))

if (
pubnetHorizonURL !== initialValues.pubnetHorizonURL ||
testnetHorizonURL !== initialValues.testnetHorizonURL
pubnetHorizonURLs !== initialValues.pubnetHorizonURLs ||
testnetHorizonURLs !== initialValues.testnetHorizonURLs
) {
await netWorker.resetAllSubscriptions()
resetNetworkCaches()
}

// tslint:disable-next-line no-console
console.debug(`Selected horizon servers:`, { pubnetHorizonURL, testnetHorizonURL })
console.debug(`Selected horizon servers:`, { pubnetHorizonURLs, testnetHorizonURLs })
}
}

Expand Down
30 changes: 18 additions & 12 deletions src/Generic/hooks/_caches.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,12 @@ function createCache<SelectorT, DataT, UpdateT>(
return cache
}

function createAccountCacheKey([horizonURL, accountID]: readonly [string, string]) {
return `${horizonURL}:${accountID}`
function createAccountCacheKey([horizonURLs, accountID]: readonly [string[], string]) {
return `${horizonURLs.map(url => `${url}:`)}${accountID}`
}

function createAssetPairCacheKey([horizonURL, selling, buying]: readonly [string, Asset, Asset]) {
return `${horizonURL}:${stringifyAsset(selling)}:${stringifyAsset(buying)}`
function createAssetPairCacheKey([horizonURLs, selling, buying]: readonly [string[], Asset, Asset]) {
return `${horizonURLs.map(url => `${url}:`)}${stringifyAsset(selling)}:${stringifyAsset(buying)}`
}

export interface TransactionHistory {
Expand Down Expand Up @@ -142,26 +142,32 @@ function areOffersNewer(prev: OfferHistory, next: OfferHistory) {
return !prev || nextMaxTimestamp > prevMaxTimestamp
}

export const accountDataCache = createCache<readonly [string, string], AccountData, AccountData>(createAccountCacheKey)

export const accountHomeDomainCache = createCache<readonly [string, string], [string] | [], AccountData["home_domain"]>(
export const accountDataCache = createCache<readonly [string[], string], AccountData, AccountData>(
createAccountCacheKey
)

export const accountOpenOrdersCache = createCache<readonly [string, string], OfferHistory, ServerApi.OfferRecord[]>(
export const accountHomeDomainCache = createCache<
readonly [string[], string],
[string] | [],
AccountData["home_domain"]
>(createAccountCacheKey)

export const accountOpenOrdersCache = createCache<readonly [string[], string], OfferHistory, ServerApi.OfferRecord[]>(
createAccountCacheKey,
areOffersNewer
)

export const accountTransactionsCache = createCache<
readonly [string, string],
readonly [string[], string],
TransactionHistory,
Horizon.TransactionResponse
>(createAccountCacheKey, areTransactionsNewer)

export const orderbookCache = createCache<readonly [string, Asset, Asset], FixedOrderbookRecord, FixedOrderbookRecord>(
createAssetPairCacheKey
)
export const orderbookCache = createCache<
readonly [string[], Asset, Asset],
FixedOrderbookRecord,
FixedOrderbookRecord
>(createAssetPairCacheKey)

// Storing the array [isPresent, stellarTomlData] is important for distinguishing between
// "the data has not yet been fetched" and "we fetched, but the site doesn't provide any data"
Expand Down
Loading

0 comments on commit cd4b436

Please sign in to comment.