Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize backend performance: drop subscriptions #34

Merged
merged 3 commits into from
Mar 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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