@Override
 public void update(
     final OwnerFullName ownerFullName,
     final String instanceId,
     final Callback<AutoScalingInstance> instanceUpdateCallback)
     throws AutoScalingMetadataException {
   persistenceSupport.updateByExample(
       persistenceSupport.exampleWithName(ownerFullName, instanceId),
       ownerFullName,
       instanceId,
       instanceUpdateCallback);
 }
  @Override
  public void markExpiredPendingUnhealthy(
      final AutoScalingGroupMetadata group, final Collection<String> instanceIds, final long maxAge)
      throws AutoScalingMetadataException {
    final AutoScalingInstance example = exampleForGroup(group);
    example.setHealthStatus(HealthStatus.Healthy);

    final List<AutoScalingInstance> instancesToMark =
        instanceIds.isEmpty()
            ? Collections.<AutoScalingInstance>emptyList()
            : persistenceSupport.listByExample(
                example,
                LifecycleState.Pending,
                Property.forName("displayName").in(instanceIds),
                Collections.<String, String>emptyMap(),
                Functions.<AutoScalingInstance>identity());

    for (final AutoScalingInstance instance : instancesToMark) {
      try {
        persistenceSupport.updateByExample(
            AutoScalingInstance.withUuid(instance.getNaturalId()),
            group.getOwner(),
            instance.getInstanceId(),
            new Callback<AutoScalingInstance>() {
              @Override
              public void fire(final AutoScalingInstance instance) {
                if (instance.getCreationTimestamp().getTime() < maxAge) {
                  logger.info("Marking pending instance unhealthy: " + instance.getInstanceId());
                  instance.setHealthStatus(HealthStatus.Unhealthy);
                } else {
                  logger.debug(
                      "Not marking pending instance unhealthy (within timeout): "
                          + instance.getInstanceId());
                }
              }
            });
      } catch (final AutoScalingMetadataNotFoundException e) {
        // removed, no need to mark unhealthy
      }
    }
  }
  @Override
  public void markMissingInstancesUnhealthy(
      final AutoScalingGroupMetadata group, final Collection<String> instanceIds)
      throws AutoScalingMetadataException {
    final AutoScalingInstance example = exampleForGroup(group);
    example.setHealthStatus(HealthStatus.Healthy);

    final List<AutoScalingInstance> instancesToMark =
        persistenceSupport.listByExample(
            example,
            LifecycleState.InService,
            instanceIds.isEmpty()
                ? Restrictions.conjunction()
                : Restrictions.not(Property.forName("displayName").in(instanceIds)),
            Collections.<String, String>emptyMap(),
            Functions.<AutoScalingInstance>identity());

    for (final AutoScalingInstance instance : instancesToMark) {
      try {
        persistenceSupport.updateByExample(
            AutoScalingInstance.withUuid(instance.getNaturalId()),
            group.getOwner(),
            instance.getInstanceId(),
            new Callback<AutoScalingInstance>() {
              @Override
              public void fire(final AutoScalingInstance instance) {
                if (instance.healthStatusGracePeriodExpired()) {
                  logger.info("Marking instance unhealthy: " + instance.getInstanceId());
                  instance.setHealthStatus(HealthStatus.Unhealthy);
                } else {
                  logger.debug(
                      "Instance not healthy but within grace period: " + instance.getInstanceId());
                }
              }
            });
      } catch (final AutoScalingMetadataNotFoundException e) {
        // removed, no need to mark unhealthy
      }
    }
  }