| 5306 | } |
| 5307 | |
| 5308 | int RedisGearsPy_PyCallbackForEach(ExecutionCtx* rctx, Record *record, void* arg){ |
| 5309 | // Call Python/C API functions... |
| 5310 | RedisModule_Assert(RedisGears_RecordGetType(record) == pythonRecordType); |
| 5311 | |
| 5312 | PythonSessionCtx* sctx = RedisGears_GetFlatExecutionPrivateData(rctx); |
| 5313 | RedisModule_Assert(sctx); |
| 5314 | |
| 5315 | PythonExecutionCtx pectx = PythonExecutionCtx_New(sctx, rctx); |
| 5316 | RedisGearsPy_Lock(&pectx); |
| 5317 | |
| 5318 | PyObject* pArgs = PyTuple_New(1); |
| 5319 | PyObject* callback = arg; |
| 5320 | PyObject* obj = PyObjRecordGet(record); |
| 5321 | Py_INCREF(obj); |
| 5322 | PyTuple_SetItem(pArgs, 0, obj); |
| 5323 | if (RedisGears_ProfileEnabled()) { |
| 5324 | // start profiling |
| 5325 | PyObject_CallFunction(profileStartFunction, "O", sctx->profiler); |
| 5326 | } |
| 5327 | PyObject* ret = PyObject_CallObject(callback, pArgs); |
| 5328 | if (RedisGears_ProfileEnabled()) { |
| 5329 | // stop profiling |
| 5330 | PyObject_CallFunction(profileStopFunction, "O", sctx->profiler); |
| 5331 | } |
| 5332 | GearsPyDecRef(pArgs); |
| 5333 | |
| 5334 | PythonThreadCtx* ptctx = GetPythonThreadCtx(); |
| 5335 | |
| 5336 | if(ret && PyCoro_CheckExact(ret)){ |
| 5337 | // object is a coroutine, we need to hold and pass it to the event loop. |
| 5338 | ret = RedisGearsPy_PyCallbackHandleCoroutine(rctx, ret, ptctx); |
| 5339 | } |
| 5340 | |
| 5341 | if(ptctx->pyfutureCreated && ret == ptctx->pyfutureCreated){ |
| 5342 | PyFuture* future = (PyFuture*)ret; |
| 5343 | future->continueType = ContinueType_Foreach; |
| 5344 | // no need to free the original record because the async record took the ownership on it |
| 5345 | |
| 5346 | // we need to free the future as we do not return it |
| 5347 | GearsPyDecRef(ret); |
| 5348 | RedisGearsPy_Unlock(&pectx); |
| 5349 | return RedisGears_StepHold; |
| 5350 | } |
| 5351 | |
| 5352 | if(ptctx->pyfutureCreated){ |
| 5353 | /** |
| 5354 | * Async record created but not returned lets disscard it |
| 5355 | */ |
| 5356 | PyFuture* f = (PyFuture*)ptctx->pyfutureCreated; |
| 5357 | RedisGears_AsyncRecordContinue(f->asyncRecord, RedisGears_GetDummyRecord()); |
| 5358 | f->asyncRecord = NULL; |
| 5359 | } |
| 5360 | |
| 5361 | if(!ret){ |
| 5362 | fetchPyError(rctx); |
| 5363 | |
| 5364 | RedisGearsPy_Unlock(&pectx); |
| 5365 | return RedisGears_StepSuccess; |
nothing calls this directly
no test coverage detected