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 021import java.util.List; 022 023/** 024 * Migration Service. 025 * 026 * @since 9.3 027 */ 028public interface MigrationService { 029 030 /** 031 * Interface for the implementation of a migrator. 032 * 033 * @since 9.3 034 */ 035 interface Migrator { 036 037 /** 038 * Probes the current state of a migration by analyzing persistent data. 039 * <p> 040 * Assumes no migration step is currently running. 041 * <p> 042 * THIS METHOD MAY TAKE A WHILE as it needs to get information from persistent storage. 043 * 044 * @return the probed state, or {@code null} if it cannot be determined 045 * @since 10.3 046 */ 047 default String probeState() { 048 return null; 049 } 050 051 /** 052 * Runs a migration step. 053 * <p> 054 * This method should periodically check for {@link MigrationContext#isShutdownRequested} and 055 * {@link Thread#isInterrupted()} and return if {@code true}. 056 * 057 * @param step the migration step to run 058 * @param migrationContext the migration context. 059 */ 060 void run(String step, MigrationContext migrationContext); 061 062 /** 063 * Allows notification of status change for a running step or new state. 064 * 065 * @since 10.3 066 */ 067 void notifyStatusChange(); 068 } 069 070 /** 071 * Interface for a migration context, passed to the {@link Migrator}. 072 * 073 * @since 9.3 074 */ 075 interface MigrationContext { 076 077 /** 078 * Notifies the migration context of the current progress. 079 * 080 * @param message an informative message about what is being migrated 081 * @param num the current number of things migrated 082 * @param total the total number of things to migrate, or {@code -1} if unknown 083 */ 084 void reportProgress(String message, long num, long total); 085 086 /** 087 * Requests a shutdown. Called internally by the migration service when the server shuts down. 088 */ 089 void requestShutdown(); 090 091 /** 092 * Checks if shutdown has been requested. 093 * <p> 094 * This should be checked periodically by the migrator, and when {@code true} the migrator should return as soon 095 * as possible, even if its work is not complete. 096 * <p> 097 * This is a "nice" version of thread interruption, which will follow a short while later, and should also be 098 * checked by the migrator. 099 * 100 * @return {@code true} if migration should be stopped as soon as possible 101 */ 102 boolean isShutdownRequested(); 103 } 104 105 /** 106 * The status of a migration. 107 * <p> 108 * A migration is either running or not. When not running, it just has a state. 109 * <p> 110 * When running, it has a step, start time, and progress information (message, num, total, last ping time). 111 * 112 * @since 9.3 113 */ 114 class MigrationStatus { 115 116 protected final String state; 117 118 protected final String step; 119 120 protected final long startTime; 121 122 protected final long pingTime; 123 124 protected final String progressMessage; 125 126 protected final long progressNum; 127 128 protected final long progressTotal; 129 130 public MigrationStatus(String state) { 131 this.state = state; 132 step = null; 133 startTime = 0; 134 pingTime = 0; 135 progressMessage = null; 136 progressNum = 0; 137 progressTotal = 0; 138 } 139 140 public MigrationStatus(String step, long startTime, long pingTime, String progressMessage, long progressNum, 141 long progressTotal) { 142 state = null; 143 this.step = step; 144 this.startTime = startTime; 145 this.pingTime = pingTime; 146 this.progressMessage = progressMessage; 147 this.progressNum = progressNum; 148 this.progressTotal = progressTotal; 149 } 150 151 /** 152 * Checks whether the migration is running. 153 * 154 * @return {@code true} if a migration is running, or {@code false} otherwise 155 */ 156 public boolean isRunning() { 157 return state == null; 158 } 159 160 /** 161 * Gets the state of the migration, if it's not running. 162 */ 163 public String getState() { 164 return state; 165 } 166 167 /** 168 * Gets the step of the migration, if it's running. 169 */ 170 public String getStep() { 171 return step; 172 } 173 174 /** 175 * Gets the start time of the migration, if it's running. 176 */ 177 public long getStartTime() { 178 return startTime; 179 } 180 181 /** 182 * Gets the ping time of the migration, if it's running. 183 */ 184 public long getPingTime() { 185 return pingTime; 186 } 187 188 /** 189 * Gets the progress message of the migration, if it's running. 190 */ 191 public String getProgressMessage() { 192 return progressMessage; 193 } 194 195 /** 196 * Gets the progress "num" of the migration, if it's running. 197 */ 198 public long getProgressNum() { 199 return progressNum; 200 } 201 202 /** 203 * Gets the progress "total" of the migration, if it's running. 204 */ 205 public long getProgressTotal() { 206 return progressTotal; 207 } 208 } 209 210 /** 211 * Gets a migration object. 212 * 213 * @param id the migration id 214 * @return the migration, or {@code null} if the migration is unknown 215 * @since 11.2 216 */ 217 Migration getMigration(String id); 218 219 /** 220 * Gets all the migration objects. 221 * 222 * @return a list of all migrations 223 * @since 11.2 224 */ 225 List<Migration> getMigrations(); 226 227 /** 228 * Gets the current status for a migration. 229 * 230 * @param id the migration id 231 * @return the status, or {@code null} if the migration is unknown 232 */ 233 MigrationStatus getStatus(String id); 234 235 /** 236 * Probes the current state of a migration by analyzing persistent data, and sets it as the new current state. 237 * <p> 238 * THIS METHOD MAY TAKE A WHILE as it needs to get information from persistent storage. 239 * 240 * @param id the migration id 241 * @return the new state, or {@code null} if it cannot be determined 242 * @since 10.3 243 */ 244 String probeAndSetState(String id); 245 246 /** 247 * Probes the migration state and runs a migration. 248 * <p> 249 * THIS METHOD MAY TAKE A WHILE as it may call {@link #probeAndSetState(String)}. 250 * 251 * @param id the migration id 252 * @since 11.2 253 */ 254 void probeAndRun(String id); 255 256 /** 257 * Runs a migration step for a migration. 258 * <p> 259 * This launches the migration asynchronously. The status of the migration can be checked with {@link #getStatus}. 260 * 261 * @param id the migration id 262 * @param step the step id 263 */ 264 void runStep(String id, String step); 265 266}