001/*- 002 * #%L 003 * HAPI FHIR JPA Server 004 * %% 005 * Copyright (C) 2014 - 2024 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.WorkChunk; 023import ca.uhn.fhir.batch2.model.WorkChunkStatusEnum; 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.ForeignKey; 031import jakarta.persistence.Id; 032import jakarta.persistence.Index; 033import jakarta.persistence.JoinColumn; 034import jakarta.persistence.Lob; 035import jakarta.persistence.ManyToOne; 036import jakarta.persistence.Table; 037import jakarta.persistence.Temporal; 038import jakarta.persistence.TemporalType; 039import jakarta.persistence.Version; 040import org.apache.commons.lang3.builder.ToStringBuilder; 041import org.apache.commons.lang3.builder.ToStringStyle; 042import org.hibernate.Length; 043 044import java.io.Serializable; 045import java.util.Date; 046 047import static ca.uhn.fhir.batch2.model.JobDefinition.ID_MAX_LENGTH; 048import static ca.uhn.fhir.jpa.entity.Batch2JobInstanceEntity.STATUS_MAX_LENGTH; 049import static org.apache.commons.lang3.StringUtils.left; 050 051@Entity 052@Table( 053 name = "BT2_WORK_CHUNK", 054 indexes = { 055 @Index(name = "IDX_BT2WC_II_SEQ", columnList = "INSTANCE_ID,SEQ"), 056 @Index(name = "IDX_BT2WC_II_SI_S_SEQ_ID", columnList = "INSTANCE_ID,TGT_STEP_ID,STAT,SEQ,ID") 057 }) 058public class Batch2WorkChunkEntity implements Serializable { 059 060 public static final int ERROR_MSG_MAX_LENGTH = 500; 061 public static final int WARNING_MSG_MAX_LENGTH = 4000; 062 private static final long serialVersionUID = -6202771941965780558L; 063 064 @Id 065 @Column(name = "ID", length = ID_MAX_LENGTH) 066 private String myId; 067 068 @Column(name = "SEQ", nullable = false) 069 private int mySequence; 070 071 @Column(name = "CREATE_TIME", nullable = false) 072 @Temporal(TemporalType.TIMESTAMP) 073 private Date myCreateTime; 074 075 @Column(name = "START_TIME", nullable = true) 076 @Temporal(TemporalType.TIMESTAMP) 077 private Date myStartTime; 078 079 @Column(name = "END_TIME", nullable = true) 080 @Temporal(TemporalType.TIMESTAMP) 081 private Date myEndTime; 082 083 @Version 084 @Column(name = "UPDATE_TIME", nullable = true) 085 @Temporal(TemporalType.TIMESTAMP) 086 private Date myUpdateTime; 087 088 @Column(name = "RECORDS_PROCESSED", nullable = true) 089 private Integer myRecordsProcessed; 090 091 @Column(name = "DEFINITION_ID", length = ID_MAX_LENGTH, nullable = false) 092 private String myJobDefinitionId; 093 094 @Column(name = "DEFINITION_VER", length = ID_MAX_LENGTH, nullable = false) 095 private int myJobDefinitionVersion; 096 097 @Column(name = "TGT_STEP_ID", length = ID_MAX_LENGTH, nullable = false) 098 private String myTargetStepId; 099 100 @Lob // TODO: VC column added in 7.2.0 - Remove non-VC column later 101 @Basic(fetch = FetchType.LAZY) 102 @Column(name = "CHUNK_DATA", nullable = true, length = Integer.MAX_VALUE - 1) 103 private String mySerializedData; 104 105 @Column(name = "CHUNK_DATA_VC", nullable = true, length = Length.LONG32) 106 private String mySerializedDataVc; 107 108 @Column(name = "STAT", length = STATUS_MAX_LENGTH, nullable = false) 109 @Enumerated(EnumType.STRING) 110 private WorkChunkStatusEnum myStatus; 111 112 @ManyToOne(fetch = FetchType.LAZY) 113 @JoinColumn( 114 name = "INSTANCE_ID", 115 insertable = false, 116 updatable = false, 117 foreignKey = @ForeignKey(name = "FK_BT2WC_INSTANCE")) 118 private Batch2JobInstanceEntity myInstance; 119 120 @Column(name = "INSTANCE_ID", length = ID_MAX_LENGTH, nullable = false) 121 private String myInstanceId; 122 123 @Column(name = "ERROR_MSG", length = ERROR_MSG_MAX_LENGTH, nullable = true) 124 private String myErrorMessage; 125 126 @Column(name = "ERROR_COUNT", nullable = false) 127 private int myErrorCount; 128 129 @Column(name = "WARNING_MSG", length = WARNING_MSG_MAX_LENGTH, nullable = true) 130 private String myWarningMessage; 131 132 /** 133 * The next time the work chunk can attempt to rerun its work step. 134 */ 135 @Column(name = "NEXT_POLL_TIME", nullable = true) 136 @Temporal(TemporalType.TIMESTAMP) 137 private Date myNextPollTime; 138 139 /** 140 * The number of times the work chunk has had its state set back to POLL_WAITING. 141 * <p> 142 * TODO: Note that this column was added in 7.2.0, so it is nullable in order to 143 * account for existing rows that were added before the column was added. In 144 * the future we should make this non-null. 145 */ 146 @Column(name = "POLL_ATTEMPTS", nullable = true) 147 private Integer myPollAttempts; 148 149 /** 150 * Default constructor for Hibernate. 151 */ 152 public Batch2WorkChunkEntity() { 153 myPollAttempts = 0; 154 } 155 156 /** 157 * Projection constructor for no-data path. 158 */ 159 public Batch2WorkChunkEntity( 160 String theId, 161 int theSequence, 162 String theJobDefinitionId, 163 int theJobDefinitionVersion, 164 String theInstanceId, 165 String theTargetStepId, 166 WorkChunkStatusEnum theStatus, 167 Date theCreateTime, 168 Date theStartTime, 169 Date theUpdateTime, 170 Date theEndTime, 171 String theErrorMessage, 172 int theErrorCount, 173 Integer theRecordsProcessed, 174 String theWarningMessage, 175 Date theNextPollTime, 176 Integer thePollAttempts) { 177 myId = theId; 178 mySequence = theSequence; 179 myJobDefinitionId = theJobDefinitionId; 180 myJobDefinitionVersion = theJobDefinitionVersion; 181 myInstanceId = theInstanceId; 182 myTargetStepId = theTargetStepId; 183 myStatus = theStatus; 184 myCreateTime = theCreateTime; 185 myStartTime = theStartTime; 186 myUpdateTime = theUpdateTime; 187 myEndTime = theEndTime; 188 myErrorMessage = theErrorMessage; 189 myErrorCount = theErrorCount; 190 myRecordsProcessed = theRecordsProcessed; 191 myWarningMessage = theWarningMessage; 192 myNextPollTime = theNextPollTime; 193 myPollAttempts = thePollAttempts != null ? thePollAttempts : 0; 194 } 195 196 public static Batch2WorkChunkEntity fromWorkChunk(WorkChunk theWorkChunk) { 197 Batch2WorkChunkEntity entity = new Batch2WorkChunkEntity( 198 theWorkChunk.getId(), 199 theWorkChunk.getSequence(), 200 theWorkChunk.getJobDefinitionId(), 201 theWorkChunk.getJobDefinitionVersion(), 202 theWorkChunk.getInstanceId(), 203 theWorkChunk.getTargetStepId(), 204 theWorkChunk.getStatus(), 205 theWorkChunk.getCreateTime(), 206 theWorkChunk.getStartTime(), 207 theWorkChunk.getUpdateTime(), 208 theWorkChunk.getEndTime(), 209 theWorkChunk.getErrorMessage(), 210 theWorkChunk.getErrorCount(), 211 theWorkChunk.getRecordsProcessed(), 212 theWorkChunk.getWarningMessage(), 213 theWorkChunk.getNextPollTime(), 214 theWorkChunk.getPollAttempts()); 215 entity.setSerializedData(theWorkChunk.getData()); 216 217 return entity; 218 } 219 220 public int getErrorCount() { 221 return myErrorCount; 222 } 223 224 public void setErrorCount(int theErrorCount) { 225 myErrorCount = theErrorCount; 226 } 227 228 public String getErrorMessage() { 229 return myErrorMessage; 230 } 231 232 public void setErrorMessage(String theErrorMessage) { 233 myErrorMessage = left(theErrorMessage, ERROR_MSG_MAX_LENGTH); 234 } 235 236 public String getWarningMessage() { 237 return myWarningMessage; 238 } 239 240 public void setWarningMessage(String theWarningMessage) { 241 myWarningMessage = theWarningMessage; 242 } 243 244 public int getSequence() { 245 return mySequence; 246 } 247 248 public void setSequence(int theSequence) { 249 mySequence = theSequence; 250 } 251 252 public Date getCreateTime() { 253 return myCreateTime; 254 } 255 256 public void setCreateTime(Date theCreateTime) { 257 myCreateTime = theCreateTime; 258 } 259 260 public Date getStartTime() { 261 return myStartTime; 262 } 263 264 public void setStartTime(Date theStartTime) { 265 myStartTime = theStartTime; 266 } 267 268 public Date getEndTime() { 269 return myEndTime; 270 } 271 272 public void setEndTime(Date theEndTime) { 273 myEndTime = theEndTime; 274 } 275 276 public Date getUpdateTime() { 277 return myUpdateTime; 278 } 279 280 public Integer getRecordsProcessed() { 281 return myRecordsProcessed; 282 } 283 284 public void setRecordsProcessed(Integer theRecordsProcessed) { 285 myRecordsProcessed = theRecordsProcessed; 286 } 287 288 public Batch2JobInstanceEntity getInstance() { 289 return myInstance; 290 } 291 292 public void setInstance(Batch2JobInstanceEntity theInstance) { 293 myInstance = theInstance; 294 } 295 296 public String getJobDefinitionId() { 297 return myJobDefinitionId; 298 } 299 300 public void setJobDefinitionId(String theJobDefinitionId) { 301 myJobDefinitionId = theJobDefinitionId; 302 } 303 304 public int getJobDefinitionVersion() { 305 return myJobDefinitionVersion; 306 } 307 308 public void setJobDefinitionVersion(int theJobDefinitionVersion) { 309 myJobDefinitionVersion = theJobDefinitionVersion; 310 } 311 312 public String getTargetStepId() { 313 return myTargetStepId; 314 } 315 316 public void setTargetStepId(String theTargetStepId) { 317 myTargetStepId = theTargetStepId; 318 } 319 320 public String getSerializedData() { 321 return mySerializedDataVc != null ? mySerializedDataVc : mySerializedData; 322 } 323 324 public void setSerializedData(String theSerializedData) { 325 mySerializedData = null; 326 mySerializedDataVc = theSerializedData; 327 } 328 329 public WorkChunkStatusEnum getStatus() { 330 return myStatus; 331 } 332 333 public void setStatus(WorkChunkStatusEnum theStatus) { 334 myStatus = theStatus; 335 } 336 337 public String getId() { 338 return myId; 339 } 340 341 public void setId(String theId) { 342 myId = theId; 343 } 344 345 public String getInstanceId() { 346 return myInstanceId; 347 } 348 349 public void setInstanceId(String theInstanceId) { 350 myInstanceId = theInstanceId; 351 } 352 353 public Date getNextPollTime() { 354 return myNextPollTime; 355 } 356 357 public void setNextPollTime(Date theNextPollTime) { 358 myNextPollTime = theNextPollTime; 359 } 360 361 public Integer getPollAttempts() { 362 if (myPollAttempts == null) { 363 return 0; 364 } 365 return myPollAttempts; 366 } 367 368 public void setPollAttempts(int thePollAttempts) { 369 myPollAttempts = thePollAttempts; 370 } 371 372 @Override 373 public String toString() { 374 return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) 375 .append("id", myId) 376 .append("instanceId", myInstanceId) 377 .append("sequence", mySequence) 378 .append("errorCount", myErrorCount) 379 .append("jobDefinitionId", myJobDefinitionId) 380 .append("jobDefinitionVersion", myJobDefinitionVersion) 381 .append("createTime", myCreateTime) 382 .append("startTime", myStartTime) 383 .append("endTime", myEndTime) 384 .append("updateTime", myUpdateTime) 385 .append("recordsProcessed", myRecordsProcessed) 386 .append("targetStepId", myTargetStepId) 387 .append("serializedData", getSerializedData()) 388 .append("status", myStatus) 389 .append("errorMessage", myErrorMessage) 390 .append("warningMessage", myWarningMessage) 391 .append("nextPollTime", myNextPollTime) 392 .append("pollAttempts", myPollAttempts) 393 .toString(); 394 } 395}