Я хотел бы использовать закрытие Groovy для обработки данных, поступающих из таблицы SQL. Для каждой новой строки вычисление будет зависеть от того, что было вычислено ранее. Тем не менее, новые строки могут появиться на последующих запусках приложения, поэтому я хотел бы иметь возможность перезагрузить закрытие, инициализированное промежуточным состоянием, которое оно имело, когда последнее завершение было выполнено в предыдущем запуске приложения.Сохранение состояния закрытия в Groovy
Например, укупорочное намереваясь вычислить скользящее среднее за 3 строк будет осуществляться следующим образом:
def prev2Val = null
def prevVal = null
def prevId = null
Closure c = { row ->
println([ prev2Val, prevVal, prevId])
def latestVal = row['val']
if (prev2Val != null) {
def movMean = (prev2Val + prevVal + latestVal)/3
sql.execute("INSERT INTO output(id, val) VALUES (?, ?)", [prevId, movMean])
}
sql.execute("UPDATE test_data SET processed=TRUE WHERE id=?", [row['id']])
prev2Val = prevVal
prevVal = latestVal
prevId = row['id']
}
test_data
имеет 3 колонки: id
(автоинкрементным первичный ключ), value
и processed
. Скользящее среднее рассчитывается на основе двух предыдущих значений и вводится в таблицу output
против id
предыдущей строки. Обработанные строки помечены processed=TRUE
.
Если все данные были доступны с самого начала, это можно было бы назвать так:
sql.eachRow("SELECT id, val FROM test_data WHERE processed=FALSE ORDER BY id", c)
Проблема возникает, когда новые строки становятся доступными после того, как заявка уже бежать. Это можно моделировать, обрабатывая небольшую порцию каждый раз (например, используя LIMIT 5
в предыдущем заявлении).
Я хотел бы иметь возможность сбросить полное состояние замыкания в конце выполнения eachRow
(например, сохранение промежуточных данных где-нибудь в базе данных) и повторная инициализация его при повторном запуске всего приложения (путем загрузки этой промежуточной переменной из базы данных).
В этом конкретном примере, я могу сделать это вручную, путем сохранения значений prev2Val
, prevVal
и prevId
, но я ищу общее решение, где точно зная, какие переменные используются не было бы необходимости.
Возможно, что-то вроде c.getState()
, который будет возвращать [ prev2Val: 1, prevVal: 2, prevId: 6]
(к примеру), и где я мог бы использовать c.setState ([ prev2Val: 1, prevVal: 2, prevId: 6]
) в следующий раз, когда приложение выполняется (если есть состояние сохраняется).
Я также должен исключить sql
из списка. Кажется, это можно сделать, используя [email protected]=null
.
Я понимаю, что это вряд ли будет работать в общем случае, но я ищу что-то достаточно общее для большинства случаев. Я пробовал dehydrate
, сериализую и rehydrate
закрытие, как описано в this Groovy issue, но я не уверен, как сохранить и сохранить все поля @
за одну операцию.
Возможно ли это? Есть ли лучший способ запомнить состояние между выполнением, если предположить, что список переменных, используемых закрытием, не обязательно известен заранее?
Точно такие проблемы, которые я ожидал. Кроме того, закрытие не имеет привязки, если я явно не даю ему делегата заранее (следуя некоторым из [этих предложений] (http://stackoverflow.com/a/3237296/372643)). Во всяком случае, это работает для того, что я пытаюсь сделать. Приветствия. – Bruno