Grails обещает потерю данных - по-видимому, не дожидаясь завершения друг друга

Следующие случайные вызовы getParentCustomers или getAccountManagersпервый. Когда он это делает, он работает нормально. Однако то, что называется вторым, проходитnullвнутрь. Ни один из этих методов никоим образом не изменяет входящие значения. Я предполагаю, что есть что-то в контексте, из которого они вызываются из исходного указателя наresponse.salesChannels теряется между задачами.

Map response = [
    salesChannels:   null,
    accountManagers: null,
    parentCustomers: null,
    isrs:            null,
    operatingUnits:  null,
    businessUnits:   null
]

def t1 = task {
    response.salesChannels = salesChannelApiService.get(salesChannel)

    def t1a = task {
        response.parentCustomers = salesChannelTransformService.getParentCustomers(response.salesChannels)
    }
    def t1b = task {
        response.accountManagers = salesChannelTransformService.getAccountManagers(response.salesChannels)
    }

    waitAll([t1a, t1b])
}

def t2 = task {
    //... other stuff
}

def t3 = task {
    //... other stuff
}

waitAll([t1, t2, t3])

return response

Я даже пытался модифицировать внутреннее устройство, чтобы использовать onComplete вместо.

...
onComplete([task {
    return salesChannelApiService.get(salesChannel)
}], { salesChannels ->
    response.salesChannels = salesChannels

    def t1a = task {
        response.parentCustomers = salesChannelTransformService.getParentCustomers(salesChannels)
    }
    def t1b = task {
        response.accountManagers = salesChannelTransformService.getAccountManagers(salesChannels)
    }

    waitAll([t1a, t1b])
})
...

Однако я все равно получаю тот же результат.

ПРИМЕЧАНИЕ: Это тоже случайно. Иногда это работает нормально - передача одного и того же списка обоим методам. Но когда он ломается, всегда тот, кто срабатывает вторым.

Есть мысли по этому поводу?

2 ответа

Решение

Так что я думаю, что в редких случаях многопоточность немного срабатывала, поэтому я удалил отдельные потоки между getParentCustomers и getAccountManager, поскольку они все равно не делают внешних вызовов.

Я думаю, что одновременное использование response.salesChannels по потокам мешало распределению памяти response.salesChannels - и оно случайным образом генерировало исключение нулевого указателя каждые несколько сотен вызовов.

Это кажется более надежным.

def t1 = createPromise()

task {
    response.salesChannels = salesChannelApiService.get(salesChannel)

    def t1a = createPromise()

    task {
        response.parentCustomers = salesChannelTransformService.getParentCustomers(response.salesChannels)
        response.accountManagers = salesChannelTransformService.getAccountManagers(response.salesChannels)
        t1a.accept()
    }

    onComplete([t1a], { a -> t1.accept() })
}

Приведенное ниже решение пока работает. Однако я понятия не имею, почему ни один из вышеперечисленных блоков кода этого не делает.

Какие-нибудь мысли?

def t1 = createPromise()

task {
    response.salesChannels = salesChannelApiService.get(salesChannel)

    def t1a = createPromise()
    def t1b = createPromise()

    task {
        response.parentCustomers = salesChannelTransformService.getParentCustomers(response.salesChannels)
        t1a.accept()
    }
    task {
        response.accountManagers = salesChannelTransformService.getAccountManagers(response.salesChannels)
        t1b.accept()
    }

    onComplete([t1a, t1b], { a, b -> t1.accept() })
}
Другие вопросы по тегам