I am try to create buckets in a new Couchbase cluster using the Node SDK. This is a process I used to do successfully use SDK 2.6. The methods are slightly different in 3.0.7 but it looks like the equivalent calls exist and the procedure should be the same. So I first call getAllBuckets to find out what buckets are currently in the cluster and whether any need to be created.
However, I get an error: âYou must have one open bucket before you can perform queries.â. Obviously I donât have an open bucket but nor should I need one for this. There may not even be any buckets on the system. I also get the same error if I try to get a single bucket with manager.getBucket("mybucket")
If I open a bucket first, with bucket = cluster.bucket("mybucket") then call manager.getBucket() or manager.getAllBuckets() it works. However, if the bucket that I opened with cluster.bucket doesnât actually exist (e.g. cluster.bucket(âdummyâ)) then the getAllBuckets donât just return an error, they throw an uncatchable unhandledPromiseRejection inside the call. This means that my catch block is not reached - the CB library has failed to catch and pass on the rejection which causes the application to quit!
I think due to the unhandled reject getBucket and getAllBuckets are not usable, so the only way that I can think of to test whether a bucket exists is to try to open it with cluser.bucket, then get the default collection and call collection.get(âdummyâ). This will fail with documentNotFound if the bucket is valid, or âcluster object was closedâ if not. This error is also given if the password is not correct, so itâs not foolproof but I canât think of a better way.
Moving on from this the next step is to create the bucket if it doesnât exist. However, this also fails if there is not a bucket open, therefore I donât think they can be used to create the first bucket in a new cluster. As an aside, the 3.0.7 API docs for createBucket are incorrect - they say that the only setting that can be passed is conflictResolutionType. They donât even say how to pass the new bucket name! The function does accept ânameâ in settings though and does work, as long as you have opened an existing bucket first.
will not work as it is not connecting to the cluster at cluster-level. Also, ensure that you are running the latest version of couchbase *3.0.7 or you may still have issues.
This is not covered well in the docs and I am going to try and fix that. If this answers your question it would help if you can mark the post as resolved or if you have any more questions about this let me know.
Thanks for the reply and the solution. I can confirm that, as long as connection is valid, calling âcouchbase,connectâ rather than ânew couchbase.Clusterâ does work and I will mark this as solved. I have a few comments/questions:
If the username or password passed to couchbase.connect is incorrect, the call still resolves the promise but getBucket() returns the same âYou mist have one open bucket before you can perform queriesâ error. This is misleading - the error should be related to authentication.
Considering the couchbase.connect call always passes even if the credentials are wrong, why does it return a promise? It seems like it could be similar to the normal âcluster = new Cluster()â call, since it doesnât actually give an error until you try to use it (so I guess isnât checking the credentials and making the connection before returning).
âit is not connecting to the cluster at cluster-levelâ - I donât understand this. What do you mean by cluster level and what level is the ânew couchbase.Clusterâ connecting at? The cluster returned by couchbase.connect can still be used for cluster.bucket(), collection.get(), etc, so whatâs the difference?
One final thing, related to this forum rather than CB: when you posted this solution you just edited your previous message where you said âIâm looking into this issueâ rather than posting a new comment. I understand why you did this - to keep the thread clean and remove unnecessary comments. However, it meant I didnât get a notification (either email or in-forum) for the solution. More trivially,it also meant I couldnât âlikeâ the solution as I had already liked the âIâm looking into itâ comment!
Thanks very much for your work and this solution. I appreciate your efforts on Couchbase.
Iâll try to respond to your questions/comments individually:
This is indeed a bit miss-leading, but itâs challenging to resolve due to the answer of your second question below.
It returns a promise because there are a few async things it does during connect, primarily related to the validation of the input parameters. For instance, if the SSL certificate you have passed is badly formatted. These kinds of errors which will never resolve themselves are thrown at connect time.
Fundamentally, Couchbase connects at a bucket level when talking to the memcached service (ie: a connection is bucket-specific). On top of this, we have a logical âcluster-levelâ which allows you to perform operations which apply to the whole cluster, such as the creation of buckets or querying with a query which crosses buckets. Calling the connect method is what sets up these initial bucket-less connections which allow us to fetch the topology of the cluster. Due to the fact that we need to perform some async work during the initial setup of our Cluster object we needed to provide a method rather than a constructor such that we can return a promise. Note that the Cluster constructor is actually hidden and documented as not intended to be used directly, Cluster::connect is the correct way to instantiate a Cluster object. I should likely have masked it behind some proxy object when exposed by the SDK, but unfortunately we wonât be able to do this until 4.0.0.
Thanks for the explanation. Are you saying that we should always use âcouchbase.connectâ rather than ânew couchbase.Clusterâ, contrary to the âGetting Startedâ doc?
Sorry to hassle you on this when you and @ericb have already resolved this issue, but I just want to clarify your previous message. Should I always use couchbase.connect rather than new couchbase.Cluster to connect, whether Iâm doing bucket or cluster level operations?