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