-
Notifications
You must be signed in to change notification settings - Fork 48
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft implementation for watch support #28
Conversation
Hi @clearday4 Cloud you please review the design (especially for the |
Append the output of
|
kubernetes/watch/watch_util.h
Outdated
extern "C" { | ||
#endif | ||
|
||
void kubernets_watch_handler(void** pData, long* pDataLen, void (*event_hander)(const char*)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want to typedef
the event handler callback?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure. It's better. I will do it.
kubernetes/src/apiClient.c
Outdated
@@ -452,6 +456,10 @@ size_t writeDataCallback(void *buffer, size_t size, size_t nmemb, void *userp) { | |||
apiClient->dataReceived = (char *)realloc( apiClient->dataReceived, apiClient->dataReceivedLen + size_this_time + 1); | |||
memcpy(apiClient->dataReceived + apiClient->dataReceivedLen, buffer, size_this_time); | |||
apiClient->dataReceivedLen += size_this_time; | |||
((char*)apiClient->dataReceived)[apiClient->dataReceivedLen] = '\0'; // the space size of (apiClient->dataReceived) = dataReceivedLen + 1 | |||
if (apiClient->watch_func) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the way to do this without modifying the API client is to split the api invoke into two phases:
- Prepare the call
- Execute the call
That way the watch code can run #1 from the generated code, but then take over the call to get access to the raw stream.
It's not going to be maintainable long term to add this to the generated code as it is Kubernetes specific.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean splitting the generator function apiClient_invoke
to 2 parts ?
I do not find a way to "take over" the call to get access to the raw stream in kubernetes-client/c because curl_easy_perform
in apiClient_invoke
of watch
request will never return to caller. So I have to add the callback function into writeDataCallback
I think apiClient->watch_func
is not Kubernetes specific, other swagger client can use this function to support watch
,
watch/watch_util.{h,c}
will not be merged into openapi c generator because they are Kubernetes specific.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I'm suggesting breaking apiClient_invoke
into two parts:
// the whole invoke function, currently a single function is split into two parts.
apiClient_invoke(...) {
// Get the curl call ready
CURL *curlRequest = apiClient_prepare(...);
// actually make the curl call
apiClient_call(curlRequest);
}
// Can be called separately to just prepare but not execute a call.
CURL *apiClient_prepare(...) {}
// Probably not used by users.
apiClient_call(...) {}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that this separation will also be useful for port-forward/logs/etc which don't follow REST standards.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After splitting apiClient_invoke
to apiClient_prepare
and apiClient_call
, how can watch code take over to access to the raw stream ?
In current apiClient_invoke
res = curl_easy_perform(handle); // <--- curl_easy_perform will never return when "watch"
Do you mean watch code implements its writeDataCallback
, non-watch request uses generator's writeDataCallback
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree. how about using curl_multi_perform instead of using curl_easy_perform?
or set timeout like curl_easy_setopt(curl_, CURLOPT_TIMEOUT, timeout_)
currently curl_easy_perform will be blocked and never return.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@brendandburns
Suppose to use curl_multi_perform
in apiClient_call()
apiClient_call(...) {
...
do {
int numfds=0;
int res = curl_multi_wait(cm, NULL, 0, MAX_WAIT_MSECS, &numfds);
if(res != CURLM_OK) {
fprintf(stderr, "error: curl_multi_wait() returned %d\n", res);
return EXIT_FAILURE;
}
curl_multi_perform(cm, &still_running);
} while(still_running);
...
}
How does the watch code take over to access the raw stream ?
I will try to implement it now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree. how about using curl_multi_perform instead of using curl_easy_perform?
or set timeout like curl_easy_setopt(curl_, CURLOPT_TIMEOUT, timeout_)
currently curl_easy_perform will be blocked and never return.
Setting timeout is not a solution, after curl_easy_perform returns after timeout, the http connection will disconnect, watch events will never come, this is not right for the watch function.
Actually, curl_easy_perform blocking is accaptable here, because only one http request is working at this time. Although using curl_multi_perform
, we still need poll the request in a loop to get the watch event stream.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried to implement with curl_multi_*
, but I found it still need inject a function to apiClient_call
to access the raw stream, it will do more changes to api client.
For the watch
, because we issue only one request at one time, curl_multi_*
is not better than curl_easy_*
, the function curl_multi_wait
will return as long as there is data comming, so we need poll in a loop while(still_running)
So I suggest adopting my current solution:
- Only add a callback function pointer
data_callback_func
, it does small change to api client. - Other functions in watch/watch_util.{h,c} are committed to this repo (kubernetes-client/c)
If somebody has time to try a new solution with curl_multi_*
, we can update/change this part in the future.
cc @clearday4
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your suggestions look good to me. Let's do it!
Sure. |
e983e6e
to
c780f06
Compare
The callback function pointer |
Great, let's wait for that to merge and then we can get this PR merged too. |
c780f06
to
b2ba27c
Compare
b2ba27c
to
2a034b5
Compare
The code is updated after |
kubernetes/watch/watch_util.c
Outdated
void kubernets_watch_handler(void** pData, long* pDataLen, KUBE_WATCH_EVENT_HANDLER_FUNC event_hander) | ||
{ | ||
char* data = *(char**)pData; | ||
//printf("dataLen=%ld, strlen(data)=%ld\n", *pDataLen, strlen(data)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Delete this debug line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
One small nit and then it's ready to merge. |
2a034b5
to
be3b335
Compare
The code change is updated. |
/lgtm Cool! |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: brendandburns, ityuhui The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
Hi @brendandburns
This is a draft implementation for
watch
support. We can discuss the design here.This PR should not be merged because a part of code should be merged to generator repo https://github.com/OpenAPITools/openapi-generator/tree/master/modules/openapi-generator/src/main/resources/C-libcurl