static RunState entityToRunState(Entity entity, WorkflowInstance instance)
throws IOException {
final long counter = entity.getLong(PROPERTY_COUNTER);
final State state = State.valueOf(entity.getString(PROPERTY_STATE));
final long timestamp = entity.getLong(PROPERTY_STATE_TIMESTAMP);
final StateData data = StateData.newBuilder()
.tries((int) entity.getLong(PROPERTY_STATE_TRIES))
.consecutiveFailures((int) entity.getLong(PROPERTY_STATE_CONSECUTIVE_FAILURES))
.retryCost(entity.getDouble(PROPERTY_STATE_RETRY_COST))
.trigger(DatastoreStorage.<String>readOpt(entity, PROPERTY_STATE_TRIGGER_TYPE).map(type ->
TriggerUtil.trigger(type, entity.getString(PROPERTY_STATE_TRIGGER_ID))))
.messages(OBJECT_MAPPER.<List<Message>>readValue(entity.getString(PROPERTY_STATE_MESSAGES),
new TypeReference<List<Message>>() { }))
.retryDelayMillis(readOpt(entity, PROPERTY_STATE_RETRY_DELAY_MILLIS))
.lastExit(DatastoreStorage.<Long>readOpt(entity, PROPERTY_STATE_LAST_EXIT).map(Long::intValue))
.executionId(readOpt(entity, PROPERTY_STATE_EXECUTION_ID))
.executionDescription(readOptJson(entity, PROPERTY_STATE_EXECUTION_DESCRIPTION,
ExecutionDescription.class))
.resourceIds(readOptJson(entity, PROPERTY_STATE_RESOURCE_IDS,
new TypeReference<Set<String>>() { }))
.triggerParameters(readOptJson(entity, PROPERTY_STATE_TRIGGER_PARAMETERS, TriggerParameters.class))
.build();
return RunState.create(instance, state, data, Instant.ofEpochMilli(timestamp), counter);
}