Skip to content

Commit

Permalink
Optimize backend performance: drop subscriptions (#34)
Browse files Browse the repository at this point in the history
* Disable subscriptions

* Log marketplace address

* Drop cache and subscriptions
  • Loading branch information
nikitayutanov authored Mar 29, 2024
1 parent 081ceef commit 88b9c1e
Show file tree
Hide file tree
Showing 17 changed files with 75 additions and 274 deletions.
55 changes: 2 additions & 53 deletions frontend/src/context/indexer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { Kind, OperationTypeNode } from 'graphql';
import { createClient } from 'graphql-ws';

import { ADDRESS } from '@/consts';
import { CollectionsQueryQuery } from '@/graphql/graphql';

const httpLink = new HttpLink({ uri: ADDRESS.INDEXER });
const wsLink = new GraphQLWsLink(createClient({ url: ADDRESS.INDEXER_WS }));
Expand All @@ -22,60 +21,10 @@ const splitLink = split(

const client = new ApolloClient({
link: splitLink,
cache: new InMemoryCache({
typePolicies: {
Query: {
fields: {
nfts: {
keyArgs: ['where', ['owner_eq', 'collection', ['id_eq']]],
merge: (existing: unknown[] = [], incoming: unknown[], { args }: { args: unknown }) => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const offset = args.offset as number;

// Slicing is necessary because the existing data is
// immutable, and frozen in development.
const merged = existing ? existing.slice(0) : [];

for (let i = 0; i < incoming.length; ++i) {
merged[offset + i] = incoming[i];
}

return merged;
},
},

// TODO: make it less mess
collections: {
keyArgs: ['where', ['admin_contains', 'admin_eq']], // admin_eq is for create collection page
merge: (
existing: CollectionsQueryQuery['collections'] = [],
incoming: CollectionsQueryQuery['collections'],
{ args }: { args: unknown },
) => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const offset = args.offset as number;

// Slicing is necessary because the existing data is
// immutable, and frozen in development.
const merged = existing ? existing.slice(0) : [];

for (let i = 0; i < incoming.length; ++i) {
merged[offset + i] = incoming[i];
}

return merged;
},
},
},
},
},
}),
cache: new InMemoryCache(),

defaultOptions: {
query: { notifyOnNetworkStatusChange: true },
watchQuery: { notifyOnNetworkStatusChange: true },
watchQuery: { notifyOnNetworkStatusChange: true, fetchPolicy: 'network-only' },
},
});

Expand Down
4 changes: 4 additions & 0 deletions frontend/src/context/marketplace/context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ProgramMetadata } from '@gear-js/api';
import { ProviderProps, useAlert } from '@gear-js/react-hooks';
import { createContext, useContext, useEffect, useState } from 'react';

import { ADDRESS } from '@/consts';
import { getIpfsLink } from '@/utils';

import { DEFAULT_VALUE, MARKETPLACE_QUERY } from './consts';
Expand All @@ -21,8 +22,11 @@ function MarketplaceProvider({ children }: ProviderProps) {
const [marketplaceMetadata, setMarketplaceMetadata] = useState<ProgramMetadata>();
const [collectionsMetadata, setCollectionsMetadata] = useState<MetadataRecord>();

const logPublicEnvs = () => console.log('public envs: ', { ...ADDRESS, CONTRACT: marketplace?.address });

useEffect(() => {
if (!marketplace) return;
logPublicEnvs();

const { metadata, collectionTypes } = marketplace;
const collectionURLs = collectionTypes.map(({ metaUrl }) => fetch(getIpfsLink(metaUrl)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import styles from './collection-card.module.scss';
type Props = Pick<Collection, 'id' | 'name' | 'collectionBanner' | 'collectionLogo' | 'admin' | 'tokensLimit'> & {
nfts: Pick<Nft, 'id' | 'mediaUrl'>[];
} & {
nftsCount: string | undefined;
nftsCount: number | undefined;
};

const PREVIEW_NFTS_COUNT = 5;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import LandscapeSVG from '../../assets/landscape.svg?react';

type Props = Omit<InfoCardProps, 'heading' | 'text' | 'SVG'> & {
heading: string | null | undefined;
text: string | number | undefined;
text: number | undefined;
};

function MintLimitInfoCard({ heading, text, ...props }: Props) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ type Props = Pick<
'id' | 'tokensLimit' | 'paymentForMint' | 'userMintLimit' | 'permissionToMint' | 'admin'
> & {
nfts: Pick<Nft, 'id' | 'mintedBy'>[];
refetch: () => void;
};

function Component({ id, tokensLimit, paymentForMint, userMintLimit, permissionToMint, admin, nfts }: Props) {
function Component({ id, tokensLimit, paymentForMint, userMintLimit, permissionToMint, admin, nfts, refetch }: Props) {
const sendMessage = useMarketplaceMessage();
const alert = useAlert();
const [isLoading, enableLoading, disableLoading] = useLoading();
Expand Down Expand Up @@ -42,7 +43,11 @@ function Component({ id, tokensLimit, paymentForMint, userMintLimit, permissionT
const percentage = (BigInt(paymentForMint) * BigInt(200)) / BigInt(FEE_MULTIPLIER);
const value = (BigInt(paymentForMint) + percentage).toString();

const onSuccess = () => alert.success('NFT minted');
const onSuccess = () => {
refetch();
alert.success('NFT minted');
};

const onFinally = disableLoading;

sendMessage({ payload, value, onSuccess, onFinally });
Expand Down
18 changes: 4 additions & 14 deletions frontend/src/graphql/gql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,14 @@ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/
*/
const documents = {
"\n query MarketplaceQuery {\n marketplaceById(id: \"1\") {\n address\n collectionTypes {\n description\n metaUrl\n type\n }\n metadata\n config {\n feePerUploadedFile\n minimumValueForTrade\n royaltyToMarketplaceForMint\n royaltyToMarketplaceForTrade\n timeBetweenCreateCollections\n }\n admins\n }\n }\n": types.MarketplaceQueryDocument,
"\n subscription CollectionSub($id: String!) {\n collectionById(id: $id) {\n id\n name\n description\n collectionBanner\n collectionLogo\n admin\n tokensLimit\n permissionToMint\n userMintLimit\n paymentForMint\n transferable\n sellable\n\n additionalLinks {\n discord\n externalUrl\n medium\n xcom\n telegram\n }\n }\n }\n": types.CollectionSubDocument,
"\n query CollectionQuery($id: String!) {\n collectionById(id: $id) {\n id\n name\n description\n collectionBanner\n collectionLogo\n admin\n tokensLimit\n permissionToMint\n userMintLimit\n paymentForMint\n transferable\n sellable\n\n additionalLinks {\n discord\n externalUrl\n medium\n xcom\n telegram\n }\n }\n }\n": types.CollectionQueryDocument,
"\n query LastCreatedCollectionQuery($admin: String!) {\n collections(where: { admin_eq: $admin }, orderBy: [createdAt_DESC, name_DESC, id_DESC], limit: 1) {\n createdAt\n }\n }\n": types.LastCreatedCollectionQueryDocument,
"\n query CollectionsConnectionQuery($where: CollectionWhereInput!) {\n collectionsConnection(orderBy: [createdAt_DESC, name_DESC, id_DESC], where: $where) {\n totalCount\n }\n }\n": types.CollectionsConnectionQueryDocument,
"\n query CollectionsQuery($limit: Int!, $offset: Int!, $where: CollectionWhereInput!) {\n collections(limit: $limit, offset: $offset, orderBy: [createdAt_DESC, name_DESC, id_DESC], where: $where) {\n id\n name\n description\n collectionBanner\n collectionLogo\n admin\n tokensLimit\n\n nfts(limit: 5) {\n id\n mediaUrl\n }\n }\n }\n": types.CollectionsQueryDocument,
"\n subscription CollectionsSub($limit: Int!, $offset: Int!, $where: CollectionWhereInput!) {\n collections(limit: $limit, offset: $offset, orderBy: [createdAt_DESC, name_DESC, id_DESC], where: $where) {\n id\n name\n description\n collectionBanner\n collectionLogo\n admin\n tokensLimit\n\n nfts(limit: 5) {\n id\n mediaUrl\n }\n }\n }\n": types.CollectionsSubDocument,
"\n query CollectionsNFTsCountQuery($ids: [String!]) {\n nftsInCollection(collections: $ids) {\n collection\n count\n }\n }\n": types.CollectionsNfTsCountQueryDocument,
"\n query NFTsConnectionQuery($where: NftWhereInput!) {\n nftsConnection(orderBy: [createdAt_DESC, name_DESC, id_DESC], where: $where) {\n totalCount\n }\n }\n": types.NfTsConnectionQueryDocument,
"\n query NFTsQuery($limit: Int!, $offset: Int!, $where: NftWhereInput!) {\n nfts(limit: $limit, offset: $offset, orderBy: [createdAt_DESC, name_DESC, id_DESC], where: $where) {\n id\n idInCollection\n name\n mediaUrl\n owner\n\n mintedBy\n\n collection {\n id\n name\n transferable\n sellable\n }\n\n sales(where: { status_eq: \"open\" }) {\n price\n }\n\n auctions(where: { status_eq: \"open\" }) {\n minPrice\n lastPrice\n endTimestamp\n }\n }\n }\n": types.NfTsQueryDocument,
"\n subscription NFTsSubscription($limit: Int!, $offset: Int!, $where: NftWhereInput!) {\n nfts(limit: $limit, offset: $offset, orderBy: [createdAt_DESC, name_DESC, id_DESC], where: $where) {\n id\n idInCollection\n name\n mediaUrl\n owner\n\n mintedBy\n\n collection {\n id\n name\n transferable\n sellable\n }\n\n sales(where: { status_eq: \"open\" }) {\n price\n }\n\n auctions(where: { status_eq: \"open\" }) {\n minPrice\n lastPrice\n endTimestamp\n }\n }\n }\n": types.NfTsSubscriptionDocument,
"\n subscription NFTQuery($id: String!) {\n nftById(id: $id) {\n id\n idInCollection\n name\n description\n mediaUrl\n owner\n createdAt\n\n collection {\n id\n name\n royalty\n sellable\n transferable\n\n type {\n type\n }\n }\n\n sales(where: { status_eq: \"open\" }) {\n price\n }\n\n auctions(where: { status_eq: \"open\" }) {\n minPrice\n lastPrice\n endTimestamp\n }\n }\n }\n": types.NftQueryDocument,
"\n query NFTQuery($id: String!) {\n nftById(id: $id) {\n id\n idInCollection\n name\n description\n mediaUrl\n owner\n createdAt\n\n collection {\n id\n name\n royalty\n sellable\n transferable\n\n type {\n type\n }\n }\n\n sales(where: { status_eq: \"open\" }) {\n price\n }\n\n auctions(where: { status_eq: \"open\" }) {\n minPrice\n lastPrice\n endTimestamp\n }\n }\n }\n": types.NftQueryDocument,
};

/**
Expand All @@ -47,7 +45,7 @@ export function graphql(source: "\n query MarketplaceQuery {\n marketplaceBy
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "\n subscription CollectionSub($id: String!) {\n collectionById(id: $id) {\n id\n name\n description\n collectionBanner\n collectionLogo\n admin\n tokensLimit\n permissionToMint\n userMintLimit\n paymentForMint\n transferable\n sellable\n\n additionalLinks {\n discord\n externalUrl\n medium\n xcom\n telegram\n }\n }\n }\n"): (typeof documents)["\n subscription CollectionSub($id: String!) {\n collectionById(id: $id) {\n id\n name\n description\n collectionBanner\n collectionLogo\n admin\n tokensLimit\n permissionToMint\n userMintLimit\n paymentForMint\n transferable\n sellable\n\n additionalLinks {\n discord\n externalUrl\n medium\n xcom\n telegram\n }\n }\n }\n"];
export function graphql(source: "\n query CollectionQuery($id: String!) {\n collectionById(id: $id) {\n id\n name\n description\n collectionBanner\n collectionLogo\n admin\n tokensLimit\n permissionToMint\n userMintLimit\n paymentForMint\n transferable\n sellable\n\n additionalLinks {\n discord\n externalUrl\n medium\n xcom\n telegram\n }\n }\n }\n"): (typeof documents)["\n query CollectionQuery($id: String!) {\n collectionById(id: $id) {\n id\n name\n description\n collectionBanner\n collectionLogo\n admin\n tokensLimit\n permissionToMint\n userMintLimit\n paymentForMint\n transferable\n sellable\n\n additionalLinks {\n discord\n externalUrl\n medium\n xcom\n telegram\n }\n }\n }\n"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
Expand All @@ -60,10 +58,6 @@ export function graphql(source: "\n query CollectionsConnectionQuery($where: Co
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "\n query CollectionsQuery($limit: Int!, $offset: Int!, $where: CollectionWhereInput!) {\n collections(limit: $limit, offset: $offset, orderBy: [createdAt_DESC, name_DESC, id_DESC], where: $where) {\n id\n name\n description\n collectionBanner\n collectionLogo\n admin\n tokensLimit\n\n nfts(limit: 5) {\n id\n mediaUrl\n }\n }\n }\n"): (typeof documents)["\n query CollectionsQuery($limit: Int!, $offset: Int!, $where: CollectionWhereInput!) {\n collections(limit: $limit, offset: $offset, orderBy: [createdAt_DESC, name_DESC, id_DESC], where: $where) {\n id\n name\n description\n collectionBanner\n collectionLogo\n admin\n tokensLimit\n\n nfts(limit: 5) {\n id\n mediaUrl\n }\n }\n }\n"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "\n subscription CollectionsSub($limit: Int!, $offset: Int!, $where: CollectionWhereInput!) {\n collections(limit: $limit, offset: $offset, orderBy: [createdAt_DESC, name_DESC, id_DESC], where: $where) {\n id\n name\n description\n collectionBanner\n collectionLogo\n admin\n tokensLimit\n\n nfts(limit: 5) {\n id\n mediaUrl\n }\n }\n }\n"): (typeof documents)["\n subscription CollectionsSub($limit: Int!, $offset: Int!, $where: CollectionWhereInput!) {\n collections(limit: $limit, offset: $offset, orderBy: [createdAt_DESC, name_DESC, id_DESC], where: $where) {\n id\n name\n description\n collectionBanner\n collectionLogo\n admin\n tokensLimit\n\n nfts(limit: 5) {\n id\n mediaUrl\n }\n }\n }\n"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
Expand All @@ -79,11 +73,7 @@ export function graphql(source: "\n query NFTsQuery($limit: Int!, $offset: Int!
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "\n subscription NFTsSubscription($limit: Int!, $offset: Int!, $where: NftWhereInput!) {\n nfts(limit: $limit, offset: $offset, orderBy: [createdAt_DESC, name_DESC, id_DESC], where: $where) {\n id\n idInCollection\n name\n mediaUrl\n owner\n\n mintedBy\n\n collection {\n id\n name\n transferable\n sellable\n }\n\n sales(where: { status_eq: \"open\" }) {\n price\n }\n\n auctions(where: { status_eq: \"open\" }) {\n minPrice\n lastPrice\n endTimestamp\n }\n }\n }\n"): (typeof documents)["\n subscription NFTsSubscription($limit: Int!, $offset: Int!, $where: NftWhereInput!) {\n nfts(limit: $limit, offset: $offset, orderBy: [createdAt_DESC, name_DESC, id_DESC], where: $where) {\n id\n idInCollection\n name\n mediaUrl\n owner\n\n mintedBy\n\n collection {\n id\n name\n transferable\n sellable\n }\n\n sales(where: { status_eq: \"open\" }) {\n price\n }\n\n auctions(where: { status_eq: \"open\" }) {\n minPrice\n lastPrice\n endTimestamp\n }\n }\n }\n"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "\n subscription NFTQuery($id: String!) {\n nftById(id: $id) {\n id\n idInCollection\n name\n description\n mediaUrl\n owner\n createdAt\n\n collection {\n id\n name\n royalty\n sellable\n transferable\n\n type {\n type\n }\n }\n\n sales(where: { status_eq: \"open\" }) {\n price\n }\n\n auctions(where: { status_eq: \"open\" }) {\n minPrice\n lastPrice\n endTimestamp\n }\n }\n }\n"): (typeof documents)["\n subscription NFTQuery($id: String!) {\n nftById(id: $id) {\n id\n idInCollection\n name\n description\n mediaUrl\n owner\n createdAt\n\n collection {\n id\n name\n royalty\n sellable\n transferable\n\n type {\n type\n }\n }\n\n sales(where: { status_eq: \"open\" }) {\n price\n }\n\n auctions(where: { status_eq: \"open\" }) {\n minPrice\n lastPrice\n endTimestamp\n }\n }\n }\n"];
export function graphql(source: "\n query NFTQuery($id: String!) {\n nftById(id: $id) {\n id\n idInCollection\n name\n description\n mediaUrl\n owner\n createdAt\n\n collection {\n id\n name\n royalty\n sellable\n transferable\n\n type {\n type\n }\n }\n\n sales(where: { status_eq: \"open\" }) {\n price\n }\n\n auctions(where: { status_eq: \"open\" }) {\n minPrice\n lastPrice\n endTimestamp\n }\n }\n }\n"): (typeof documents)["\n query NFTQuery($id: String!) {\n nftById(id: $id) {\n id\n idInCollection\n name\n description\n mediaUrl\n owner\n createdAt\n\n collection {\n id\n name\n royalty\n sellable\n transferable\n\n type {\n type\n }\n }\n\n sales(where: { status_eq: \"open\" }) {\n price\n }\n\n auctions(where: { status_eq: \"open\" }) {\n minPrice\n lastPrice\n endTimestamp\n }\n }\n }\n"];

export function graphql(source: string) {
return (documents as any)[source] ?? {};
Expand Down
Loading

0 comments on commit 88b9c1e

Please sign in to comment.