Skip to content

Commit

Permalink
fixup! feat(cardano-services): implement provider selection based on …
Browse files Browse the repository at this point in the history
…env variables and config
  • Loading branch information
ginnun committed Sep 10, 2024
1 parent ced22b9 commit 0d44798
Show file tree
Hide file tree
Showing 2 changed files with 171 additions and 142 deletions.
4 changes: 2 additions & 2 deletions packages/cardano-services/src/Program/options/providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ export enum ProviderImplementation {
BLOCKFROST = 'blockfrost',
DBSYNC = 'dbsync',
// Below ones are specific to TxSubmitProvider
'SUBMIT_NODE' = 'submit-node',
'SUBMIT_API' = 'submit-api'
SUBMIT_NODE = 'submit-node',
SUBMIT_API = 'submit-api'
}

export type ProviderImplementations = {
Expand Down
309 changes: 169 additions & 140 deletions packages/cardano-services/src/Program/programs/providerServer.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
/* eslint-disable complexity */
import { AssetProvider, CardanoNode, HandleProvider, Provider, Seconds, StakePoolProvider } from '@cardano-sdk/core';
import {
AssetProvider,
CardanoNode,
ChainHistoryProvider,
HandleProvider,
Provider,
RewardsProvider,
Seconds,
StakePoolProvider,
UtxoProvider
} from '@cardano-sdk/core';
import { CardanoWsClient, TxSubmitApiProvider } from '@cardano-sdk/cardano-services-client';
import { Logger } from 'ts-log';
import { Observable } from 'rxjs';
import { OgmiosCardanoNode } from '@cardano-sdk/ogmios';
import { PgConnectionConfig } from '@cardano-sdk/projection-typeorm';
import { Pool } from 'pg';
import { SrvRecord } from 'dns';
import { WarmCache } from '../../InMemoryCache/WarmCache';
import { createLogger } from 'bunyan';
import { isNotNil } from '@cardano-sdk/util';
import memoize from 'lodash/memoize.js';
Expand Down Expand Up @@ -54,6 +63,7 @@ import { HttpServer, HttpServerConfig, HttpService, getListen } from '../../Http
import { InMemoryCache, NoCache } from '../../InMemoryCache';
import { MissingProgramOption, MissingServiceDependency, RunnableDependencies, UnknownServiceName } from '../errors';
import { ProviderServerArgs, ProviderServerOptionDescriptions, ServiceNames } from './types';
import { WarmCache } from '../../InMemoryCache/WarmCache';
import { createDbSyncMetadataService } from '../../Metadata';
import { getConnectionConfig, getOgmiosObservableCardanoNode } from '../services';
import { getEntities } from '../../Projection';
Expand Down Expand Up @@ -90,15 +100,25 @@ let sharedHandleProvider: HandleProvider;

const selectProviderImplementation = <T extends Provider>(
impl: ProviderImplementation,
typeorm?: () => T & TypeormProvider,
dbsync?: () => T & Provider,
blockfrost?: () => T & BlockfrostProvider
) =>
(impl === ProviderImplementation.TYPEORM
? typeorm!()
: impl === ProviderImplementation.DBSYNC
? dbsync!()
: blockfrost!()) as T;
impls: {
typeorm?: () => T & TypeormProvider;
dbsync?: () => T & Provider;
blockfrost?: () => T & BlockfrostProvider;
},
logger: Logger,
service?: ServiceNames
) => {
const selected =
impl === ProviderImplementation.TYPEORM
? impls.typeorm!()
: impl === ProviderImplementation.DBSYNC
? impls.dbsync!()
: (impls.blockfrost!() as T);

logger.info(`Selected ${typeof selected} for ${service} provider based on value ${impl}`);

return selected;
};

const serviceMapFactory = (options: ServiceMapFactoryOptions) => {
const { args, pools, dnsResolver, genesisData, logger, node } = options;
Expand Down Expand Up @@ -182,25 +202,6 @@ const serviceMapFactory = (options: ServiceMapFactoryOptions) => {
});
});

const getNetworkInfoProvider = (cardanoNode: CardanoNode, dbPools: DbPools) => {
if (args.useWebSocketApi) return getWebSocketClient().networkInfoProvider;

if (!genesisData)
throw new MissingProgramOption(ServiceNames.NetworkInfo, CommonOptionsDescriptions.CardanoNodeConfigPath);

return new DbSyncNetworkInfoProvider({
cache: {
db: getDbCache(),
healthCheck: healthCheckCache
},
cardanoNode,
dbPools,
epochMonitor: getEpochMonitor(dbPools.main),
genesisData,
logger
});
};

const getHandleProvider = async () => {
if (sharedHandleProvider) return sharedHandleProvider;

Expand Down Expand Up @@ -278,124 +279,152 @@ const serviceMapFactory = (options: ServiceMapFactoryOptions) => {

const getBlockfrostAssetProvider = () => new BlockfrostAssetProvider({ blockfrost: getBlockfrostApi(), logger });

const getBlockfrostEnabledNetworkInfoHttpService = () =>
new NetworkInfoHttpService({
logger,
networkInfoProvider: new BlockfrostNetworkInfoProvider({ blockfrost: getBlockfrostApi(), logger })
});
const getBlockfrostUtxoProvider = () => new BlockfrostUtxoProvider({ blockfrost: getBlockfrostApi(), logger });

const getBlockfrostEnabledChainHistoryHttpService = () =>
new ChainHistoryHttpService({
chainHistoryProvider: new BlockfrostChainHistoryProvider({ blockfrost: getBlockfrostApi(), logger }),
logger
});
const getDbSyncUtxoProvider = withDbSyncProvider(
(dbPools, cardanoNode) =>
new DbSyncUtxoProvider({
cache: {
healthCheck: healthCheckCache
},
cardanoNode,
dbPools,
logger
}),
ServiceNames.Utxo
);

const getBlockfrostEnabledRewardsHttpService = () =>
new RewardsHttpService({
logger,
rewardsProvider: new BlockfrostRewardsProvider({ blockfrost: getBlockfrostApi(), logger })
});
const getBlockfrostNetworkInfoProvider = () =>
new BlockfrostNetworkInfoProvider({ blockfrost: getBlockfrostApi(), logger });

const getBlockfrostTxSubmitProvider = () =>
new BlockfrostTxSubmitProvider({ blockfrost: getBlockfrostApi(), logger });
const getDbSyncNetworkInfoProvider = withDbSyncProvider((dbPools, cardanoNode) => {
if (!genesisData)
throw new MissingProgramOption(ServiceNames.NetworkInfo, CommonOptionsDescriptions.CardanoNodeConfigPath);

const getBlockfrostEnabledUtxoHttpService = () =>
new UtxoHttpService({
logger,
utxoProvider: new BlockfrostUtxoProvider({ blockfrost: getBlockfrostApi(), logger })
return new DbSyncNetworkInfoProvider({
cache: {
db: getDbCache(),
healthCheck: healthCheckCache
},
cardanoNode,
dbPools,
epochMonitor: getEpochMonitor(dbPools.main),
genesisData,
logger
});
}, ServiceNames.NetworkInfo);

const getBlockfrostChainHistoryProvider = () =>
new BlockfrostChainHistoryProvider({ blockfrost: getBlockfrostApi(), logger });

const getDbSyncChainHistoryProvider = withDbSyncProvider(
(dbPools, cardanoNode) =>
new DbSyncChainHistoryProvider(
{ paginationPageSizeLimit: args.paginationPageSizeLimit! },
{
cache: {
healthCheck: healthCheckCache
},
cardanoNode,
dbPools,
logger,
metadataService: createDbSyncMetadataService(dbPools.main, logger)
}
),
ServiceNames.ChainHistory
);

const getBlockfrostRewardsProvider = () => new BlockfrostRewardsProvider({ blockfrost: getBlockfrostApi(), logger });

const getDbSyncRewardsProvider = withDbSyncProvider(
(dbPools, cardanoNode) =>
new DbSyncRewardsProvider(
{ paginationPageSizeLimit: args.paginationPageSizeLimit! },
{
cache: {
healthCheck: healthCheckCache
},
cardanoNode,
dbPools,
logger
}
),
ServiceNames.Rewards
);
const getBlockfrostTxSubmitProvider = () =>
new BlockfrostTxSubmitProvider({ blockfrost: getBlockfrostApi(), logger });

return {
[ServiceNames.Asset]: async () => {
const chosenImplementation = args.useTypeormAssetProvider
? ProviderImplementation.TYPEORM
: args.assetProvider ?? ProviderImplementation.DBSYNC;
const assetProvider = selectProviderImplementation<AssetProvider>(
chosenImplementation,
getTypeormAssetProvider,
getDbSyncAssetProvider,
getBlockfrostAssetProvider
);
return new AssetHttpService({ assetProvider, logger });
},
[ServiceNames.StakePool]: async () => {
const chosenImplementation = args.useTypeormStakePoolProvider
? ProviderImplementation.TYPEORM
: args.stakePoolProvider ?? ProviderImplementation.DBSYNC;

const stakePoolProvider = selectProviderImplementation<StakePoolProvider>(
chosenImplementation,
getTypeormStakePoolProvider,
getDbSyncStakePoolProvider
);

return new StakePoolHttpService({ logger, stakePoolProvider });
},
[ServiceNames.Utxo]:
args.utxoProvider === ProviderImplementation.BLOCKFROST
? getBlockfrostEnabledUtxoHttpService
: withDbSyncProvider(
async (dbPools, cardanoNode) =>
new UtxoHttpService({
logger,
utxoProvider: new DbSyncUtxoProvider({
cache: {
healthCheck: healthCheckCache
},
cardanoNode,
dbPools,
logger
})
}),
ServiceNames.Utxo
),
[ServiceNames.ChainHistory]:
args.chainHistoryProvider === ProviderImplementation.BLOCKFROST
? getBlockfrostEnabledChainHistoryHttpService
: withDbSyncProvider(async (dbPools, cardanoNode) => {
const chainHistoryProvider = new DbSyncChainHistoryProvider(
{ paginationPageSizeLimit: args.paginationPageSizeLimit! },
{
cache: {
healthCheck: healthCheckCache
},
cardanoNode,
dbPools,
logger,
metadataService: createDbSyncMetadataService(dbPools.main, logger)
}
);
return new ChainHistoryHttpService({ chainHistoryProvider, logger });
}, ServiceNames.ChainHistory),
[ServiceNames.Asset]: async () =>
new AssetHttpService({
assetProvider: selectProviderImplementation<AssetProvider>(
args.useTypeormAssetProvider
? ProviderImplementation.TYPEORM
: args.assetProvider ?? ProviderImplementation.DBSYNC,
{ blockfrost: getBlockfrostAssetProvider, dbsync: getDbSyncAssetProvider, typeorm: getTypeormAssetProvider },
logger,
ServiceNames.Asset
),
logger
}),
[ServiceNames.StakePool]: async () =>
new StakePoolHttpService({
logger,
stakePoolProvider: selectProviderImplementation<StakePoolProvider>(
args.useTypeormStakePoolProvider
? ProviderImplementation.TYPEORM
: args.stakePoolProvider ?? ProviderImplementation.DBSYNC,
{ dbsync: getDbSyncStakePoolProvider, typeorm: getTypeormStakePoolProvider },
logger,
ServiceNames.StakePool
)
}),
[ServiceNames.Utxo]: async () =>
new UtxoHttpService({
logger,
utxoProvider: selectProviderImplementation<UtxoProvider>(
args.utxoProvider ?? ProviderImplementation.DBSYNC,
{
blockfrost: getBlockfrostUtxoProvider,
dbsync: getDbSyncUtxoProvider
},
logger,
ServiceNames.Utxo
)
}),
[ServiceNames.ChainHistory]: async () =>
new ChainHistoryHttpService({
chainHistoryProvider: selectProviderImplementation<ChainHistoryProvider>(
args.chainHistoryProvider ?? ProviderImplementation.DBSYNC,
{ blockfrost: getBlockfrostChainHistoryProvider, dbsync: getDbSyncChainHistoryProvider },
logger,
ServiceNames.ChainHistory
),
logger
}),
[ServiceNames.Handle]: async () => new HandleHttpService({ handleProvider: await getHandleProvider(), logger }),
[ServiceNames.Rewards]:
args.rewardsProvider === ProviderImplementation.BLOCKFROST
? getBlockfrostEnabledRewardsHttpService
: withDbSyncProvider(async (dbPools, cardanoNode) => {
const rewardsProvider = new DbSyncRewardsProvider(
{ paginationPageSizeLimit: args.paginationPageSizeLimit! },
{
cache: {
healthCheck: healthCheckCache
},
cardanoNode,
dbPools,
logger
}
);
return new RewardsHttpService({ logger, rewardsProvider });
}, ServiceNames.Rewards),
[ServiceNames.NetworkInfo]:
args.networkInfoProvider === ProviderImplementation.BLOCKFROST
? getBlockfrostEnabledNetworkInfoHttpService
: withDbSyncProvider(
async (dbPools, cardanoNode) =>
new NetworkInfoHttpService({
logger,
networkInfoProvider: getNetworkInfoProvider(cardanoNode, dbPools)
}),
ServiceNames.NetworkInfo
),
[ServiceNames.Rewards]: async () =>
new RewardsHttpService({
logger,
rewardsProvider: selectProviderImplementation<RewardsProvider>(
args.rewardsProvider ?? ProviderImplementation.DBSYNC,
{ blockfrost: getBlockfrostRewardsProvider, dbsync: getDbSyncRewardsProvider },
logger,
ServiceNames.Rewards
)
}),
[ServiceNames.NetworkInfo]: async () => {
const networkInfoProvider =
args.networkInfoProvider === ProviderImplementation.BLOCKFROST
? getBlockfrostNetworkInfoProvider()
: args.useWebSocketApi
? getWebSocketClient().networkInfoProvider
: getDbSyncNetworkInfoProvider();
return new NetworkInfoHttpService({
logger,
networkInfoProvider
});
},
[ServiceNames.TxSubmit]: async () => {
const txSubmitProvider = args.useSubmitApi
? getSubmitApiProvider()
Expand Down

0 comments on commit 0d44798

Please sign in to comment.