diff options
author | Jonathan Aillet <jonathan.aillet@iot.bzh> | 2019-02-26 11:44:26 +0100 |
---|---|---|
committer | Jonathan Aillet <jonathan.aillet@iot.bzh> | 2019-02-26 12:21:13 +0100 |
commit | 66bd15bab1f7e7c24be22aabde272755a0e05973 (patch) | |
tree | 6a7b7bc2a9fdae759e34d7c33ffebfbb2fd40f0b | |
parent | 0ed00b3d5af4181d2b65fcd12b43769c505ac567 (diff) |
Rework 'ActionExecOne' to prevent race issues
Use afb asynchronous calls to prevent issue when calling from
an event handler.
Also use subcall when in a request to pass on identity/events
of/to the original caller.
Change-Id: I821f92a2974415296cf19023b37f4639f7baaf5a
Signed-off-by: Jonathan Aillet <jonathan.aillet@iot.bzh>
-rw-r--r-- | ctl-lib/ctl-action.c | 89 |
1 files changed, 78 insertions, 11 deletions
diff --git a/ctl-lib/ctl-action.c b/ctl-lib/ctl-action.c index 735ade9..39bc2ae 100644 --- a/ctl-lib/ctl-action.c +++ b/ctl-lib/ctl-action.c @@ -51,13 +51,74 @@ void ActionExecUID(afb_req_t request, CtlConfigT *ctlConfig, const char *uid, js } } +void HandleApiCallActionResponseFromVerbCall(void *data, struct json_object *responseJ, const char *error, const char *info, afb_req_t request) { + CtlActionT *action = (CtlActionT *) data; + + if (!action) { + afb_req_fail_f(request, + "Action is null, won't be able to handle the response, error=%s info=%s response=%s", + error ? error : "NULL", + info ? info : "NULL", + responseJ ? json_object_get_string(responseJ) : "NULL"); + } + else if (error) { + afb_req_fail_f(request, + "subcall-fail", + "An error happened during verb call, error=%s info=%s uid=%s api=%s verb=%s args=%s response=%s", + error ? error : "NULL", + info ? info : "NULL", + action->uid, + action->exec.subcall.api, + action->exec.subcall.verb, + json_object_get_string(action->argsJ), + responseJ ? json_object_get_string(responseJ) : "NULL"); + } + else { + afb_req_success(request, responseJ ? json_object_get(responseJ) : NULL, info); + } +} + +void HandleApiCallActionResponseFromEvent(void *data, struct json_object *responseJ, const char *error, const char *info, afb_api_t apiHandle) { + CtlActionT *action = (CtlActionT *) data; + + if (!action) { + AFB_API_ERROR(apiHandle, + "Action is null, won't be able to handle the response, error=%s info=%s response=%s", + error ? error : "NULL", + info ? info : "NULL", + responseJ ? json_object_get_string(responseJ) : "NULL"); + } + else if (error) { + AFB_API_ERROR(apiHandle, + "An error happened during verb call, error=%s info=%s uid=%s api=%s verb=%s args=%s response=%s", + error ? error : "NULL", + info ? info : "NULL", + action->uid, + action->exec.subcall.api, + action->exec.subcall.verb, + json_object_get_string(action->argsJ), + responseJ ? json_object_get_string(responseJ) : "NULL"); + } + else { + AFB_API_DEBUG(apiHandle, + "Seems that everything went fine during verb call, error=%s info=%s uid=%s api=%s verb=%s args=%s response=%s", + error ? error : "NULL", + info ? info : "NULL", + action->uid, + action->exec.subcall.api, + action->exec.subcall.verb, + json_object_get_string(action->argsJ), + responseJ ? json_object_get_string(responseJ) : "NULL"); + } +} + int ActionExecOne(CtlSourceT *source, CtlActionT* action, json_object *queryJ) { int err = 0; switch (action->type) { case CTL_TYPE_API: { - json_object *returnJ, *toReturnJ, *extendedQueryJ = NULL; + json_object *extendedQueryJ = NULL; if (action->argsJ) { switch(json_object_get_type(queryJ)) { @@ -82,16 +143,22 @@ int ActionExecOne(CtlSourceT *source, CtlActionT* action, json_object *queryJ) { } /* AFB Subcall will release the json_object doing the json_object_put() call */ - err = afb_api_call_sync_legacy(action->api, action->exec.subcall.api, action->exec.subcall.verb, extendedQueryJ, &returnJ); - if(err && afb_req_is_valid(source->request)) - afb_req_fail_f(source->request, "subcall-fail", "ActionExecOne(AppFw) uid=%s api=%s verb=%s args=%s", source->uid, action->exec.subcall.api, action->exec.subcall.verb, json_object_get_string(action->argsJ)); - else if(err && ! afb_req_is_valid(source->request)) - AFB_API_ERROR(action->api, "ActionExecOne(AppFw) uid=%s api=%s verb=%s args=%s", source->uid, action->exec.subcall.api, action->exec.subcall.verb, json_object_get_string(action->argsJ)); - else if(afb_req_is_valid(source->request)) { - if(wrap_json_unpack(returnJ, "{s:o}", "response", &toReturnJ)) - AFB_API_ERROR(action->api, "ActionExecOne(Can't unpack response) uid=%s api=%s verb=%s args=%s", source->uid, action->exec.subcall.api, action->exec.subcall.verb, json_object_get_string(action->argsJ)); - else - afb_req_success(source->request, toReturnJ, NULL); + if (!source->request) { + afb_api_call(action->api, + action->exec.subcall.api, + action->exec.subcall.verb, + extendedQueryJ, + &HandleApiCallActionResponseFromEvent, + (void *) action); + } + else { + afb_req_subcall(source->request, + action->exec.subcall.api, + action->exec.subcall.verb, + extendedQueryJ, + afb_req_subcall_pass_events | afb_req_subcall_on_behalf, + &HandleApiCallActionResponseFromVerbCall, + (void *) action); } break; } |