Skip to content
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

Connected client and Async #1394

Draft
wants to merge 81 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
c977bd4
Improvements to experimental Async API
snej Feb 3, 2022
88bfcaf
Lots more Async work!
snej Feb 4, 2022
00cfb30
More Async
snej Feb 4, 2022
84ead1a
Async cleanup/refactoring
snej Feb 10, 2022
7e27c8d
(WIP)
snej Feb 10, 2022
1e9e1ec
More Async work/fixes
snej Feb 18, 2022
04093a2
Use Async in the replicator
snej Feb 18, 2022
8762084
ConnectedClient prototype
snej Feb 15, 2022
0162eb6
Thread-safety for QuietReporter
snej Feb 18, 2022
e2ac765
Xcode: Disable sanitizers for LogEncoder.cc and Logging.cc
snej Feb 18, 2022
1aef69c
LoopbackProvider: Disabled a troublesome assertion
snej Feb 18, 2022
beaf254
More ConnectedClient work
snej Feb 18, 2022
660aea3
ConnectedClient: More tests and some fixes
snej Feb 22, 2022
75eba03
Added kC4ReplicatorOptionAllowConnectedClient
snej Feb 22, 2022
5138867
WIP: Implementing ConnectedClient observer
snej Feb 22, 2022
88ae6dd
BLIP: Define constants for hardcoded strings like "Profile"
snej Feb 22, 2022
dbccbb9
Made BLIP::MessageNo type-safe
snej Feb 22, 2022
55665b1
(more blip cleanup)
snej Feb 22, 2022
625e945
c4Test: Made importJSONLines work in non-empty db
snej Feb 22, 2022
8565cb6
(oops, fixed MessageBuilder)
snej Feb 22, 2022
d62c9bc
ConnectedClient::observe works
snej Feb 22, 2022
91c8960
Async tweaks (avoid copying)
snej Feb 23, 2022
d39ba90
ConnectedClient: Don't use alloc_slice in API
snej Feb 23, 2022
b1ea96b
Async: Got rid of BEGIN/AWAIT/END, and other work
snej Feb 25, 2022
edd4948
Async: Improved error/exception handling
snej Feb 25, 2022
6542a06
Async: Simplified the way providers notify
snej Feb 25, 2022
e064af4
Async: Error handling working, whew
snej Mar 2, 2022
ce017e9
API: Added constant `kC4NoError`
snej Mar 3, 2022
0602109
Async: Cleanup, API tweaks, documentation
snej Mar 3, 2022
79cab42
Fleshing out and documenting Result
snej Mar 4, 2022
dcf0bb5
Result: Hardcode C4Error instead of it being a template param
snej Mar 4, 2022
09f42e2
Fixed CMake build
snej Mar 4, 2022
ad517d3
Result::value() now throws the error as an exception
snej Mar 4, 2022
a416ffb
Result: Cleanup
snej Mar 4, 2022
65c5b0c
GCC & MSVC fixes
snej Mar 4, 2022
e5f79c5
Xcode: Disable `-fsanitize-ignorelist` flag until Jenkins is upgraded
snej Mar 7, 2022
de5316d
c4connectedclient API
jayahariv Mar 11, 2022
4a26a19
Update the API to pass only a Configuration and will create the c4ock…
jayahariv Mar 16, 2022
0f7e16c
add socket options as well as append the blipsync in the URL
jayahariv Mar 17, 2022
4d3ce4a
release the connected client once its done, exposed the start, stop a…
jayahariv Mar 17, 2022
dd90f28
update docs
jayahariv Mar 18, 2022
68a9b59
remove empty line
jayahariv Mar 18, 2022
cd7631f
review changes
jayahariv Mar 22, 2022
50203fb
add the API definitions in c4_ee txt file too and generated the expor…
jayahariv Mar 24, 2022
96e0be7
include the implementation files to cmake source list
jayahariv Mar 24, 2022
cf85c8d
avoid designated initializer
jayahariv Mar 24, 2022
f4bd081
keep the lock only for delegate: review changes
jayahariv Mar 24, 2022
bd24d79
rename the callback to GetDocument
jayahariv Mar 24, 2022
f30757f
Removed unnecessary #include from Async.hh
snej Apr 6, 2022
8d250bc
ConnectedClient: Encryption/decryption/_attachments
snej Apr 7, 2022
5443009
ConnectedClient: Got encryption/decryption tests working
snej Apr 7, 2022
bb4cdf5
Connected Client: Minor C API & doc tweaks
snej Apr 7, 2022
7a3c692
Doxygen fixes
snej Apr 7, 2022
e889a68
ConnectedClient: added a blobs/attachments test
snej Apr 9, 2022
4495d4f
ConnectedClient: getBlobContents() now takes a C4BlobKey
snej Apr 9, 2022
3d43cab
ConnectedClient: Legacy-attachment unit tests
snej Apr 11, 2022
6f24c66
Added ConnectedClientProtocol.md
snej Apr 11, 2022
2afbcc5
Connected Client: Some changes to protocol
snej Apr 14, 2022
4495cf1
Expose docUpdate API (#1437)
jayahariv Apr 18, 2022
f8f4d47
Connected Client: experimental implementation of "query"
snej Apr 15, 2022
67ba28e
C4ConnectedClient API fixes
snej Apr 20, 2022
920e034
Made C4ConnectedClient with with BuiltInWebSocket
snej Apr 20, 2022
d531c46
Added C4ConnectedClient::getStatus
snej Apr 20, 2022
bf27809
Merge branch 'master' into feature/connected-client
snej Apr 21, 2022
434dc98
Merge branch 'feature/connected-client' of https://github.com/couchba…
snej Apr 28, 2022
c29a151
WIP: allDocs for ConnectedClient
snej Apr 28, 2022
c3f6d89
WIP: Server side of ConnectedClient allDocs
snej Apr 28, 2022
25fc306
Connected Client: allDocs fixes
snej Apr 28, 2022
91e10e8
ConnectedClient: query improvements
snej May 2, 2022
a36a68d
ConnectedClient: Added a query unit test, fixed a bug.
snej May 2, 2022
df83807
ConnectedClient: Added listener options [API]
snej May 2, 2022
0979404
blip::IncomingMessage now uses fleece::Doc
snej May 4, 2022
fd5b451
Fixed CMake build
snej May 4, 2022
b0bd654
Bumped LITECORE_VERSION and LITECORE_API_VERSION
snej May 4, 2022
8682cbf
ConnectedClient: Changed query result data format
snej May 20, 2022
4bb9a22
oops, updated Fleece to fix build
snej May 26, 2022
d3850cb
Renamed Replicator::ProtocolName() -> protocolName()
snej Jun 1, 2022
f530bd9
Fixed: C4ConnectedClient doesn't use auth
snej Jun 1, 2022
6d231ff
Xcode: Only run Doxygen in Release builds
snej Jun 1, 2022
f17bbc3
C4ConnectedClient: Implemented onStatusChanged callback
snej Jun 1, 2022
b974f51
Merge branch 'master' into feature/connected-client
snej Jun 1, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions C/Cpp_include/c4.hh
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,4 @@
#include "c4Query.hh"
#include "c4Replicator.hh"
#include "c4Socket.hh"
#include "c4ConnectedClient.hh"
125 changes: 125 additions & 0 deletions C/Cpp_include/c4ConnectedClient.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
//
// c4ConnectedClient.hh
//
// Copyright 2022-Present Couchbase, Inc.
//
// Use of this software is governed by the Business Source License included
// in the file licenses/BSL-Couchbase.txt. As of the Change Date specified
// in that file, in accordance with the Business Source License, use of this
// software will be governed by the Apache License, Version 2.0, included in
// the file licenses/APL2.txt.
//

#pragma once
#include "c4Base.hh"
#include "Async.hh"
#include "c4ConnectedClientTypes.h"
#include "fleece/Fleece.h"

C4_ASSUME_NONNULL_BEGIN

struct C4ConnectedClient : public fleece::RefCounted,
public fleece::InstanceCountedIn<C4Database>,
C4Base
{
/// Creates a new ConnectedClient
/// \note It will automatically starts the client, no need to call `start()`.
///
/// @param params Connected Client parameters.
/// @result A new \ref C4ConnectedClient, or NULL on failure.
static Retained<C4ConnectedClient> newClient(const C4ConnectedClientParameters &params);

/// The current connection status.
virtual litecore::actor::Async<C4ConnectedClientStatus> getStatus() const =0;

/// The HTTP response headers.
virtual alloc_slice getResponseHeaders() const noexcept =0;

#ifdef COUCHBASE_ENTERPRISE
/// The server's TLS certificate.
virtual C4Cert* C4NULLABLE getPeerTLSCertificate() const =0;
#endif

/// Result of a successful `getDoc()` call.
struct DocResponse {
alloc_slice docID, revID, body;
bool deleted;
};

/// Gets the current revision of a document from the server.
/// You can set the `unlessRevID` parameter to avoid getting a redundant copy of a
/// revision you already have.
/// @param docID The document ID.
/// @param collectionID The name of the document's collection, or `nullslice` for default.
/// @param unlessRevID If non-null, and equal to the current server-side revision ID,
/// the server will return error {WebSocketDomain, 304}.
/// @param asFleece If true, the response's `body` field is Fleece; if false, it's JSON.
/// @result An async value that, when resolved, contains either a `DocResponse` struct
/// or a C4Error.
virtual litecore::actor::Async<DocResponse> getDoc(slice docID,
slice collectionID,
slice unlessRevID,
bool asFleece)=0;

/// Pushes a new document revision to the server.
/// @param docID The document ID.
/// @param collectionID The name of the document's collection, or `nullslice` for default.
/// @param parentRevID The ID of the parent revision on the server,
/// or `nullslice` if this is a new document.
/// @param revisionFlags Flags of this revision.
/// @param fleeceData The document body encoded as Fleece (without shared keys!)
/// @return An async value that, when resolved, contains new revisionID or the status as a C4Error
virtual litecore::actor::Async<std::string> putDoc(slice docID,
slice collectionID,
slice parentRevID,
C4RevisionFlags revisionFlags,
slice fleeceData)=0;

/// Callback for \ref getAllDocIDs.
/// @param ids A vector of docIDs; empty on the final call.
/// @param error NULL or a pointer to an error.
using AllDocsReceiver = std::function<void(const std::vector<slice>& ids,
const C4Error* C4NULLABLE error)>;

/// Requests a list of all document IDs, or optionally only those matching a pattern.
/// The docIDs themselves are passed to a callback.
/// The callback will be called zero or more times with a non-empty vector of docIDs,
/// then once with an empty vector and an optional error.
/// @param collectionID The ID of the collection to observe.
/// @param globPattern Either `nullslice` or a glob-style pattern string (with `*` or
/// `?` wildcards) for docIDs to match.
/// @param callback The callback to receive the docIDs.
virtual void getAllDocIDs(slice collectionID,
slice globPattern,
AllDocsReceiver callback) =0;

/// Callback for \ref query.
/// @param rowJSON A row of the result, encoded as a JSON object.
/// On the final call, will be `nullslice`.
/// @param rowDict The row parsed as a Fleece Dict, if you requested it.
/// @param error NULL or, on the final call, a pointer to an error.
using QueryReceiver = std::function<void(FLSlice rowJSON,
FLDict rowDict,
const C4Error* C4NULLABLE error)>;

/// Runs a query on the server and gets the results.
/// The callback will be called one or more times; see its documentation for details.
/// @param name The name by which the query has been registered on the server;
/// or a full query string beginning with "SELECT " or "{".
/// @param parameters A Dict mapping query parameter names to values.
/// @param rowsAsFleece True if you want the rows to be Fleece-encoded, false for JSON.
/// @param receiver A callback that will be invoked for each row of the result,
/// and/or if there's an error.
virtual void query(slice name,
FLDict C4NULLABLE parameters,
bool rowsAsFleece,
QueryReceiver receiver) =0;

/// Tells a connected client to start.
virtual void start()=0;

/// Tells a replicator to stop.
virtual void stop()=0;
};

C4_ASSUME_NONNULL_END
6 changes: 0 additions & 6 deletions C/Cpp_include/c4Document.hh
Original file line number Diff line number Diff line change
Expand Up @@ -146,12 +146,6 @@ struct C4Document : public fleece::RefCounted,
/// Returns the Document instance, if any, that contains the given Fleece value.
static C4Document* C4NULLABLE containingValue(FLValue) noexcept;

static bool isOldMetaProperty(slice propertyName) noexcept;
static bool hasOldMetaProperties(FLDict) noexcept;

static alloc_slice encodeStrippingOldMetaProperties(FLDict properties,
FLSharedKeys);

// Special property names & values:

/** The Dict property that identifies it as a special type of object.
Expand Down
1 change: 1 addition & 0 deletions C/Cpp_include/c4EnumUtil.hh
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
//

#pragma once
#include "c4Compat.h"
#include <type_traits>

/// Declares `++` and `--` functions for an `enum class`.
Expand Down
3 changes: 2 additions & 1 deletion C/Doxyfile
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,7 @@ SORT_MEMBERS_CTORS_1ST = NO
# appear in their defined order.
# The default value is: NO.

SORT_GROUP_NAMES = NO
SORT_GROUP_NAMES = YES

# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
# fully-qualified names, including namespaces. If set to NO, the class list will
Expand Down Expand Up @@ -2039,6 +2039,7 @@ INCLUDE_FILE_PATTERNS =

PREDEFINED = DOXYGEN_PARSING=1 \
C4API= \
C4API_BEGIN_DECLS= \
C4NULLABLE= \
C4NONNULL= \
C4_RETURNS_NONNULL= \
Expand Down
11 changes: 10 additions & 1 deletion C/DoxygenDependencies.txt
Original file line number Diff line number Diff line change
@@ -1,23 +1,32 @@
$(SRCROOT)/../C/include/c4.h
$(SRCROOT)/../C/Doxyfile
$(SRCROOT)/../C/include/c4Base.h
$(SRCROOT)/../C/include/c4BlobStore.h
$(SRCROOT)/../C/include/c4BlobStoreTypes.h
$(SRCROOT)/../C/include/c4Certificate.h
$(SRCROOT)/../C/include/c4CertificateTypes.h
$(SRCROOT)/../C/include/c4Collection.h
$(SRCROOT)/../C/include/c4Compat.h
$(SRCROOT)/../C/include/c4ConnectedClient.h
$(SRCROOT)/../C/include/c4ConnectedClientTypes.h
$(SRCROOT)/../C/include/c4Database.h
$(SRCROOT)/../C/include/c4DatabaseTypes.h
$(SRCROOT)/../C/include/c4DocEnumerator.h
$(SRCROOT)/../C/include/c4DocEnumeratorTypes.h
$(SRCROOT)/../C/include/c4Document+Fleece.h
$(SRCROOT)/../C/include/c4Document.h
$(SRCROOT)/../C/include/c4DocumentStruct.h
$(SRCROOT)/../C/include/c4DocumentTypes.h
$(SRCROOT)/../C/include/c4Error.h
$(SRCROOT)/../C/include/c4Index.h
$(SRCROOT)/../C/include/c4IndexTypes.h
$(SRCROOT)/../C/include/c4Listener.h
$(SRCROOT)/../C/include/c4ListenerTypes.h
$(SRCROOT)/../C/include/c4Log.h
$(SRCROOT)/../C/include/c4Observer.h
$(SRCROOT)/../C/include/c4PredictiveQuery.h
$(SRCROOT)/../C/include/c4Query.h
$(SRCROOT)/../C/include/c4QueryTypes.h
$(SRCROOT)/../C/include/c4Replicator.h
$(SRCROOT)/../C/include/c4ReplicatorTypes.h
$(SRCROOT)/../C/include/c4Socket.h
$(SRCROOT)/../C/include/c4SocketTypes.h
6 changes: 6 additions & 0 deletions C/c4.exp
Original file line number Diff line number Diff line change
Expand Up @@ -417,5 +417,11 @@ _FLDictIterator_End
_FLValue_IsEqual
_FLValue_ToJSON5

_c4client_new
_c4client_getDoc
_c4client_start
_c4client_stop
_c4client_putDoc

# Apple specific
_FLEncoder_WriteNSObject
7 changes: 4 additions & 3 deletions C/c4CAPI.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "c4Query.hh"
#include "c4QueryImpl.hh"
#include "c4Replicator.hh"
#include "LegacyAttachments.hh"

#include "c4.h"
#include "c4Private.h"
Expand Down Expand Up @@ -1102,12 +1103,12 @@ FLSharedKeys c4db_getFLSharedKeys(C4Database *db) noexcept {


bool c4doc_isOldMetaProperty(C4String prop) noexcept {
return C4Document::isOldMetaProperty(prop);
return legacy_attachments::isOldMetaProperty(prop);
}


bool c4doc_hasOldMetaProperties(FLDict doc) noexcept {
return C4Document::hasOldMetaProperties(doc);
return legacy_attachments::hasOldMetaProperties(doc);
}


Expand Down Expand Up @@ -1152,7 +1153,7 @@ bool c4doc_blobIsCompressible(FLDict blobDict) {

C4SliceResult c4doc_encodeStrippingOldMetaProperties(FLDict doc, FLSharedKeys sk, C4Error *outError) noexcept {
return tryCatch<C4SliceResult>(outError, [&]{
return C4SliceResult(C4Document::encodeStrippingOldMetaProperties(doc, sk));
return C4SliceResult(legacy_attachments::encodeStrippingOldMetaProperties(doc, sk));
});
}

Expand Down
16 changes: 0 additions & 16 deletions C/c4Document.cc
Original file line number Diff line number Diff line change
Expand Up @@ -361,19 +361,3 @@ C4RevisionFlags C4Document::revisionFlagsFromDocFlags(C4DocumentFlags docFlags)
C4Document* C4Document::containingValue(FLValue value) noexcept {
return C4Collection::documentContainingValue(value);
}


bool C4Document::isOldMetaProperty(slice propertyName) noexcept {
return legacy_attachments::isOldMetaProperty(propertyName);
}


bool C4Document::hasOldMetaProperties(FLDict dict) noexcept {
return legacy_attachments::hasOldMetaProperties((const fleece::impl::Dict*)dict);
}


alloc_slice C4Document::encodeStrippingOldMetaProperties(FLDict properties, FLSharedKeys sk) {
return legacy_attachments::encodeStrippingOldMetaProperties((const fleece::impl::Dict*)properties,
(fleece::impl::SharedKeys*)sk);
}
37 changes: 18 additions & 19 deletions C/c4Error.cc
Original file line number Diff line number Diff line change
Expand Up @@ -225,31 +225,30 @@ C4Error C4Error::fromException(const exception &x) noexcept {

__cold
C4Error C4Error::fromCurrentException() noexcept {
// This rigamarole recovers the current exception being thrown...
auto xp = std::current_exception();
if (xp) {
try {
std::rethrow_exception(xp);
} catch(const std::exception& x) {
// Now we have the exception, so we can record it in outError:
return C4Error::fromException(x);
} catch (...) { }
return fromException(error::convertCurrentException());
}


static string getMessage(const C4Error &c4err) {
auto info = ErrorTable::instance().copy(c4err);
return info ? info->message : "";
}


namespace litecore {
// Declared in Error.hh
error::error(const C4Error &c4err)
:error(error::Domain(c4err.domain), c4err.code, getMessage(c4err))
{
if (auto info = ErrorTable::instance().copy(c4err))
backtrace = info->backtrace;
}
return ErrorTable::instance().makeError(
LiteCoreDomain, kC4ErrorUnexpectedError,
{"Unknown C++ exception", Backtrace::capture(1)});
}


[[noreturn]] __cold
void C4Error::raise() const {
if (auto info = ErrorTable::instance().copy(*this); info) {
error e(error::Domain(domain), code, info->message);
e.backtrace = info->backtrace;
throw e;
} else {
error::_throw(error::Domain(domain), code);
}
throw litecore::error(*this);
}


Expand Down
6 changes: 6 additions & 0 deletions C/c4_ee.exp
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,12 @@ _FLDictIterator_End
_FLValue_IsEqual
_FLValue_ToJSON5

_c4client_new
_c4client_getDoc
_c4client_start
_c4client_stop
_c4client_putDoc


_c4db_URINameFromPath

Expand Down
1 change: 1 addition & 0 deletions C/include/c4.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@
#include "c4Query.h"
#include "c4Replicator.h"
#include "c4Socket.h"
#include "c4ConnectedClient.h"
10 changes: 8 additions & 2 deletions C/include/c4Base.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ C4API_BEGIN_DECLS

// Corresponds to Couchbase Lite product version number, with 2 digits for minor and patch versions.
// i.e. `10000 * MajorVersion + 100 * MinorVersion + PatchVersion`
#define LITECORE_VERSION 30000
#define LITECORE_VERSION 30100

// This number has no absolute meaning but is bumped whenever the LiteCore public API changes.
#define LITECORE_API_VERSION 351
#define LITECORE_API_VERSION 352


/** \defgroup Base Data Types and Base Functions
Expand Down Expand Up @@ -117,6 +117,9 @@ typedef struct C4Cert C4Cert;
/** Opaque handle to a namespace of documents in an opened database. */
typedef struct C4Collection C4Collection;

/** Opaque reference to a Connected Client. */
typedef struct C4ConnectedClient C4ConnectedClient;

/** A collection-observer reference. */
typedef struct C4CollectionObserver C4CollectionObserver;

Expand Down Expand Up @@ -182,6 +185,8 @@ static inline C4Cert* C4NULLABLE
c4cert_retain(C4Cert* C4NULLABLE r) C4API {return (C4Cert*)c4base_retain(r);}
static inline C4Collection* C4NULLABLE
c4coll_retain(C4Collection* C4NULLABLE r) C4API {return (C4Collection*)c4base_retain(r);}
static inline C4ConnectedClient* C4NULLABLE
c4client_retain(C4ConnectedClient* C4NULLABLE r) C4API {return (C4ConnectedClient*)c4base_retain(r);}
static inline C4Database* C4NULLABLE
c4db_retain(C4Database* C4NULLABLE r) C4API {return (C4Database*)c4base_retain(r);}
static inline C4KeyPair* C4NULLABLE
Expand All @@ -197,6 +202,7 @@ CBL_CORE_API C4Socket* C4NULLABLE
c4socket_retain(C4Socket* C4NULLABLE) C4API;

static inline void c4cert_release (C4Cert* C4NULLABLE r) C4API {c4base_release(r);}
static inline void c4client_release (C4ConnectedClient* C4NULLABLE r) C4API {c4base_release(r);}
static inline void c4coll_release (C4Collection* C4NULLABLE r) C4API {c4base_release(r);}
static inline void c4db_release (C4Database* C4NULLABLE r) C4API {c4base_release(r);}
static inline void c4keypair_release(C4KeyPair* C4NULLABLE r) C4API {c4base_release(r);}
Expand Down
Loading