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,
|
||||
} from '@/features/migration/Migration.types.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 { makeToast } from '@/base/utils/Toast.ts';
|
||||
|
||||
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(
|
||||
mangaToMigrate: MangaToMigrate | null | undefined,
|
||||
mangaToMigrateTo: MangaToMigrateTo | null | undefined,
|
||||
@@ -285,24 +268,7 @@ export class MangaMigration {
|
||||
return {
|
||||
copy: () =>
|
||||
trackBindingsToAdd.map(
|
||||
(trackRecord) =>
|
||||
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,
|
||||
(trackRecord) => requestManager.bindTrackRecord(mangaToMigrateTo.id, trackRecord.id).response,
|
||||
),
|
||||
cleanup: () =>
|
||||
mode === 'migrate'
|
||||
|
||||
@@ -40,6 +40,15 @@ export type BindTrackPayloadFieldPolicy = {
|
||||
clientMutationId?: 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 CategoryEdgeFieldPolicy = {
|
||||
cursor?: FieldPolicy<any> | FieldReadFunction<any>;
|
||||
@@ -869,6 +878,7 @@ export type MultiSelectListPreferenceFieldPolicy = {
|
||||
};
|
||||
export type MutationKeySpecifier = (
|
||||
| 'bindTrack'
|
||||
| 'bindTrackRecord'
|
||||
| 'clearCachedImages'
|
||||
| 'clearDownloader'
|
||||
| 'connectKoSyncAccount'
|
||||
@@ -948,6 +958,7 @@ export type MutationKeySpecifier = (
|
||||
)[];
|
||||
export type MutationFieldPolicy = {
|
||||
bindTrack?: FieldPolicy<any> | FieldReadFunction<any>;
|
||||
bindTrackRecord?: FieldPolicy<any> | FieldReadFunction<any>;
|
||||
clearCachedImages?: FieldPolicy<any> | FieldReadFunction<any>;
|
||||
clearDownloader?: FieldPolicy<any> | FieldReadFunction<any>;
|
||||
connectKoSyncAccount?: FieldPolicy<any> | FieldReadFunction<any>;
|
||||
@@ -2455,6 +2466,10 @@ export type StrictTypedTypePolicies = {
|
||||
keyFields?: false | BindTrackPayloadKeySpecifier | (() => undefined | BindTrackPayloadKeySpecifier);
|
||||
fields?: BindTrackPayloadFieldPolicy;
|
||||
};
|
||||
BindTrackRecordPayload?: Omit<TypePolicy, 'fields' | 'keyFields'> & {
|
||||
keyFields?: false | BindTrackRecordPayloadKeySpecifier | (() => undefined | BindTrackRecordPayloadKeySpecifier);
|
||||
fields?: BindTrackRecordPayloadFieldPolicy;
|
||||
};
|
||||
CategoryEdge?: Omit<TypePolicy, 'fields' | 'keyFields'> & {
|
||||
keyFields?: false | CategoryEdgeKeySpecifier | (() => undefined | CategoryEdgeKeySpecifier);
|
||||
fields?: CategoryEdgeFieldPolicy;
|
||||
|
||||
@@ -71,6 +71,18 @@ export type BindTrackPayload = {
|
||||
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 = {
|
||||
distinctFrom?: InputMaybe<Scalars['Boolean']['input']>;
|
||||
distinctFromAll?: InputMaybe<Array<Scalars['Boolean']['input']>>;
|
||||
@@ -1310,6 +1322,7 @@ export type MultiSelectListPreference = {
|
||||
export type Mutation = {
|
||||
__typename?: 'Mutation';
|
||||
bindTrack: BindTrackPayload;
|
||||
bindTrackRecord?: Maybe<BindTrackRecordPayload>;
|
||||
clearCachedImages: ClearCachedImagesPayload;
|
||||
clearDownloader?: Maybe<ClearDownloaderPayload>;
|
||||
connectKoSyncAccount: KoSyncConnectPayload;
|
||||
@@ -1391,6 +1404,10 @@ export type MutationBindTrackArgs = {
|
||||
input: BindTrackInput;
|
||||
};
|
||||
|
||||
export type MutationBindTrackRecordArgs = {
|
||||
input: BindTrackRecordInput;
|
||||
};
|
||||
|
||||
export type MutationClearCachedImagesArgs = {
|
||||
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<{
|
||||
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`
|
||||
mutation TRACKER_UNBIND($input: UnbindTrackInput!) {
|
||||
unbindTrack(input: $input) {
|
||||
|
||||
@@ -126,6 +126,8 @@ import type {
|
||||
StopUpdaterMutationVariables,
|
||||
TrackerBindMutation,
|
||||
TrackerBindMutationVariables,
|
||||
TrackerBindTrackRecordMutation,
|
||||
TrackerBindTrackRecordMutationVariables,
|
||||
TrackerFetchBindMutation,
|
||||
TrackerFetchBindMutationVariables,
|
||||
TrackerLoginCredentialsMutation,
|
||||
@@ -309,6 +311,7 @@ import type { QueuePriority } from '@/lib/Queue.ts';
|
||||
import { SourceAwareQueue } from '@/lib/SourceAwareQueue.ts';
|
||||
import { TRACKER_SEARCH } from '@/lib/graphql/tracker/TrackerQuery.ts';
|
||||
import {
|
||||
TRACK_BIND_TRACK_RECORD,
|
||||
TRACKER_BIND,
|
||||
TRACKER_FETCH_BIND,
|
||||
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(
|
||||
recordId: number,
|
||||
deleteRemoteTrack?: boolean,
|
||||
|
||||
Reference in New Issue
Block a user