Repository: corona-warn-app/cwa-server
File: common/persistence/src/main/java/app/coronawarn/server/common/persistence/service/TraceTimeIntervalWarningService.java (Java)

Code before:
    this.fakeCheckinsGenerator = fakeCheckinsGenerator;
  }

  /**
   * Store the given checkin data as {@link TraceTimeIntervalWarning} entities. Returns the number
   * of inserted entities, which is useful for the case where there might be conflicts with the
   * table constraints during the db save operations.
   */
  @Transactional
  public int saveCheckins(List<CheckIn> checkins) {
    return saveCheckins(checkins, this::hashLocationId);
  }

  private int saveCheckins(List<CheckIn> checkins, Function<ByteString, byte[]> idHashGenerator) {
    int numberOfInsertedTraceWarnings = 0;

    for (CheckIn checkin : checkins) {
      byte[] hashId = idHashGenerator.apply(checkin.getLocationId());
      if (hashId != NO_HASH) {
        boolean traceWarningInsertedSuccessfully = traceTimeIntervalWarningRepo
            .saveDoNothingOnConflict(hashId,
                checkin.getStartIntervalNumber(),
                checkin.getEndIntervalNumber() - checkin.getStartIntervalNumber(),
                checkin.getTransmissionRiskLevel(),
                CheckinsDateSpecification.HOUR_SINCE_EPOCH_DERIVATION
                    .apply(Instant.now().getEpochSecond()));

        if (traceWarningInsertedSuccessfully) {
          numberOfInsertedTraceWarnings++;
        }
      }
    }

    int conflictingTraceWarnings = checkins.size() - numberOfInsertedTraceWarnings;
    if (conflictingTraceWarnings > 0) {
      logger.warn(
          "{} out of {} TraceTimeIntervalWarnings conflicted with existing "
          + "database entries or had errors while storing "
              + "and were ignored.",
          conflictingTraceWarnings, checkins.size());
    }

    return numberOfInsertedTraceWarnings;
  }

  /**
   * For each checkin in the given list, generate other fake checkin data based on the passed in
   * number and store everything as {@link TraceTimeIntervalWarning} entities. Returns the number of
   * inserted entities which is useful for the case where there might be conflicts with the table
   * constraints during the db save operations.
   */

Review comment (suggestion):
Can lead to time zone inconsistencies during testing. Prefer to use [TimeUtils](https://github.com/corona-warn-app/cwa-server/blob/f06b7d2b0091f9fb9f6342238e31854597798fa2/services/distribution/src/main/java/app/coronawarn/server/services/distribution/assembly/structure/util/TimeUtils.java#L23) (which should probably be moved to "common" I guess...).

Code after:
      FakeCheckinsGenerator fakeCheckinsGenerator) throws NoSuchAlgorithmException {
    this.traceTimeIntervalWarningRepo = traceTimeIntervalWarningRepo;
    this.fakeCheckinsGenerator = fakeCheckinsGenerator;
    this.hashAlgorithm = MessageDigest.getInstance("SHA-256");
  }

  /**
   * Store the given checkin data as {@link TraceTimeIntervalWarning} entities. Returns the number
   * of inserted entities, which is useful for the case where there might be conflicts with the
   * table constraints during the db save operations.
   */
  @Transactional
  public int saveCheckins(List<CheckIn> checkins) {
    return saveCheckins(checkins, this::hashLocationId);
  }

  private int saveCheckins(List<CheckIn> checkins, Function<ByteString, byte[]> idHashGenerator) {
    int numberOfInsertedTraceWarnings = 0;

    for (CheckIn checkin : checkins) {
      byte[] hashId = idHashGenerator.apply(checkin.getLocationId());
      boolean traceWarningInsertedSuccessfully = traceTimeIntervalWarningRepo
          .saveDoNothingOnConflict(hashId, checkin.getStartIntervalNumber(),
              checkin.getEndIntervalNumber() - checkin.getStartIntervalNumber(),
              checkin.getTransmissionRiskLevel(),
              CheckinsDateSpecification.HOUR_SINCE_EPOCH_DERIVATION
                  .apply(Instant.now().getEpochSecond()));

      if (traceWarningInsertedSuccessfully) {
        numberOfInsertedTraceWarnings++;
      }
    }

    int conflictingTraceWarnings = checkins.size() - numberOfInsertedTraceWarnings;
    if (conflictingTraceWarnings > 0) {
      logger.warn(
          "{} out of {} TraceTimeIntervalWarnings conflicted with existing "
          + "database entries or had errors while storing "
              + "and were ignored.",
          conflictingTraceWarnings, checkins.size());
    }

    return numberOfInsertedTraceWarnings;
  }

  /**
   * For each checkin in the given list, generate other fake checkin data based on the passed in
   * number and store everything as {@link TraceTimeIntervalWarning} entities. Returns the number of
   * inserted entities which is useful for the case where there might be conflicts with the table
   * constraints during the db save operations.
   */