github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/ui/src/models/task.ts (about)

     1  import { api, ListResponse } from './api'
     2  
     3  const injectedRtkApi = api.injectEndpoints({
     4    endpoints: build => ({
     5      dmapiCreateTask: build.mutation<
     6        { task: Task; check_result: string },
     7        { task: Task }
     8      >({
     9        query: queryArg => ({
    10          url: `/tasks`,
    11          method: 'POST',
    12          body: queryArg,
    13        }),
    14        invalidatesTags: ['Task'],
    15      }),
    16      dmapiGetTaskList: build.query<
    17        ListResponse<Task>,
    18        {
    19          withStatus?: boolean
    20          stage?: TaskStage
    21          sourceNameList?: string[]
    22        }
    23      >({
    24        query: queryArg => ({
    25          url: `/tasks`,
    26          params: {
    27            with_status: queryArg.withStatus,
    28            stage: queryArg.stage,
    29            source_name_list: queryArg.sourceNameList,
    30          },
    31        }),
    32        providesTags: ['Task'],
    33      }),
    34      dmapiDeleteTask: build.mutation<
    35        void,
    36        {
    37          taskName: string
    38          force?: boolean
    39        }
    40      >({
    41        query: queryArg => ({
    42          url: `/tasks/${queryArg.taskName}`,
    43          method: 'DELETE',
    44          params: { force: queryArg.force },
    45        }),
    46        invalidatesTags: ['Task'],
    47      }),
    48      dmapiGetTask: build.query<Task, { taskName: string; withStatus?: boolean }>(
    49        {
    50          query: queryArg => ({
    51            url: `/tasks/${queryArg.taskName}`,
    52            params: { with_status: queryArg.withStatus },
    53          }),
    54        }
    55      ),
    56      dmapiUpdateTask: build.mutation<
    57        { task: Task; check_result: string },
    58        { task: Task }
    59      >({
    60        query: queryArg => ({
    61          url: `/tasks/${queryArg.task.name}`,
    62          method: 'PUT',
    63          body: queryArg,
    64        }),
    65        invalidatesTags: ['Task'],
    66      }),
    67      dmapiGetTaskStatus: build.query<
    68        ListResponse<SubTaskStatus>,
    69        {
    70          taskName: string
    71          sourceNameList?: string[]
    72        }
    73      >({
    74        query: queryArg => ({
    75          url: `/tasks/${queryArg.taskName}/status`,
    76          params: queryArg.sourceNameList
    77            ? { source_name_list: queryArg.sourceNameList }
    78            : undefined,
    79        }),
    80      }),
    81      dmapiStopTask: build.mutation<
    82        void,
    83        {
    84          taskName: string
    85          source_name_list?: string[]
    86          timeout_duration?: any
    87        }
    88      >({
    89        query: queryArg => ({
    90          url: `/tasks/${queryArg.taskName}/stop`,
    91          method: 'POST',
    92          body: {
    93            source_name_list: queryArg.source_name_list,
    94            timeout_duration: queryArg.timeout_duration,
    95          },
    96        }),
    97        invalidatesTags: ['Task'],
    98      }),
    99      dmapiStartTask: build.mutation<void, DmapiStartTaskApiArg>({
   100        query: queryArg => ({
   101          url: `/tasks/${queryArg.taskName}/start`,
   102          method: 'POST',
   103          body: queryArg.startTaskRequest,
   104        }),
   105        invalidatesTags: ['Task'],
   106      }),
   107      dmapiGetSchemaListByTaskAndSource: build.query<
   108        string[],
   109        {
   110          taskName: string
   111          sourceName: string
   112        }
   113      >({
   114        query: queryArg => ({
   115          url: `/tasks/${queryArg.taskName}/sources/${queryArg.sourceName}/schemas`,
   116        }),
   117      }),
   118      dmapiGetTableListByTaskAndSource: build.query<
   119        string[],
   120        {
   121          taskName: string
   122          sourceName: string
   123          schemaName: string
   124        }
   125      >({
   126        query: queryArg => ({
   127          url: `/tasks/${queryArg.taskName}/sources/${queryArg.sourceName}/schemas/${queryArg.schemaName}`,
   128        }),
   129      }),
   130      dmapiConverterTask: build.mutation<
   131        { task: Task; task_config_file: string },
   132        {
   133          task?: Task
   134          task_config_file?: string
   135        }
   136      >({
   137        query: queryArg => ({
   138          url: `/tasks/converters`,
   139          method: 'POST',
   140          body: queryArg,
   141        }),
   142      }),
   143      dmapiGetTaskMigrateTargets: build.query<
   144        ListResponse<TaskMigrateTarget>,
   145        {
   146          taskName: string
   147          sourceName: string
   148          schemaPattern?: string
   149          tablePattern?: string
   150        }
   151      >({
   152        query: queryArg => ({
   153          url: `/tasks/${queryArg.taskName}/sources/${queryArg.sourceName}/migrate_targets`,
   154          params: {
   155            schema_pattern: queryArg.schemaPattern,
   156            table_pattern: queryArg.tablePattern,
   157          },
   158        }),
   159        keepUnusedDataFor: 1,
   160      }),
   161    }),
   162  })
   163  
   164  export type TaskMigrateTarget = {
   165    source_schema: string
   166    source_table: string
   167    target_schema: string
   168    target_table: string
   169  }
   170  
   171  export type DmapiStartTaskApiArg = {
   172    taskName: string
   173    startTaskRequest?: {
   174      remove_meta?: boolean
   175      safe_mode_time_duration?: string
   176      source_name_list?: string[]
   177  
   178      /**
   179       * supported format:
   180       * 2006-01-02T15:04:05 or 2006-01-02T15:04:05
   181       *
   182       */
   183      start_time?: string
   184    }
   185  }
   186  
   187  export type Security = {
   188    ssl_ca_content: string
   189    ssl_cert_content: string
   190    ssl_key_content: string
   191    cert_allowed_cn?: string[]
   192  } | null
   193  
   194  export type TaskTargetDataBase = {
   195    host: string
   196    port: number
   197    user: string
   198    password: string
   199    security?: Security
   200  }
   201  
   202  export type TaskBinLogFilterRule = {
   203    ignore_event?: string[]
   204    ignore_sql?: string[]
   205  }
   206  
   207  export const supportedIgnorableEvents = [
   208    'all',
   209    'all dml',
   210    'all ddl',
   211    'none',
   212    'none ddl',
   213    'none dml',
   214    'insert',
   215    'update',
   216    'delete',
   217    'create database',
   218    'drop database',
   219    'create table',
   220    'create index',
   221    'drop table',
   222    'truncate table',
   223    'rename table',
   224    'drop index',
   225    'alter table',
   226  ] as const
   227  
   228  export type TaskTableMigrateRule = {
   229    source: {
   230      source_name: string
   231      schema: string
   232      table: string
   233    }
   234    target?: {
   235      schema: string
   236      table: string
   237    }
   238    binlog_filter_rule?: string[]
   239  }
   240  
   241  export enum TaskMigrateConsistencyLevel {
   242    Flush = 'flush',
   243    Snapshot = 'snapshot',
   244    Lock = 'lock',
   245    None = 'none',
   246    Auto = 'auto',
   247  }
   248  
   249  export type TaskFullMigrateConf = {
   250    export_threads?: number
   251    import_threads?: number
   252    data_dir?: string
   253    consistency?: TaskMigrateConsistencyLevel
   254  }
   255  
   256  export type TaskIncrMigrateConf = {
   257    repl_threads?: number
   258    repl_batch?: number
   259  }
   260  
   261  export type TaskSourceConf = {
   262    source_name: string
   263    binlog_name?: string
   264    binlog_pos?: number
   265    binlog_gtid?: string
   266  }
   267  
   268  export type TaskSourceConfig = {
   269    full_migrate_conf?: TaskFullMigrateConf
   270    incr_migrate_conf?: TaskIncrMigrateConf
   271    source_conf: TaskSourceConf[]
   272  }
   273  
   274  export enum TaskMode {
   275    FULL = 'full',
   276    INCREMENTAL = 'incremental',
   277    ALL = 'all',
   278  }
   279  
   280  export enum TaskShardMode {
   281    PESSIMISTIC = 'pessimistic',
   282    OPTIMISTIC = 'optimistic',
   283    NONE = 'none',
   284  }
   285  
   286  export enum OnDuplicateBehavior {
   287    OVERWRITE = 'overwrite',
   288    ERROR = 'error',
   289    REPLACE = 'replace',
   290  }
   291  
   292  export type Task = {
   293    name: string
   294    task_mode: TaskMode
   295    shard_mode?: TaskShardMode
   296    meta_schema?: string
   297    enhance_online_schema_change: boolean
   298    on_duplicate: OnDuplicateBehavior
   299    target_config: TaskTargetDataBase
   300    binlog_filter_rule?: {
   301      [key: string]: TaskBinLogFilterRule
   302    }
   303    table_migrate_rule: TaskTableMigrateRule[]
   304    source_config: TaskSourceConfig
   305    status_list?: SubTaskStatus[]
   306  }
   307  
   308  export interface TaskFormData extends Task {
   309    binlog_filter_rule_array?: Array<TaskBinLogFilterRule & { name: string }>
   310    start_after_saved?: boolean
   311  }
   312  
   313  export type LoadStatus = {
   314    finished_bytes: number
   315    total_bytes: number
   316    progress: string
   317    meta_binlog: string
   318    meta_binlog_gtid: string
   319  }
   320  
   321  export type ShardingGroup = {
   322    target: string
   323    ddl_list: string[]
   324    first_location: string
   325    synced: string[]
   326    unsynced: string[]
   327  }
   328  
   329  export type SyncStatus = {
   330    total_events: number
   331    total_tps: number
   332    recent_tps: number
   333    master_binlog: string
   334    master_binlog_gtid: string
   335    syncer_binlog: string
   336    syncer_binlog_gtid: string
   337    blocking_ddls: string[]
   338    unresolved_groups: ShardingGroup[]
   339    synced: boolean
   340    binlog_type: string
   341    seconds_behind_master: number
   342  }
   343  
   344  export type SubTaskStatus = {
   345    name: string
   346    source_name: string
   347    worker_name: string
   348    stage: TaskStage
   349    unit: TaskUnit
   350    unresolved_ddl_lock_id?: string
   351    load_status?: LoadStatus | null
   352    sync_status?: SyncStatus | null
   353  }
   354  
   355  export const {
   356    useDmapiStartTaskMutation,
   357    useDmapiGetTaskListQuery,
   358    useDmapiDeleteTaskMutation,
   359    useDmapiGetTaskStatusQuery,
   360    useDmapiCreateTaskMutation,
   361    useDmapiGetTaskQuery,
   362    useDmapiStopTaskMutation,
   363    useDmapiUpdateTaskMutation,
   364    useDmapiGetSchemaListByTaskAndSourceQuery,
   365    useDmapiGetTableListByTaskAndSourceQuery,
   366    useDmapiConverterTaskMutation,
   367    useDmapiGetTaskMigrateTargetsQuery,
   368  } = injectedRtkApi
   369  
   370  export enum TaskUnit {
   371    InvalidUnit = 'InvalidUnit',
   372    Check = 'Check',
   373    Dump = 'Dump',
   374    Load = 'Load',
   375    Sync = 'Sync',
   376    Relay = 'Relay',
   377  }
   378  
   379  export enum TaskStage {
   380    InvalidStage = 'InvalidStage',
   381    New = 'New',
   382    Running = 'Running',
   383    Paused = 'Paused',
   384    Stopped = 'Stopped',
   385    Finished = 'Finished',
   386    Pausing = 'Pausing',
   387    Resuming = 'Resuming',
   388    Stopping = 'Stopping',
   389  }
   390  
   391  // https://github.com/pingcap/tiflow/blob/9261014edd93902d1b0bcb473aec911e80901721/dm/dm/ctl/master/query_status.go#L130
   392  export const calculateTaskStatus = (subtasks?: SubTaskStatus[]): TaskStage => {
   393    if (!subtasks) {
   394      return TaskStage.InvalidStage
   395    }
   396  
   397    // TODO Error status
   398    if (subtasks.some(subtask => subtask.stage === TaskStage.Resuming)) {
   399      return TaskStage.Resuming
   400    }
   401  
   402    if (subtasks.some(subtask => subtask.stage === TaskStage.Pausing)) {
   403      return TaskStage.Pausing
   404    }
   405  
   406    if (subtasks.some(subtask => subtask.stage === TaskStage.Paused)) {
   407      return TaskStage.Paused
   408    }
   409  
   410    if (subtasks.every(subtask => subtask.stage === TaskStage.New)) {
   411      return TaskStage.New
   412    }
   413  
   414    if (subtasks.every(subtask => subtask.stage === TaskStage.Finished)) {
   415      return TaskStage.Finished
   416    }
   417  
   418    if (subtasks.every(subtask => subtask.stage === TaskStage.Stopped)) {
   419      return TaskStage.Stopped
   420    }
   421  
   422    return TaskStage.Running
   423  }