Skip to content

Commit

Permalink
[release] @subql/[email protected] @subql/[email protected]
Browse files Browse the repository at this point in the history
* implement state manager

* get signed state

* support both old and new state

* minor fixes

* update logs

* fix state cache

* apollo-links support channel performance

* revert main file config

* deal with base64 encoded authorization error message
enhance debug log

* pass state store for apollo-links and eth-provider

* [release] @subql/[email protected] @subql/[email protected]
  • Loading branch information
icezohu authored Apr 29, 2024
1 parent 6506128 commit d71862b
Show file tree
Hide file tree
Showing 19 changed files with 370 additions and 105 deletions.
30 changes: 21 additions & 9 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
"parserOptions": {
"sourceType": "module"
},
"plugins": ["@typescript-eslint/eslint-plugin", "header"],
"plugins": [
"@typescript-eslint/eslint-plugin",
"header"
],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended"
Expand All @@ -14,17 +17,26 @@
"jest": true,
"browser": true
},
"ignorePatterns": ["**/packages/**/dist/**", "/test/jest-setup.ts"],
"ignorePatterns": [
"**/packages/**/dist/**",
"/test/jest-setup.ts"
],
"rules": {
"@typescript-eslint/interface-name-prefix": "off",
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/no-explicit-any": "off",
"header/header": [2, "line", [
{
"pattern": " Copyright \\d{4}(-\\d{4})? SubQuery Pte Ltd authors & contributors",
"template": " Copyright 2020-2023 SubQuery Pte Ltd authors & contributors" },
" SPDX-License-Identifier: Apache-2.0"
], 2]
"header/header": [
2,
"line",
[
{
"pattern": " Copyright \\d{4}(-\\d{4})? SubQuery Pte Ltd authors & contributors",
"template": " Copyright 2020-2024 SubQuery Pte Ltd authors & contributors"
},
" SPDX-License-Identifier: Apache-2.0"
],
2
]
}
}
}
5 changes: 4 additions & 1 deletion packages/apollo-links/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [1.4.0] - 2024-04-29

## [1.3.2] - 2024-01-26

## [1.3.0] - 2024-01-22
Expand Down Expand Up @@ -96,7 +98,8 @@ Breaking change for `dictHttpLink` and `deploymentHttpLink`, use `const { link }

- Add Authlink for Apollo client

[unreleased]: https://github.com/subquery/network-clients/compare/v1.3.2...HEAD
[unreleased]: https://github.com/subquery/network-clients/compare/v1.4.0...HEAD
[1.4.0]: https://github.com/subquery/network-clients/compare/v1.3.2...v1.4.0
[1.3.2]: https://github.com/subquery/network-clients/compare/v1.3.0...v1.3.2
[1.3.0]: https://github.com/subquery/network-clients/compare/v1.2.6...v1.3.0
[1.2.6]: https://github.com/subquery/network-clients/compare/v1.2.4...v1.2.6
Expand Down
2 changes: 1 addition & 1 deletion packages/apollo-links/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@subql/apollo-links",
"version": "1.3.2",
"version": "1.4.0",
"description": "SubQuery Network - graphql links",
"main": "dist/index.js",
"author": "SubQuery Pte Limited",
Expand Down
4 changes: 3 additions & 1 deletion packages/apollo-links/src/authHttpLink.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// SPDX-License-Identifier: Apache-2.0

import { ApolloLink, from } from '@apollo/client/core';

import {
IStore,
OrderManager,
Expand All @@ -28,6 +27,7 @@ interface BaseAuthOptions {
logger?: Logger; // logger for `AuthLink`
fallbackServiceUrl?: string; // fall back service url for `AuthLink`
scoreStore?: IStore; // pass store in, so it doesn't get lost between page refresh
stateStore?: IStore;
selector?: RunnerSelector;
maxRetries?: number;
useImmediateFallbackOnError?: boolean;
Expand Down Expand Up @@ -68,6 +68,7 @@ function authHttpLink(options: AuthOptions): AuthHttpLink {
authUrl,
projectType,
scoreStore,
stateStore,
maxRetries,
useImmediateFallbackOnError = false,
logger: _logger,
Expand All @@ -84,6 +85,7 @@ function authHttpLink(options: AuthOptions): AuthHttpLink {
projectType,
logger,
scoreStore,
stateStore,
responseFormat: ResponseFormat.Inline,
selector,
timeout,
Expand Down
4 changes: 2 additions & 2 deletions packages/apollo-links/src/core/clusterAuthLink.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ export class ClusterAuthLink extends ApolloLink {
.getRequestParams(this.getRequestId(operation))
.then((params) => {
if (params) {
const { headers, url, type, runner } = params;
operation.setContext({ url, headers, type, indexer: runner });
const { headers, url, type, runner, channelId } = params;
operation.setContext({ url, headers, type, indexer: runner, channelId });
sub = forward(operation).subscribe(observer);
} else {
this.logger?.debug('no available orders');
Expand Down
45 changes: 18 additions & 27 deletions packages/apollo-links/src/core/responseLink.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

import { ApolloLink, FetchResult, NextLink, Observable, Operation } from '@apollo/client/core';
import { ChannelState, OrderManager, OrderType, POST, ScoreType } from '@subql/network-support';
import { ChannelState, OrderManager, OrderType, ScoreType, State } from '@subql/network-support';
import { Base64 } from 'js-base64';
import { Logger } from '../utils/logger';

Expand All @@ -13,57 +13,48 @@ export type ResponseLinkOptions = {
};

export class ResponseLink extends ApolloLink {
private options: ResponseLinkOptions;

constructor(private option: ResponseLinkOptions) {
constructor(private options: ResponseLinkOptions) {
super();
this.options = option;
}

get logger(): Logger | undefined {
return this.options.logger;
}

async syncChannelState(state: ChannelState): Promise<void> {
try {
const stateUrl = new URL('/channel/state', this.options.authUrl);
const res = await POST<{ consumerSign: string }>(stateUrl.toString(), state);

if (res.consumerSign) {
this.logger?.debug(`syncChannelState succeed`);
} else {
this.logger?.debug(`syncChannelState failed: ${JSON.stringify(res)}`);
}
} catch (e) {
this.logger?.debug(`syncChannelState failed: ${String(e)}`);
}
}

override request(operation: Operation, forward: NextLink): Observable<FetchResult> | null {
if (!forward) return null;

const { type, indexer } = operation.getContext();
const { type, indexer, channelId } = operation.getContext();

return new Observable<FetchResult>((observer) => {
const subscription = forward(operation).subscribe({
next: (response: FetchResult<Record<string, any>> & { state: ChannelState }) => {
next: (response: FetchResult<Record<string, any>> & { state: State | ChannelState }) => {
if (!response.errors || response.errors?.length === 0) {
this.options.orderManager.updateScore(indexer, ScoreType.SUCCESS);
}

if (type === OrderType.flexPlan) {
const responseHeaders = operation.getContext().response.headers;
if (responseHeaders) {
const channelState = responseHeaders.get('X-Channel-State')
? (JSON.parse(
let channelState: State | ChannelState;
if (responseHeaders.get('X-Channel-State')) {
try {
channelState = JSON.parse(
Base64.decode(responseHeaders.get('X-Channel-State')).toString()
) as ChannelState)
: response.state;
) as ChannelState;
} catch {
channelState = {
authorization: responseHeaders.get('X-Channel-State'),
};
}
} else {
channelState = response.state;
}

if (!channelState) {
this.logger?.debug("Can't find the channel state information");
}
void this.syncChannelState(channelState);
void this.options.orderManager.syncChannelState(channelId, channelState);
}
}

Expand Down
22 changes: 14 additions & 8 deletions packages/eth-provider/src/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
ProjectType,
ResponseFormat,
ScoreType,
State,
generateUniqueId,
silentLogger,
} from '@subql/network-support';
Expand All @@ -39,6 +40,7 @@ interface Options {
logger?: Logger; // logger for `AuthLink`
fallbackUrl?: string | ConnectionInfo; // fall back service url for `AuthLink`
scoreStore?: IStore; // pass store in, so it doesn't get lost between page refresh
stateStore?: IStore;
maxRetries?: number;
network?: Networkish;
}
Expand All @@ -62,6 +64,8 @@ export class SubqueryAuthedRpcProvider extends JsonRpcProvider {
projectType: ProjectType.deployment,
logger: this.logger,
responseFormat: ResponseFormat.Wrapped,
scoreStore: opt.scoreStore,
stateStore: opt.stateStore,
});
}

Expand Down Expand Up @@ -91,8 +95,7 @@ export class SubqueryAuthedRpcProvider extends JsonRpcProvider {
const requestResult: () => Promise<string> = async () => {
const requestParams = await this.orderManager.getRequestParams(requestId);
if (requestParams) {
// eslint-disable-next-line @typescript-eslint/unbound-method
const { url, headers, type, runner } = requestParams;
const { url, headers, type, runner, channelId } = requestParams;
try {
const result = await this._send(
{
Expand All @@ -102,6 +105,7 @@ export class SubqueryAuthedRpcProvider extends JsonRpcProvider {
request,
{
type,
channelId,
}
);

Expand Down Expand Up @@ -142,13 +146,15 @@ export class SubqueryAuthedRpcProvider extends JsonRpcProvider {
async _send(
url: string | ConnectionInfo,
request: unknown,
options: {
options?: {
type?: OrderType;
} = {}
channelId?: string;
}
): Promise<any> {
const { type } = options;
const type = options?.type;
const channelId = options?.channelId;
let result;
let state: ChannelState | undefined;
let state: State | ChannelState | undefined;
try {
result = await fetchJson(url, JSON.stringify(request), (payload, resp) => {
let res = payload;
Expand Down Expand Up @@ -186,8 +192,8 @@ export class SubqueryAuthedRpcProvider extends JsonRpcProvider {
});
throw error;
}
if (state && type === OrderType.flexPlan) {
void this.orderManager.syncChannelState(state);
if (type === OrderType.flexPlan && channelId && state) {
void this.orderManager.syncChannelState(channelId, state);
}
return result;
}
Expand Down
5 changes: 4 additions & 1 deletion packages/network-support/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [1.2.0] 2024-04-29

## [1.1.2] 2024-04-08

## [1.1.1] 2024-03-22
Expand All @@ -25,7 +27,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- It's a internal library.

[unreleased]: https://github.com/subquery/network-support/compare/v1.1.2...HEAD
[unreleased]: https://github.com/subquery/network-support/compare/v1.2.0...HEAD
[1.2.0]: https://github.com/subquery/network-support/releases/tag/v1.2.0
[1.1.2]: https://github.com/subquery/network-support/releases/tag/v1.1.2
[1.1.1]: https://github.com/subquery/network-support/releases/tag/v1.1.1
[1.1.0]: https://github.com/subquery/network-support/releases/tag/v1.1.0
Expand Down
5 changes: 3 additions & 2 deletions packages/network-support/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@subql/network-support",
"version": "1.1.2",
"version": "1.2.0",
"main": "dist/index.js",
"author": "SubQuery Pte Limited",
"license": "Apache-2.0",
Expand All @@ -13,7 +13,8 @@
"cross-fetch": "^4.0.0",
"js-base64": "^3.7.5",
"jwt-decode": "^3.1.2",
"lru-cache": "^10.0.1"
"lru-cache": "^10.0.1",
"semver": "^7.6.0"
},
"devDependencies": {
"@types/node": "18",
Expand Down
10 changes: 6 additions & 4 deletions packages/network-support/src/fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { customFetch, generateUniqueId, Logger } from './utils';
import { ChannelState, OrderType } from './types';
import { ScoreType } from './scoreManager';
import { Base64 } from 'js-base64';
import { State } from './stateManager';

interface SystemError extends Error {
code?: string | undefined;
Expand Down Expand Up @@ -55,13 +56,14 @@ export function createFetch(
headers: {},
type: OrderType.fallback,
runner: 'fallback',
channelId: 'fallback',
};
logger?.warn(`fallback to ${orderManager.fallbackServiceUrl}`);
} else {
throw new FetchError(`no available order`, 'sqn');
}
}
const { url, headers, type, runner } = requestParams;
const { url, headers, type, runner, channelId } = requestParams;
try {
const _res = await customFetch(url, {
headers: {
Expand All @@ -71,7 +73,7 @@ export function createFetch(
method: 'post',
body: init.body,
});
let state: ChannelState | undefined, res: object;
let state: State | ChannelState | undefined, res: object;
if (type === OrderType.flexPlan) {
[res, state] = orderManager.extractChannelState(
await _res.json(),
Expand All @@ -91,8 +93,8 @@ export function createFetch(
}

orderManager.updateScore(runner, ScoreType.SUCCESS);
if (state && type === OrderType.flexPlan) {
void orderManager.syncChannelState(state);
if (type === OrderType.flexPlan && channelId && state) {
void orderManager.syncChannelState(channelId, state);
}
return {
status: _res.status,
Expand Down
1 change: 1 addition & 0 deletions packages/network-support/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@
export * from './types';
export * from './orderManager';
export * from './scoreManager';
export * from './stateManager';
export * from './utils';
export * from './fetch';
Loading

0 comments on commit d71862b

Please sign in to comment.