Use new "binTrackRecord" mutation during migration
Does not cause any requests to the trackers during the migration, which prevents getting rate limited closes #1104
This commit is contained in:
@@ -21,27 +21,10 @@ import type {
|
|||||||
MigrationChapter,
|
MigrationChapter,
|
||||||
} from '@/features/migration/Migration.types.ts';
|
} from '@/features/migration/Migration.types.ts';
|
||||||
import { getMetadataServerSettings } from '@/features/settings/services/ServerSettingsMetadata.ts';
|
import { getMetadataServerSettings } from '@/features/settings/services/ServerSettingsMetadata.ts';
|
||||||
import { Queue } from '@/lib/Queue.ts';
|
|
||||||
import type { TrackerIdInfo } from '@/features/tracker/Tracker.types.ts';
|
|
||||||
import { assertIsDefined } from '@/base/Asserts.ts';
|
|
||||||
import { t } from '@lingui/core/macro';
|
import { t } from '@lingui/core/macro';
|
||||||
import { makeToast } from '@/base/utils/Toast.ts';
|
import { makeToast } from '@/base/utils/Toast.ts';
|
||||||
|
|
||||||
export class MangaMigration {
|
export class MangaMigration {
|
||||||
private static trackerQueue = new Map<TrackerIdInfo['id'], Queue>();
|
|
||||||
|
|
||||||
private static getOrCreateQueue(trackerId: TrackerIdInfo['id']): Queue {
|
|
||||||
if (!MangaMigration.trackerQueue.has(trackerId)) {
|
|
||||||
MangaMigration.trackerQueue.set(trackerId, new Queue(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
const queue = MangaMigration.trackerQueue.get(trackerId);
|
|
||||||
|
|
||||||
assertIsDefined(queue);
|
|
||||||
|
|
||||||
return queue;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async migrate(
|
static async migrate(
|
||||||
mangaToMigrate: MangaToMigrate | null | undefined,
|
mangaToMigrate: MangaToMigrate | null | undefined,
|
||||||
mangaToMigrateTo: MangaToMigrateTo | null | undefined,
|
mangaToMigrateTo: MangaToMigrateTo | null | undefined,
|
||||||
@@ -285,24 +268,7 @@ export class MangaMigration {
|
|||||||
return {
|
return {
|
||||||
copy: () =>
|
copy: () =>
|
||||||
trackBindingsToAdd.map(
|
trackBindingsToAdd.map(
|
||||||
(trackRecord) =>
|
(trackRecord) => requestManager.bindTrackRecord(mangaToMigrateTo.id, trackRecord.id).response,
|
||||||
MangaMigration.getOrCreateQueue(trackRecord.trackerId).enqueue(
|
|
||||||
String(mangaToMigrate.id),
|
|
||||||
async () => {
|
|
||||||
try {
|
|
||||||
await requestManager.bindTracker(
|
|
||||||
mangaToMigrateTo.id,
|
|
||||||
trackRecord.trackerId,
|
|
||||||
trackRecord.remoteId,
|
|
||||||
trackRecord.private,
|
|
||||||
).response;
|
|
||||||
} finally {
|
|
||||||
await new Promise((resolve) => {
|
|
||||||
setTimeout(resolve, 500);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
).promise,
|
|
||||||
),
|
),
|
||||||
cleanup: () =>
|
cleanup: () =>
|
||||||
mode === 'migrate'
|
mode === 'migrate'
|
||||||
|
|||||||
@@ -40,6 +40,15 @@ export type BindTrackPayloadFieldPolicy = {
|
|||||||
clientMutationId?: FieldPolicy<any> | FieldReadFunction<any>;
|
clientMutationId?: FieldPolicy<any> | FieldReadFunction<any>;
|
||||||
trackRecord?: FieldPolicy<any> | FieldReadFunction<any>;
|
trackRecord?: FieldPolicy<any> | FieldReadFunction<any>;
|
||||||
};
|
};
|
||||||
|
export type BindTrackRecordPayloadKeySpecifier = (
|
||||||
|
| 'clientMutationId'
|
||||||
|
| 'trackRecord'
|
||||||
|
| BindTrackRecordPayloadKeySpecifier
|
||||||
|
)[];
|
||||||
|
export type BindTrackRecordPayloadFieldPolicy = {
|
||||||
|
clientMutationId?: FieldPolicy<any> | FieldReadFunction<any>;
|
||||||
|
trackRecord?: FieldPolicy<any> | FieldReadFunction<any>;
|
||||||
|
};
|
||||||
export type CategoryEdgeKeySpecifier = ('cursor' | 'node' | CategoryEdgeKeySpecifier)[];
|
export type CategoryEdgeKeySpecifier = ('cursor' | 'node' | CategoryEdgeKeySpecifier)[];
|
||||||
export type CategoryEdgeFieldPolicy = {
|
export type CategoryEdgeFieldPolicy = {
|
||||||
cursor?: FieldPolicy<any> | FieldReadFunction<any>;
|
cursor?: FieldPolicy<any> | FieldReadFunction<any>;
|
||||||
@@ -869,6 +878,7 @@ export type MultiSelectListPreferenceFieldPolicy = {
|
|||||||
};
|
};
|
||||||
export type MutationKeySpecifier = (
|
export type MutationKeySpecifier = (
|
||||||
| 'bindTrack'
|
| 'bindTrack'
|
||||||
|
| 'bindTrackRecord'
|
||||||
| 'clearCachedImages'
|
| 'clearCachedImages'
|
||||||
| 'clearDownloader'
|
| 'clearDownloader'
|
||||||
| 'connectKoSyncAccount'
|
| 'connectKoSyncAccount'
|
||||||
@@ -948,6 +958,7 @@ export type MutationKeySpecifier = (
|
|||||||
)[];
|
)[];
|
||||||
export type MutationFieldPolicy = {
|
export type MutationFieldPolicy = {
|
||||||
bindTrack?: FieldPolicy<any> | FieldReadFunction<any>;
|
bindTrack?: FieldPolicy<any> | FieldReadFunction<any>;
|
||||||
|
bindTrackRecord?: FieldPolicy<any> | FieldReadFunction<any>;
|
||||||
clearCachedImages?: FieldPolicy<any> | FieldReadFunction<any>;
|
clearCachedImages?: FieldPolicy<any> | FieldReadFunction<any>;
|
||||||
clearDownloader?: FieldPolicy<any> | FieldReadFunction<any>;
|
clearDownloader?: FieldPolicy<any> | FieldReadFunction<any>;
|
||||||
connectKoSyncAccount?: FieldPolicy<any> | FieldReadFunction<any>;
|
connectKoSyncAccount?: FieldPolicy<any> | FieldReadFunction<any>;
|
||||||
@@ -2455,6 +2466,10 @@ export type StrictTypedTypePolicies = {
|
|||||||
keyFields?: false | BindTrackPayloadKeySpecifier | (() => undefined | BindTrackPayloadKeySpecifier);
|
keyFields?: false | BindTrackPayloadKeySpecifier | (() => undefined | BindTrackPayloadKeySpecifier);
|
||||||
fields?: BindTrackPayloadFieldPolicy;
|
fields?: BindTrackPayloadFieldPolicy;
|
||||||
};
|
};
|
||||||
|
BindTrackRecordPayload?: Omit<TypePolicy, 'fields' | 'keyFields'> & {
|
||||||
|
keyFields?: false | BindTrackRecordPayloadKeySpecifier | (() => undefined | BindTrackRecordPayloadKeySpecifier);
|
||||||
|
fields?: BindTrackRecordPayloadFieldPolicy;
|
||||||
|
};
|
||||||
CategoryEdge?: Omit<TypePolicy, 'fields' | 'keyFields'> & {
|
CategoryEdge?: Omit<TypePolicy, 'fields' | 'keyFields'> & {
|
||||||
keyFields?: false | CategoryEdgeKeySpecifier | (() => undefined | CategoryEdgeKeySpecifier);
|
keyFields?: false | CategoryEdgeKeySpecifier | (() => undefined | CategoryEdgeKeySpecifier);
|
||||||
fields?: CategoryEdgeFieldPolicy;
|
fields?: CategoryEdgeFieldPolicy;
|
||||||
|
|||||||
@@ -71,6 +71,18 @@ export type BindTrackPayload = {
|
|||||||
trackRecord: TrackRecordType;
|
trackRecord: TrackRecordType;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type BindTrackRecordInput = {
|
||||||
|
clientMutationId?: InputMaybe<Scalars['String']['input']>;
|
||||||
|
mangaId: Scalars['Int']['input'];
|
||||||
|
trackRecordId: Scalars['Int']['input'];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type BindTrackRecordPayload = {
|
||||||
|
__typename?: 'BindTrackRecordPayload';
|
||||||
|
clientMutationId?: Maybe<Scalars['String']['output']>;
|
||||||
|
trackRecord: TrackRecordType;
|
||||||
|
};
|
||||||
|
|
||||||
export type BooleanFilterInput = {
|
export type BooleanFilterInput = {
|
||||||
distinctFrom?: InputMaybe<Scalars['Boolean']['input']>;
|
distinctFrom?: InputMaybe<Scalars['Boolean']['input']>;
|
||||||
distinctFromAll?: InputMaybe<Array<Scalars['Boolean']['input']>>;
|
distinctFromAll?: InputMaybe<Array<Scalars['Boolean']['input']>>;
|
||||||
@@ -1310,6 +1322,7 @@ export type MultiSelectListPreference = {
|
|||||||
export type Mutation = {
|
export type Mutation = {
|
||||||
__typename?: 'Mutation';
|
__typename?: 'Mutation';
|
||||||
bindTrack: BindTrackPayload;
|
bindTrack: BindTrackPayload;
|
||||||
|
bindTrackRecord?: Maybe<BindTrackRecordPayload>;
|
||||||
clearCachedImages: ClearCachedImagesPayload;
|
clearCachedImages: ClearCachedImagesPayload;
|
||||||
clearDownloader?: Maybe<ClearDownloaderPayload>;
|
clearDownloader?: Maybe<ClearDownloaderPayload>;
|
||||||
connectKoSyncAccount: KoSyncConnectPayload;
|
connectKoSyncAccount: KoSyncConnectPayload;
|
||||||
@@ -1391,6 +1404,10 @@ export type MutationBindTrackArgs = {
|
|||||||
input: BindTrackInput;
|
input: BindTrackInput;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type MutationBindTrackRecordArgs = {
|
||||||
|
input: BindTrackRecordInput;
|
||||||
|
};
|
||||||
|
|
||||||
export type MutationClearCachedImagesArgs = {
|
export type MutationClearCachedImagesArgs = {
|
||||||
input: ClearCachedImagesInput;
|
input: ClearCachedImagesInput;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3951,6 +3951,42 @@ export type TrackerBindMutation = {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type TrackerBindTrackRecordMutationVariables = Exact<{
|
||||||
|
input: Types.BindTrackRecordInput;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
export type TrackerBindTrackRecordMutation = {
|
||||||
|
__typename: 'Mutation';
|
||||||
|
bindTrackRecord: {
|
||||||
|
__typename: 'BindTrackRecordPayload';
|
||||||
|
trackRecord: {
|
||||||
|
__typename: 'TrackRecordType';
|
||||||
|
id: number;
|
||||||
|
remoteId: string;
|
||||||
|
trackerId: number;
|
||||||
|
remoteUrl: string;
|
||||||
|
title: string;
|
||||||
|
status: number;
|
||||||
|
lastChapterRead: number;
|
||||||
|
totalChapters: number;
|
||||||
|
score: number;
|
||||||
|
displayScore: string;
|
||||||
|
startDate: string;
|
||||||
|
finishDate: string;
|
||||||
|
private: boolean;
|
||||||
|
manga: {
|
||||||
|
__typename: 'MangaType';
|
||||||
|
id: number;
|
||||||
|
trackRecords: {
|
||||||
|
__typename: 'TrackRecordNodeList';
|
||||||
|
totalCount: number;
|
||||||
|
nodes: Array<{ __typename: 'TrackRecordType'; id: number; trackerId: number }>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} | null;
|
||||||
|
};
|
||||||
|
|
||||||
export type TrackerUnbindMutationVariables = Exact<{
|
export type TrackerUnbindMutationVariables = Exact<{
|
||||||
input: Types.UnbindTrackInput;
|
input: Types.UnbindTrackInput;
|
||||||
}>;
|
}>;
|
||||||
|
|||||||
@@ -69,6 +69,28 @@ export const TRACKER_BIND = gql`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const TRACK_BIND_TRACK_RECORD = gql`
|
||||||
|
${TRACK_RECORD_BIND_FIELDS}
|
||||||
|
|
||||||
|
mutation TRACKER_BIND_TRACK_RECORD($input: BindTrackRecordInput!) {
|
||||||
|
bindTrackRecord(input: $input) {
|
||||||
|
trackRecord {
|
||||||
|
...TRACK_RECORD_BIND_FIELDS
|
||||||
|
manga {
|
||||||
|
id
|
||||||
|
trackRecords {
|
||||||
|
totalCount
|
||||||
|
nodes {
|
||||||
|
id
|
||||||
|
trackerId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
export const TRACKER_UNBIND = gql`
|
export const TRACKER_UNBIND = gql`
|
||||||
mutation TRACKER_UNBIND($input: UnbindTrackInput!) {
|
mutation TRACKER_UNBIND($input: UnbindTrackInput!) {
|
||||||
unbindTrack(input: $input) {
|
unbindTrack(input: $input) {
|
||||||
|
|||||||
@@ -126,6 +126,8 @@ import type {
|
|||||||
StopUpdaterMutationVariables,
|
StopUpdaterMutationVariables,
|
||||||
TrackerBindMutation,
|
TrackerBindMutation,
|
||||||
TrackerBindMutationVariables,
|
TrackerBindMutationVariables,
|
||||||
|
TrackerBindTrackRecordMutation,
|
||||||
|
TrackerBindTrackRecordMutationVariables,
|
||||||
TrackerFetchBindMutation,
|
TrackerFetchBindMutation,
|
||||||
TrackerFetchBindMutationVariables,
|
TrackerFetchBindMutationVariables,
|
||||||
TrackerLoginCredentialsMutation,
|
TrackerLoginCredentialsMutation,
|
||||||
@@ -309,6 +311,7 @@ import type { QueuePriority } from '@/lib/Queue.ts';
|
|||||||
import { SourceAwareQueue } from '@/lib/SourceAwareQueue.ts';
|
import { SourceAwareQueue } from '@/lib/SourceAwareQueue.ts';
|
||||||
import { TRACKER_SEARCH } from '@/lib/graphql/tracker/TrackerQuery.ts';
|
import { TRACKER_SEARCH } from '@/lib/graphql/tracker/TrackerQuery.ts';
|
||||||
import {
|
import {
|
||||||
|
TRACK_BIND_TRACK_RECORD,
|
||||||
TRACKER_BIND,
|
TRACKER_BIND,
|
||||||
TRACKER_FETCH_BIND,
|
TRACKER_FETCH_BIND,
|
||||||
TRACKER_LOGIN_CREDENTIALS,
|
TRACKER_LOGIN_CREDENTIALS,
|
||||||
@@ -3719,6 +3722,19 @@ export class RequestManager {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bindTrackRecord(
|
||||||
|
mangaId: number,
|
||||||
|
trackRecordId: number,
|
||||||
|
options?: MutationOptions<TrackerBindTrackRecordMutation, TrackerBindTrackRecordMutationVariables>,
|
||||||
|
): AbortableApolloMutationResponse<TrackerBindTrackRecordMutation> {
|
||||||
|
return this.doRequest(
|
||||||
|
GQLMethod.MUTATION,
|
||||||
|
TRACK_BIND_TRACK_RECORD,
|
||||||
|
{ input: { mangaId, trackRecordId } },
|
||||||
|
options,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public unbindTracker(
|
public unbindTracker(
|
||||||
recordId: number,
|
recordId: number,
|
||||||
deleteRemoteTrack?: boolean,
|
deleteRemoteTrack?: boolean,
|
||||||
|
|||||||
Reference in New Issue
Block a user