001/* 002 * (C) Copyright 2017 Nuxeo (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Florent Guillaume 018 */ 019package org.nuxeo.runtime.migration; 020 021/** 022 * Migration Service. 023 * 024 * @since 9.3 025 */ 026public interface MigrationService { 027 028 /** 029 * Interface for the implementation of a migrator. 030 * 031 * @since 9.3 032 */ 033 interface Migrator { 034 035 /** 036 * Probes the current state of a migration by analyzing persistent data. 037 * <p> 038 * Assumes no migration step is currently running. 039 * <p> 040 * THIS METHOD MAY TAKE A WHILE as it needs to get information from persistent storage. 041 * 042 * @return the probed state, or {@code null} if it cannot be determined 043 * @since 10.3 044 */ 045 default String probeState() { 046 return null; 047 } 048 049 /** 050 * Runs a migration step. 051 * <p> 052 * This method should periodically check for {@link MigrationContext#isShutdownRequested} and 053 * {@link Thread#isInterrupted} and return if {@code true}. 054 * 055 * @param step the migration step to run 056 * @param migrationContext the migration context. 057 */ 058 void run(String step, MigrationContext migrationContext); 059 060 /** 061 * Allows notification of status change for a running step or new state. 062 * 063 * @since 10.3 064 */ 065 void notifyStatusChange(); 066 } 067 068 /** 069 * Interface for a migration context, passed to the {@link Migrator}. 070 * 071 * @since 9.3 072 */ 073 interface MigrationContext { 074 075 /** 076 * Notifies the migration context of the current progress. 077 * 078 * @param message an informative message about what is being migrated 079 * @param num the current number of things migrated 080 * @param total the total number of things to migrate, or {@code -1} if unknown 081 */ 082 void reportProgress(String message, long num, long total); 083 084 /** 085 * Requests a shutdown. Called internally by the migration service when the server shuts down. 086 */ 087 void requestShutdown(); 088 089 /** 090 * Checks if shutdown has been requested. 091 * <p> 092 * This should be checked periodically by the migrator, and when {@code true} the migrator should return as soon 093 * as possible, even if its work is not complete. 094 * <p> 095 * This is a "nice" version of thread interruption, which will follow a short while later, and should also be 096 * checked by the migrator. 097 * 098 * @return {@code true} if migration should be stopped as soon as possible 099 */ 100 boolean isShutdownRequested(); 101 } 102 103 /** 104 * The status of a migration. 105 * <p> 106 * A migration is either running or not. When not running, it just has a state. 107 * <p> 108 * When running, it has a step, start time, and progress information (message, num, total, last ping time). 109 * 110 * @since 9.3 111 */ 112 public class MigrationStatus { 113 114 protected final String state; 115 116 protected final String step; 117 118 protected final long startTime; 119 120 protected final long pingTime; 121 122 protected final String progressMessage; 123 124 protected final long progressNum; 125 126 protected final long progressTotal; 127 128 public MigrationStatus(String state) { 129 this.state = state; 130 step = null; 131 startTime = 0; 132 pingTime = 0; 133 progressMessage = null; 134 progressNum = 0; 135 progressTotal = 0; 136 } 137 138 public MigrationStatus(String step, long startTime, long pingTime, String progressMessage, long progressNum, 139 long progressTotal) { 140 state = null; 141 this.step = step; 142 this.startTime = startTime; 143 this.pingTime = pingTime; 144 this.progressMessage = progressMessage; 145 this.progressNum = progressNum; 146 this.progressTotal = progressTotal; 147 } 148 149 /** 150 * Checks whether the migration is running. 151 * 152 * @return {@code true} if a migration is running, or {@code false} otherwise 153 */ 154 public boolean isRunning() { 155 return state == null; 156 } 157 158 /** 159 * Gets the state of the migration, if it's not running. 160 */ 161 public String getState() { 162 return state; 163 } 164 165 /** 166 * Gets the step of the migration, if it's running. 167 */ 168 public String getStep() { 169 return step; 170 } 171 172 /** 173 * Gets the start time of the migration, if it's running. 174 */ 175 public long getStartTime() { 176 return startTime; 177 } 178 179 /** 180 * Gets the ping time of the migration, if it's running. 181 */ 182 public long getPingTime() { 183 return pingTime; 184 } 185 186 /** 187 * Gets the progress message of the migration, if it's running. 188 */ 189 public String getProgressMessage() { 190 return progressMessage; 191 } 192 193 /** 194 * Gets the progress "num" of the migration, if it's running. 195 */ 196 public long getProgressNum() { 197 return progressNum; 198 } 199 200 /** 201 * Gets the progress "total" of the migration, if it's running. 202 */ 203 public long getProgressTotal() { 204 return progressTotal; 205 } 206 } 207 208 /** 209 * Gets the current status for a migration. 210 * 211 * @param id the migration id 212 * @return the status, or {@code null} if the migration is unknown 213 */ 214 MigrationStatus getStatus(String id); 215 216 /** 217 * Probes the current state of a migration by analyzing persistent data, and sets it as the new current state. 218 * <p> 219 * THIS METHOD MAY TAKE A WHILE as it needs to get information from persistent storage. 220 * 221 * @param id the migration id 222 * @return the new state, or {@code null} if it cannot be determined 223 * @since 10.3 224 */ 225 String probeAndSetState(String id); 226 227 /** 228 * Runs a migration step for a migration. 229 * <p> 230 * This launches the migration asynchronously. The status of the migration can be checked with {@link #getStatus}. 231 * 232 * @param id the migration id 233 * @param step the step id 234 */ 235 void runStep(String id, String step); 236 237}