Выполнение метода до определенного условия
Я пишу тестовый spock проект, который работает c REST приложением, который в свою очередь работает с БД.
Проблематика заключается в том при дергании рест запросов, в БД не успевает записываться инфа и приходится изобретать такие вот штуки.
Как можно реализовать метод, который будет выполняться пока не удовлетворит некоторое условие. Всё что я смог реализовать это:
class Helper {
static def waitForResponse(Closure closure, int size = 1) {
int count = 0
BaseResponse response = closure.call()
while (response.body.size != size && count <= 15) {
response = closure.call()
log.info("try to get response, count: ${count}, response: ${response}")
if (response.body.size != size) {
sleep 200
}
count++
}
checkSuccess(response)
return response.body
}
}
}
Это удовлетворяет только тем запросам, формат которых - лист, да и то работает не совсем так, как мне нужно. В ответе может быть List<Мар>
Нужно что то типо:
class Waiter {
BaseResponse response = waitForResponse({someMetod(someParam)}, it.someField == "someValue")
// либо
BaseResponse response = waitForResponse({someMetod(someParam)}, {it.someField == "someValue"})
}
т.е. someMetod(someParam) будет выполняться с промежутками в 200мс до тех пор пока не удовлетворит условию либо закончатся попытки
Быть может я вообще не в ту степь копнул и есть что то более изящное?
P.S. я всего лишь тестер, поэтому предложения про то что нужно оптимизировать работу с БД мне вряд ли помогут:(
Ответы (1 шт):
Передавайте еще одно Closure, в котором задавайте условие:
static def waitForResponse(Closure action, Closure condition) {
int count = 0
BaseResponse response = action()
while (!condition(response) && count < MAX_TRIES) {
sleep 200
count++;
}
if (count == MAX_TRIES) {
# не удалось, бросаем исключение с подробностями
}
return response.body
}
И тогда можно вызывать так:
def body = waitForResponse(
{someMetod(someParam)},
{it.body.size > 100}
)
Или создать вспомогательные функции, чтоб облегчить проверки и сделать их более высокоуровнемыми:
def body = waitForResponse(
{someMetod(someParam)},
{'some-value' in someParseFunction(it)}
)
someParseFunction - это функция, которая принимает BaseResponse и из него достает, то что вам нужно. Таких функций можно сделать сколько нужно для разных сценариев.
Еще я люблю делать DLS, чтоб можно было писать так:
def body = execute { someMethod(someParam)} andWait {'some-value' in parseSome(it)}
Для этого сделайте вспомогательный метод:
def execute(Closure action) {
return ['andWait': {condition -> waitForResponse(action, condition) }]
}