@Override
  public List<Execution> lockAndFetchGeneric(Instant now, int limit) {
    return jdbcRunner.inTransaction(
        txRunner -> {
          final UnresolvedFilter unresolvedFilter =
              new UnresolvedFilter(taskResolver.getUnresolved());
          String selectForUpdateQuery =
              jdbcCustomization.createGenericSelectForUpdateQuery(
                  tableName, limit, unresolvedFilter.andCondition(), orderByPriority);
          List<Execution> candidates =
              getExecutions(txRunner, selectForUpdateQuery, now, limit, unresolvedFilter);

          if (candidates.isEmpty()) {
            return new ArrayList<>();
          }

          String pickedBy = truncate(schedulerSchedulerName.getName(), 50);
          Instant lastHeartbeat = clock.now();

          // no need to use 'version' here since we have locked the row
          final int[] updated =
              txRunner.executeBatch(
                  "update "
                      + tableName
                      + " set picked = ?, picked_by = ?, last_heartbeat = ?, version = version + 1 "
                      + " where task_name = ? "
                      + " and task_instance = ? ",
                  candidates,
                  (value, ps) -> {
                    ps.setBoolean(1, true);
                    ps.setString(2, pickedBy);
                    jdbcCustomization.setInstant(ps, 3, lastHeartbeat);
                    ps.setString(4, value.taskInstance.getTaskName());
                    ps.setString(5, value.taskInstance.getId());
                  });
          int totalUpdated = IntStream.of(updated).sum();
          // FIXLATER: should we update picked executions with the updates to these fields?

          if (totalUpdated != candidates.size()) {
            LOG.error(
                "Did not update same amount of executions that were locked in the transaction. This might mean some assumption is wrong here, or that transaction is not working. Needs to be investigated. Updated: {}, expected: {}",
                totalUpdated,
                candidates.size());

            List<Execution> locked = new ArrayList<>();
            List<Execution> noLock = new ArrayList<>();
            for (int i = 0; i < candidates.size(); i++) {
              if (updated[i] > 1) {
                LOG.error("Should never happen, indicates a bug.");
              }
              if (updated[i] > 0) {
                locked.add(candidates.get(i));
              } else {
                noLock.add(candidates.get(i));
              }
            }
            String instancesNotLocked =
                noLock.stream().map(e -> e.taskInstance.toString()).collect(joining(","));
            LOG.warn(
                "Returning picked executions for processing. Did not manage to pick executions: {}",
                instancesNotLocked);

            return updateToPicked(locked, pickedBy, lastHeartbeat);
          } else {
            return updateToPicked(candidates, pickedBy, lastHeartbeat);
          }
        });
  }
Instead of doing delete+insert, we allow updating an existing execution will all new fields

@return the execution-time of the new execution
db-scheduler/src/main/java/com/github/kagkarlsson/scheduler/jdbc/JdbcTaskRepository.java