-
Notifications
You must be signed in to change notification settings - Fork 1
Couchbase sdk brpc #3
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
base: master
Are you sure you want to change the base?
Conversation
| std::vector<bthread_t> bids; | ||
| for (int i = 0; i < 5; i++) { | ||
| bthread_t bid; | ||
| if (bthread_start_background(&bid, nullptr, threaded_example, ¶ms[i]) != |
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.
All the threads sharing a single cluster connection, all the threads are communicating to different buckets and performing CRUD operations.
| .adhoc(false); | ||
|
|
||
| // add positional parameters, you can also use named parameters and other | ||
| // query options that might be required. |
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.
query functions is overloaded with query_options so that end-user can have full control over the query. Here, we have used placeholders '$1' to test the working of the query_options.
src/brpc/couchbase.h
Outdated
| void CloseCouchbase(); | ||
|
|
||
| // query helper functions | ||
| std::pair<bool, std::vector<std::string>> Query(std::string statement); |
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.
cluster level query without any query_options. Simple string type queries, without any parameters.
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.
nice!
src/brpc/couchbase.h
Outdated
| // query helper functions | ||
| std::pair<bool, std::vector<std::string>> Query(std::string statement); | ||
| std::pair<bool, std::vector<std::string>> Query( | ||
| std::string statement, couchbase::query_options& q_opts); |
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.
cluster level query supporting query_options.
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.
Great this is here.
src/brpc/couchbase.h
Outdated
| std::string statement, couchbase::query_options& q_opts); | ||
| std::pair<bool, std::vector<std::string>> Query( | ||
| std::string statement, const std::string& bucket_name, | ||
| const std::string& scope = "_default"); |
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.
Scope level query. However in the query(statement) the collection is needed to specified i.e. inside the string itself.
src/brpc/couchbase.h
Outdated
| const std::string& scope = "_default"); | ||
| std::pair<bool, std::vector<std::string>> Query( | ||
| std::string statement, const std::string& bucket_name, | ||
| const std::string& scope, couchbase::query_options& q_opts); |
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.
Scope level query with query_options.
| << std::endl; | ||
| start = std::chrono::high_resolution_clock::now(); | ||
| std::string scoped_query = | ||
| "SELECT META().id, email FROM _default WHERE email LIKE '%@%'"; // Here |
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.
When running a scoped query then we need to give a collection in the FROM field. So the _default is needed inside the query.
ingenthr
left a comment
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.
This isn't a completely thorough review, but I think there are a couple places to examine:
- the initialization might need to consider a case where the connection won't work right now, but might work in the future. it's a bit binary at the moment, but a couchbase SDK instance isn't binary with respect to a 'connection'. I'm not sure the best way to reconcile this. Options might be to expose the ping/health_check or to put an optional waitUntilReady() in the initialization.
- I'm not sure about the error handling. If this aligns to how other projects in bRPC do it, then I think it's fine, but we might need to populate some other closed over or thread local variable with error details. Can you have a thought on this?
docs/en/couchbase_client.md
Outdated
|
|
||
| All operations return boolean values or pairs indicating success/failure: | ||
|
|
||
| - **CRUD operations**: Return `true` on success, `false` on failure |
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.
so, in the 'false' case, wouldn't a user need more information? If it's a CAS mismatch, I'll want to backoff/retry, but if it's an add() case and the doc is already there, no point in retrying.
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.
It's not boolean for all the CRUD operations. I will fix the doc. So, currently get is having a (bool and the error) as the return types so that client can know what error has actually come. Other operations(add,upsert,delete) are having the boolean return type which I should change as well following your later comment on the functions.
| @@ -0,0 +1,141 @@ | |||
| #include <bthread/bthread.h> | |||
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.
nice that we have a multithread sample!
| std::string key = "item::" + std::to_string(i); | ||
| std::string value = | ||
| R"({"name": "John Doe", "age": 31, "email": "[email protected]", "updated": true})"; | ||
| if (couchbase_client->CouchbaseAdd(key, value, bucket_name)) { |
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've not looked, but is this how the memcached handles errors @giriraj-singh-couchbase ? Is there an easy way to have this if() branching but still have details on failures? This one is related to my other feedback that we may need to know when the add() fails, is it because of something unusual (in which case I'll want to retry) or because of something that will never work (because some other client added the doc first)
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.
Oh, okay. I was printing the errors inside the functions itself and then simply returning false. Client might want to keep different logic based on the errors. So over here, the changes that I am thinking is to return the boolean true or false and the error with it too if any. and based upon the error, user can handle the client code logic.
src/brpc/couchbase.cpp
Outdated
| } | ||
|
|
||
| // Query operation at cluster level without query options | ||
| std::pair<bool, vector<std::string>> CouchbaseWrapper::Query( |
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.
Nice that you got queries in here!
src/brpc/couchbase.h
Outdated
| void CloseCouchbase(); | ||
|
|
||
| // query helper functions | ||
| std::pair<bool, std::vector<std::string>> Query(std::string statement); |
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.
nice!
| auto [connect_err, cluster] = | ||
| couchbase::cluster::connect(connection_string, options).get(); | ||
|
|
||
| if (connect_err) { |
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.
This is a section that probably requires some thought. Generally with the SDKs there is no such thing as a "connection failure". once initialized, it tries to connect forever. There are pros and cons to this, but it's where we are at the moment.
The code here reads as if it's looking for "a connection" which isn't really how it works. Maybe it should be a waituntilready(). I've added @DemetrisChr as a reviewer. He uses this SDK from multiple places, so he may be able to offer some advice.
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.
The C++ SDK behaves a little differently compared to other SDKs here. cluster::connect blocks until a memcached connection is established and a config is seen on that connection, up until the bootstrap timeout.
So a wait_until_ready is not as necessary, and why it it hasn't been added to the SDK yet (although wait_until_ready can also be used for checking the readiness of services, so we probably need to add it eventually).
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.
Hii @DemetrisChr, Can you tell me how is bootstrap timeout different from connect timeout? As far as I can think of bootstrap timeout means that the total time that can be taken for full initialisation and setup of clusters whereas connect timeout is for establishing of sockets only. Is it correct?
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, that's right.
The connect timeout is the timeout for establishing each individual memcached connection, used here. This includes connections made both during the initial bootstrap phase & any connections made later on (for example, connections made when opening buckets).
The bootstrap timeout (used here) covers the entire bootstrap phase, until a single connection is established successfully and a config received, which can involve a number of connection retries.
src/brpc/couchbase.h
Outdated
|
|
||
| // Upsert (insert/update) document | ||
| bool CouchbaseUpsert(const std::string& key, const std::string& value, | ||
| const std::string& bucket_name, |
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.
We may want to file an improvement issue for the future to use fully qualified buckets/scopes/collections. This offers protection from a delete-recreate of a collection being logically different. I think this is fine for now though.
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 do mention it as it may change the API in the future. I guess we could add something that isn't a string.
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.
Can you please tell me more about fully qualified buckets/scopes/collection? I was not able to get the context of what is the meaning of that. However, we can do operation at any level: buckets, scopes and collections all are supported in this very function.
src/brpc/couchbase.h
Outdated
| // query helper functions | ||
| std::pair<bool, std::vector<std::string>> Query(std::string statement); | ||
| std::pair<bool, std::vector<std::string>> Query( | ||
| std::string statement, couchbase::query_options& q_opts); |
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.
Great this is here.
…ased upon the errors the code can be driven, tested and did changes to work on linux.
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.
license-eye has totally checked 1730 files.
| Valid | Invalid | Ignored | Fixed |
|---|---|---|---|
| 865 | 4 | 861 | 0 |
Click to see the invalid file list
- example/couchbase_example/client.cpp
- example/couchbase_example/multi_threaded_client.cpp
- src/brpc/couchbase.cpp
- src/brpc/couchbase.h
| @@ -0,0 +1,394 @@ | |||
| #include <gflags/gflags.h> | |||
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.
| #include <gflags/gflags.h> | |
| /* | |
| * Licensed to the Apache Software Foundation (ASF) under one | |
| * or more contributor license agreements. See the NOTICE file | |
| * distributed with this work for additional information | |
| * regarding copyright ownership. The ASF licenses this file | |
| * to you under the Apache License, Version 2.0 (the | |
| * "License"); you may not use this file except in compliance | |
| * with the License. You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, | |
| * software distributed under the License is distributed on an | |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| * KIND, either express or implied. See the License for the | |
| * specific language governing permissions and limitations | |
| * under the License. | |
| */ | |
| #include <gflags/gflags.h> |
| @@ -0,0 +1,161 @@ | |||
| #include <bthread/bthread.h> | |||
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.
| #include <bthread/bthread.h> | |
| /* | |
| * Licensed to the Apache Software Foundation (ASF) under one | |
| * or more contributor license agreements. See the NOTICE file | |
| * distributed with this work for additional information | |
| * regarding copyright ownership. The ASF licenses this file | |
| * to you under the Apache License, Version 2.0 (the | |
| * "License"); you may not use this file except in compliance | |
| * with the License. You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, | |
| * software distributed under the License is distributed on an | |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| * KIND, either express or implied. See the License for the | |
| * specific language governing permissions and limitations | |
| * under the License. | |
| */ | |
| #include <bthread/bthread.h> |
| @@ -0,0 +1,299 @@ | |||
| #include "brpc/couchbase.h" | |||
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.
| #include "brpc/couchbase.h" | |
| /* | |
| * Licensed to the Apache Software Foundation (ASF) under one | |
| * or more contributor license agreements. See the NOTICE file | |
| * distributed with this work for additional information | |
| * regarding copyright ownership. The ASF licenses this file | |
| * to you under the Apache License, Version 2.0 (the | |
| * "License"); you may not use this file except in compliance | |
| * with the License. You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, | |
| * software distributed under the License is distributed on an | |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| * KIND, either express or implied. See the License for the | |
| * specific language governing permissions and limitations | |
| * under the License. | |
| */ | |
| #include "brpc/couchbase.h" |
| @@ -0,0 +1,82 @@ | |||
| #pragma once | |||
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.
| #pragma once | |
| /* | |
| * Licensed to the Apache Software Foundation (ASF) under one | |
| * or more contributor license agreements. See the NOTICE file | |
| * distributed with this work for additional information | |
| * regarding copyright ownership. The ASF licenses this file | |
| * to you under the Apache License, Version 2.0 (the | |
| * "License"); you may not use this file except in compliance | |
| * with the License. You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, | |
| * software distributed under the License is distributed on an | |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| * KIND, either express or implied. See the License for the | |
| * specific language governing permissions and limitations | |
| * under the License. | |
| */ | |
| #pragma once |
| } else { | ||
| //based on the returned error do actual error handling | ||
| if(add_response.err.ec() == couchbase::errc::key_value::document_exists){ | ||
| //handle the error |
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.
Much better-- it's great when these kinds of examples show at least rudimentary error handling.
| ``` | ||
|
|
||
| **Note**: If scope and collection are not specified, they default to `"_default"`. | ||
| **Note**: If scope and collection are not specified, they set to `"_default"`. |
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.
Kind of funny English here to my en_US eyes. Instead "are set" might be better.
| DEFINE_string(username, "selfdb", "Couchbase username"); | ||
| DEFINE_string(password, "Selfdb@1", "Couchbase password"); | ||
| DEFINE_string(couchbase_host, "couchbase://localhost", "Couchbase server host"); | ||
| DEFINE_string(username, "Administrator", "Couchbase username"); |
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.
Nitpick: I tend to not like to use Administrator/password everywhere, as it encourages bad security behavior. They should have a normal user. Not necessary to change though unless you think about it.
| "Couchbase server host"); | ||
| DEFINE_string(username, "selfdb", "Couchbase username"); | ||
| DEFINE_string(password, "Selfdb@1", "Couchbase password"); | ||
| DEFINE_string(couchbase_host, "couchbase://localhost", "Couchbase server host"); |
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.
Nitpick: examples like this are often great places to drop in a few commented out examples of common things a user might want to do. For example, switch on TLS. Or add the wan development profile.
See:
https://docs.couchbase.com/cxx-sdk/current/howtos/managing-connections.html#connecting-to-a-cluster
No need to change unless you want to though.
What problem does this PR solve?
Currently, brpc supports various protocols like memcached, Redis, and HTTP, but lacks native support for Couchbase, a popular NoSQL document database. Users who want to integrate Couchbase with brpc applications can now directly use the builtin wrapper functions, this would help in writing less code and build the applications even faster.
What is changed and the side effects?
Changed:
Side effects:
Performance effects:
Breaking backward compatibility: