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 }