
001/*- 002 * #%L 003 * HAPI FHIR JPA Server 004 * %% 005 * Copyright (C) 2014 - 2025 Smile CDR, Inc. 006 * %% 007 * Licensed under the Apache License, Version 2.0 (the "License"); 008 * you may not use this file except in compliance with the License. 009 * You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 * #L% 019 */ 020package ca.uhn.fhir.jpa.entity; 021 022import ca.uhn.fhir.batch2.model.JobDefinition; 023import ca.uhn.fhir.batch2.model.StatusEnum; 024import jakarta.persistence.Basic; 025import jakarta.persistence.Column; 026import jakarta.persistence.Entity; 027import jakarta.persistence.EnumType; 028import jakarta.persistence.Enumerated; 029import jakarta.persistence.FetchType; 030import jakarta.persistence.Id; 031import jakarta.persistence.Index; 032import jakarta.persistence.Lob; 033import jakarta.persistence.Table; 034import jakarta.persistence.Temporal; 035import jakarta.persistence.TemporalType; 036import jakarta.persistence.Version; 037import org.apache.commons.lang3.builder.ToStringBuilder; 038import org.apache.commons.lang3.builder.ToStringStyle; 039import org.hibernate.Length; 040import org.hibernate.annotations.JdbcTypeCode; 041import org.hibernate.type.SqlTypes; 042 043import java.io.Serializable; 044import java.util.Date; 045 046import static ca.uhn.fhir.batch2.model.JobDefinition.ID_MAX_LENGTH; 047import static ca.uhn.fhir.jpa.entity.Batch2WorkChunkEntity.ERROR_MSG_MAX_LENGTH; 048import static ca.uhn.fhir.jpa.entity.Batch2WorkChunkEntity.WARNING_MSG_MAX_LENGTH; 049import static org.apache.commons.lang3.StringUtils.left; 050 051@Entity 052@Table( 053 name = "BT2_JOB_INSTANCE", 054 indexes = {@Index(name = "IDX_BT2JI_CT", columnList = "CREATE_TIME")}) 055public class Batch2JobInstanceEntity implements Serializable { 056 057 public static final int STATUS_MAX_LENGTH = 20; 058 public static final int TIME_REMAINING_LENGTH = 100; 059 public static final int PARAMS_JSON_MAX_LENGTH = 2000; 060 private static final long serialVersionUID = 8187134261799095422L; 061 public static final int INITIATING_USER_NAME_MAX_LENGTH = 200; 062 public static final int INITIATING_CLIENT_ID_MAX_LENGTH = 200; 063 064 @Id 065 @Column(name = "ID", length = JobDefinition.ID_MAX_LENGTH, nullable = false) 066 private String myId; 067 068 @Column(name = "CREATE_TIME", nullable = false) 069 @Temporal(TemporalType.TIMESTAMP) 070 private Date myCreateTime; 071 072 @Column(name = "START_TIME", nullable = true) 073 @Temporal(TemporalType.TIMESTAMP) 074 private Date myStartTime; 075 076 @Column(name = "END_TIME", nullable = true) 077 @Temporal(TemporalType.TIMESTAMP) 078 private Date myEndTime; 079 080 @Version 081 @Column(name = "UPDATE_TIME", nullable = true) 082 @Temporal(TemporalType.TIMESTAMP) 083 private Date myUpdateTime; 084 085 @Column(name = "DEFINITION_ID", length = JobDefinition.ID_MAX_LENGTH, nullable = false) 086 private String myDefinitionId; 087 088 @Column(name = "DEFINITION_VER", nullable = false) 089 private int myDefinitionVersion; 090 091 @Column(name = "STAT", length = STATUS_MAX_LENGTH, nullable = false) 092 @Enumerated(EnumType.STRING) 093 @JdbcTypeCode(SqlTypes.VARCHAR) 094 private StatusEnum myStatus; 095 096 @Column(name = "JOB_CANCELLED", nullable = false) 097 private boolean myCancelled; 098 099 @Column(name = "FAST_TRACKING", nullable = true) 100 private Boolean myFastTracking; 101 102 // TODO: VC column added in 7.2.0 - Remove non-VC column later 103 @Column(name = "PARAMS_JSON", length = PARAMS_JSON_MAX_LENGTH, nullable = true) 104 private String myParamsJson; 105 106 @Lob // TODO: VC column added in 7.2.0 - Remove non-VC column later 107 @Column(name = "PARAMS_JSON_LOB", nullable = true) 108 private String myParamsJsonLob; 109 110 @Column(name = "PARAMS_JSON_VC", nullable = true, length = Length.LONG32) 111 private String myParamsJsonVc; 112 113 @Column(name = "CMB_RECS_PROCESSED", nullable = true) 114 private Integer myCombinedRecordsProcessed; 115 116 @Column(name = "CMB_RECS_PER_SEC", nullable = true) 117 private Double myCombinedRecordsProcessedPerSecond; 118 119 @Column(name = "TOT_ELAPSED_MILLIS", nullable = true) 120 private Integer myTotalElapsedMillis; 121 122 @Column(name = "WORK_CHUNKS_PURGED", nullable = false) 123 private boolean myWorkChunksPurged; 124 125 @Column(name = "PROGRESS_PCT", nullable = false) 126 private double myProgress; 127 128 @Column(name = "ERROR_MSG", length = ERROR_MSG_MAX_LENGTH, nullable = true) 129 private String myErrorMessage; 130 131 @Column(name = "ERROR_COUNT", nullable = false) 132 private int myErrorCount; 133 134 @Column(name = "EST_REMAINING", length = TIME_REMAINING_LENGTH, nullable = true) 135 private String myEstimatedTimeRemaining; 136 137 @Column(name = "CUR_GATED_STEP_ID", length = ID_MAX_LENGTH, nullable = true) 138 private String myCurrentGatedStepId; 139 140 @Column(name = "WARNING_MSG", length = WARNING_MSG_MAX_LENGTH, nullable = true) 141 private String myWarningMessages; 142 143 @Column(name = "USER_NAME", length = INITIATING_USER_NAME_MAX_LENGTH, nullable = true) 144 private String myTriggeringUsername; 145 146 @Column(name = "CLIENT_ID", length = INITIATING_CLIENT_ID_MAX_LENGTH, nullable = true) 147 private String myTriggeringClientId; 148 149 @Column(name = "USER_DATA_JSON", length = Length.LONG32, nullable = true) 150 private String myUserDataJson; 151 152 /** 153 * Any output from the job can be held in this column 154 * Even serialized json 155 */ 156 @Lob // TODO: VC column added in 7.2.0 - Remove non-VC column later 157 @Basic(fetch = FetchType.LAZY) 158 @Column(name = "REPORT", nullable = true, length = Integer.MAX_VALUE - 1) 159 private String myReport; 160 161 @Column(name = "REPORT_VC", nullable = true, length = Length.LONG32) 162 private String myReportVc; 163 164 public String getCurrentGatedStepId() { 165 return myCurrentGatedStepId; 166 } 167 168 public void setCurrentGatedStepId(String theCurrentGatedStepId) { 169 myCurrentGatedStepId = theCurrentGatedStepId; 170 } 171 172 public boolean isCancelled() { 173 return myCancelled; 174 } 175 176 public void setCancelled(boolean theCancelled) { 177 myCancelled = theCancelled; 178 } 179 180 public int getErrorCount() { 181 return myErrorCount; 182 } 183 184 public void setErrorCount(int theErrorCount) { 185 myErrorCount = theErrorCount; 186 } 187 188 public Integer getTotalElapsedMillis() { 189 return myTotalElapsedMillis; 190 } 191 192 public void setTotalElapsedMillis(Integer theTotalElapsedMillis) { 193 myTotalElapsedMillis = theTotalElapsedMillis; 194 } 195 196 public Integer getCombinedRecordsProcessed() { 197 return myCombinedRecordsProcessed; 198 } 199 200 public void setCombinedRecordsProcessed(Integer theCombinedRecordsProcessed) { 201 myCombinedRecordsProcessed = theCombinedRecordsProcessed; 202 } 203 204 public Double getCombinedRecordsProcessedPerSecond() { 205 return myCombinedRecordsProcessedPerSecond; 206 } 207 208 public void setCombinedRecordsProcessedPerSecond(Double theCombinedRecordsProcessedPerSecond) { 209 myCombinedRecordsProcessedPerSecond = theCombinedRecordsProcessedPerSecond; 210 } 211 212 public Date getCreateTime() { 213 return myCreateTime; 214 } 215 216 public void setCreateTime(Date theCreateTime) { 217 myCreateTime = theCreateTime; 218 } 219 220 public Date getStartTime() { 221 return myStartTime; 222 } 223 224 public void setStartTime(Date theStartTime) { 225 myStartTime = theStartTime; 226 } 227 228 public Date getEndTime() { 229 return myEndTime; 230 } 231 232 public void setEndTime(Date theEndTime) { 233 myEndTime = theEndTime; 234 } 235 236 public void setUpdateTime(Date theTime) { 237 myUpdateTime = theTime; 238 } 239 240 public Date getUpdateTime() { 241 return myUpdateTime; 242 } 243 244 public String getId() { 245 return myId; 246 } 247 248 public void setId(String theId) { 249 myId = theId; 250 } 251 252 public String getDefinitionId() { 253 return myDefinitionId; 254 } 255 256 public void setDefinitionId(String theDefinitionId) { 257 myDefinitionId = theDefinitionId; 258 } 259 260 public int getDefinitionVersion() { 261 return myDefinitionVersion; 262 } 263 264 public void setDefinitionVersion(int theDefinitionVersion) { 265 myDefinitionVersion = theDefinitionVersion; 266 } 267 268 public StatusEnum getStatus() { 269 return myStatus; 270 } 271 272 public void setStatus(StatusEnum theStatus) { 273 myStatus = theStatus; 274 } 275 276 public String getParams() { 277 if (myParamsJsonVc != null) { 278 return myParamsJsonVc; 279 } 280 if (myParamsJsonLob != null) { 281 return myParamsJsonLob; 282 } 283 return myParamsJson; 284 } 285 286 public void setParams(String theParams) { 287 myParamsJsonVc = theParams; 288 myParamsJsonLob = null; 289 myParamsJson = null; 290 } 291 292 public boolean getWorkChunksPurged() { 293 return myWorkChunksPurged; 294 } 295 296 public void setWorkChunksPurged(boolean theWorkChunksPurged) { 297 myWorkChunksPurged = theWorkChunksPurged; 298 } 299 300 public double getProgress() { 301 return myProgress; 302 } 303 304 public void setProgress(double theProgress) { 305 myProgress = theProgress; 306 } 307 308 public String getErrorMessage() { 309 return myErrorMessage; 310 } 311 312 public void setErrorMessage(String theErrorMessage) { 313 myErrorMessage = left(theErrorMessage, ERROR_MSG_MAX_LENGTH); 314 } 315 316 public String getEstimatedTimeRemaining() { 317 return myEstimatedTimeRemaining; 318 } 319 320 public void setEstimatedTimeRemaining(String theEstimatedTimeRemaining) { 321 myEstimatedTimeRemaining = left(theEstimatedTimeRemaining, TIME_REMAINING_LENGTH); 322 } 323 324 public String getReport() { 325 return myReportVc != null ? myReportVc : myReport; 326 } 327 328 public void setReport(String theReport) { 329 myReportVc = theReport; 330 myReport = null; 331 } 332 333 public String getWarningMessages() { 334 return myWarningMessages; 335 } 336 337 public void setWarningMessages(String theWarningMessages) { 338 myWarningMessages = theWarningMessages; 339 } 340 341 public String getTriggeringUsername() { 342 return myTriggeringUsername; 343 } 344 345 public Batch2JobInstanceEntity setTriggeringUsername(String theTriggeringUsername) { 346 myTriggeringUsername = theTriggeringUsername; 347 return this; 348 } 349 350 public String getTriggeringClientId() { 351 return myTriggeringClientId; 352 } 353 354 public Batch2JobInstanceEntity setTriggeringClientId(String theTriggeringClientId) { 355 myTriggeringClientId = theTriggeringClientId; 356 return this; 357 } 358 359 @Override 360 public String toString() { 361 return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) 362 .append("id", myId) 363 .append("definitionId", myDefinitionId) 364 .append("definitionVersion", myDefinitionVersion) 365 .append("errorCount", myErrorCount) 366 .append("createTime", myCreateTime) 367 .append("startTime", myStartTime) 368 .append("endTime", myEndTime) 369 .append("updateTime", myUpdateTime) 370 .append("status", myStatus) 371 .append("cancelled", myCancelled) 372 .append("combinedRecordsProcessed", myCombinedRecordsProcessed) 373 .append("combinedRecordsProcessedPerSecond", myCombinedRecordsProcessedPerSecond) 374 .append("totalElapsedMillis", myTotalElapsedMillis) 375 .append("workChunksPurged", myWorkChunksPurged) 376 .append("progress", myProgress) 377 .append("errorMessage", myErrorMessage) 378 .append("estimatedTimeRemaining", myEstimatedTimeRemaining) 379 .append("report", getReport()) 380 .append("warningMessages", myWarningMessages) 381 .append("initiatingUsername", myTriggeringUsername) 382 .append("initiatingclientId", myTriggeringClientId) 383 .toString(); 384 } 385 386 /** 387 * @return true if every step of the job has produced exactly 1 chunk. 388 */ 389 public boolean isFastTracking() { 390 if (myFastTracking == null) { 391 myFastTracking = false; 392 } 393 return myFastTracking; 394 } 395 396 public void setFastTracking(boolean theFastTracking) { 397 myFastTracking = theFastTracking; 398 } 399 400 public String getUserDataJson() { 401 return myUserDataJson; 402 } 403 404 public void setUserDataJson(String theUserDataJson) { 405 myUserDataJson = theUserDataJson; 406 } 407}