Get desktop application:
View/edit binary Protocol Buffers messages
When an implementation supports multiple APIs, this enum allows sending which is preferred to be used for a given test. This is an abstraction that allows us to test e.g. Java's blocking vs reactive APIs. Declaration in supportedApis: For implementations with just one API: Only declare DEFAULT. For implementations with separate blocking & async APIs: declare both. When the performer receives a preferred API: For implementations with just one API: ignore it. For implementations with separate blocking & async APIs: use the appropriate one.
Used in: , , , ,
Used in: ,
Used in:
An X509 certificate in PEM format, e.g. -----BEGIN CERTIFICATE----- MIIDKDCCAhCgAwIBAgIGAYfmPG2mMA0GCSqGSIb3DQEBCwUAMDYxNDAyBgNVBAMT K2FwcHMuY2xvdWQtbmF0aXZlLmZnMWIucDEub3BlbnNoaWZ0YXBwcy5jb20wHhcN ... I+VkRC5NwrqMsnR3149LAVcj6Jen8hMjLM0wR8Frqu2zV9HW5yHMQmOTOKE= -----END CERTIFICATE----- The SDK should apply it in whatever way makes sense for it. Some SDKs (e.g. the C++ wrappers) cannot pass in such a certificate directly to the SDK. In this case they should write it to a temporary file first.
An X509 key in PEM format, e.g. -----BEGIN RSA PRIVATE KEY----- MIIJKAIBAAKCAgEAwiYPcb0zL9B5ZCn5mo/sF2QwdNr/aKjdfvnO6hx9h80klu5m ... QZ57rjd7D6hDSzbSxNW54ktF0ZJrBZatfXJize2/WL1SzSAkm7rJovUWXKA= -----END RSA PRIVATE KEY----- The SDK should apply it in whatever way makes sense for it. Some SDKs (e.g. the C++ wrappers) cannot pass in such a certificate directly to the SDK. In this case they should write it to a temporary file first.
Used in:
Used in:
Controls how a given workload is bounded. A simple bounding would be to just run X operations as fast as possible, and then stop. In future we will support more advanced bounds, such as the performer maintaining a target throughput of 100 ops/sec and seeing what the latency is, for 60 seconds.
Used in: , ,
The performer decrements the counter and continues iff counter is now > 0
The performer should not change the counter, just continue iff its equal to the initial value
Clear all counters for a given performer.
Used as request type in: PerformerService.clearAllCounters
(message has no fields)
Empty but included anyway per GRPC best practices.
Used as response type in: PerformerService.clearAllCounters
(message has no fields)
Used in:
Will only be sent to ExtSDKIntegration-enabled performers.
The performer should use a custom JsonSerializer when creating the Cluster. This custom JsonSerializer is required to have specific serialization and deserialization logic, which the driver will validate. See the Java performer for implementation details.
Used for TLS enabled clusters such as Capella clusters. Note that use_tls should only be used by SDKs that have such a field (e.g. Java). Many SDKs do not have a use_tls equivalent, and TLS is enabled via couchbases:// on the connection string. The driver will use the appropriate option.
If specified, it's the path to an certificate in PEM format, that the SDK should apply in whatever way makes sense for it. If `cert_path` is specified, `cert` will not be. (They are not `oneof`, for backwards compatibility). Note that now FIT is mainly tested through Docker, `cert_path` is generally not usable since it's non-trivial to pass files between Docker containers. `cert` should generally be used instead.
If specified, it's an X509 certificate in PEM format, e.g. -----BEGIN CERTIFICATE----- MIIDKDCCAhCgAwIBAgIGAYfmPG2mMA0GCSqGSIb3DQEBCwUAMDYxNDAyBgNVBAMT K2FwcHMuY2xvdWQtbmF0aXZlLmZnMWIucDEub3BlbnNoaWZ0YXBwcy5jb20wHhcN ... I+VkRC5NwrqMsnR3149LAVcj6Jen8hMjLM0wR8Frqu2zV9HW5yHMQmOTOKE= -----END CERTIFICATE----- The SDK should apply it in whatever way makes sense for it. Some SDKs (e.g. the C++ wrappers) cannot pass in such a certificate directly to the SDK. In this case they should write it to a temporary file first. If `cert_path` is specified, `cert` will not be. (They are not `oneof`, for backwards compatibility). `cert` can be used where it's not easy to pass `cert_path`, such as when the driver and performer are on separate nodes or Docker containers.
The SDK should skip certificate validation. It's SDK dependent how to implement this. On JVM it may involve applying InsecureTrustManager, while on a C++ wrapper it may require manipulating the connstr to pass "?tls_verify=none". Not every SDK can support this option against every backend. See internal discussion: https://couchbase.slack.com/archives/G9682CWN7/p1698333449931709 Behind cap CLUSTER_CONFIG_INSECURE.
Following taken from: https://github.com/couchbaselabs/sdk-rfcs/blob/master/rfc/0059-sdk3-foundation.md#configuration
Whether some sort of observability (e.g. OpenTelemetry) output should be configured. The performer should pass this in to the cluster config's `requestTracer` and/or `meter` settings (depending on whether tracing and/or metrics is enabled). These will generally create OpenTelemetry SDK objects, e.g. SdkTracerProvider and SdkMeterProvider. These must be closed at the same time as this cluster connection is closed. Otherwise the SdkMeterProvider will continue outputting metrics until the application ends.
A Application telemetry endpoint WebSocket URI of the form "ws://<host>:<port>/<path>"
Used as request type in: PerformerService.clusterConnectionClose
Used as response type in: PerformerService.clusterConnectionClose
The number of cluster connections the performer has, after closing this one.
Only sent to ExtSDKIntegration-supporting performers. Creates a cluster connection, with an optional cluster & transactions configuration.
Used as request type in: PerformerService.clusterConnectionCreate
The id to use for this connection.
Details of the cluster connection. cluster_hostname is the connection string. As with all fields (see rule 1 in README.md), the performer should pass this directly to the SDK without manipulation. E.g. it should not prepend couchbase:// or similar.
Either these two fields will be set or authenticator will be set, but not both. These will always be set until the performer returns the SupportsAuthenticator capability.
Can apply SDK tunables that can't be represented generically in GRPC. One example is for performance testing, where we may want to experiment with various approaches in say the Java SDK. So one run may send "com.couchbase.executorMaxThreadCount"="10", and the next set it to "20". Interpretation of the tunables, and how to apply them inside the SDK, is completely SDK-dependent. The intent is that the tunables be associated with the cluster connection, but this may not be possible in all implementations - e.g. Java uses global system properties instead. Generally performers can ignore this field unless they are explicitly planning on using it.
Either this will be set or username/password will be set, but not both. These will never be set until the performer returns the SupportsAuthenticator capability.
Used as response type in: PerformerService.clusterConnectionCreate
The number of cluster connections the performer has, after opening this one.
Used in: , , , , , , , , ,
Used in: , , , , , , ,
This should be passed directly into the SDK, as string type - no initial conversion into a JsonObject or similar. How this is treated by the SDK will depend on the transcoder set (if any), which is sent separately in the options. (Usually it will be sent with RawJsonTranscoder).
The contents of this are JSON. The performer should convert to a platform-dependent representation of JSON, and then pass into the SDK. For Java, that would be the SDK's JsonObject. For Node, the result of JSON.parse(). Whatever is the most appropriate way to take a JSON blob and send it to the SDK without having to provide a transcoder, is the intent here.
Treat this content as a byte array and pass it directly through the SDK.
If this is sent then the performer should pass null/nil/none (depending on language) as the content.
The user is doing someResult.contentAs[Something]() - this allows specifying the Something. The protocol generally then requires that content to be converted into bytes to be streamed back.
Used in: , , , , , , , , , , , , ,
Intended to get the result as a String, then convert it into bytes from UTF-8. Something like this: var result = someResult.contentAs[String]() var returnOverGRPC = result.getBytes(StandardCharsets.UTF_8)
Intended to get the result as a byte array, then convert it into bytes. Something like this: var returnOverGRPC = someResult.contentAs[Array[Byte]]() var returnOverGRPC = someResult.contentAsBytes()
JSON handling is very platform-dependent. The intent is to get the result in your platform's most standard/natural representation of JSON Objects, and then convert it into bytes, again using the most standard way of doing that. E.g. this is intended to represent how most users will use the SDK. var result = someResult.contentAs[JsonObject] var returnOverGRPC = result.toBytes()
JSON handling is very platform-dependent. The intent is to get the result in your platform's most standard/natural representation of JSON Arrays, and then convert it into bytes, again using the most standard way of doing that. E.g. this is intended to represent how most users will use the SDK. var result = someResult.contentAs[JsonArray] var returnOverGRPC = result.toBytes()
This is a way to represent an SDK deserializing content as a Boolean. Results where this is used should include a boolean in the oneof selection for content
The driver is requesting someResult.contentAs[Integer]. The performer is free to interpret `Integer` in a platform-specific way. Tests will only be expecting values well below the limits of a 32 bit signed integer, and the performer can safely use the platform-specific version of such a type to hold the value: for example, an `int` or `long` are both fine.
The driver is requesting someResult.contentAs[Float]. The performer is free to interpret `Float` in a platform-specific way. Tests will only be expecting values well below the limits of a 32 bit signed floating point, and the performer can safely use the platform-specific version of such a type to hold the value: for example, a `float` or `double` are both fine.
For subsystems (such as transactions) that rely on performer-side validation. Many result types have a `SomeResult.contentAs[SomeType]()` call, and this message controls how the performer executes those, and what validation it performs.
Used in: , , ,
How the performer should perform SomeResult.contentAs[SomeType]().
If true, the contentAs operation is expected to succeed and the performer needs to validate this, raising a GRPC FAILED_PRECONDITION error if not. If false, the contentAs operation is expected to fail and similarly the performer needs to validate this and raise a GRPC INVALID_ARGUMENT error if validation fails. Specifically the operation would be expected to fail with an SDK3 DecodingFailureException. However, it is known that some SDKs do not follow the model, and so it is not a required part of the validation. The performer can choose to optionally validate it is a DecodingFailureException, for an extra level of regression safety.
If specified, the performer will check the results of contentAs operation against this. The results of the contentAs operation should be converted to a byte[] first. Iff the expected content does not equal the actual content, the performer should raise a GRPC FAILED_PRECONDITION error.
Used in: ,
Used in: , , , , ,
Used for content as bytes and JSON
content returned by sdk is supposed to be null
Used in:
(message has no fields)
An exception derived from CouchbaseException "Ex" naming as transactions already has CouchbaseException in an enum.
Used in:
The simple name e.g. "DocumentNotFoundException"
Broadly this is the result of outputting the exception. E.g. for Java `ex.toString()`. Per the RFC it's expected to contain the serialized error context.
All errors derived from CouchbaseException. The performer should return the most specific error possible. E.g. not SDK_COUCHBASE_EXCEPTION, unless a raw CouchbaseException is what the SDK raised. From https://github.com/couchbaselabs/sdk-rfcs/blob/master/rfc/0058-error-handling.md Go specific notes: Go deviates from the error handling RFC in a few ways, and gets some special handling in the performer to map it into the RFC model so it can work with the FIT GRPC: 1. It doesn't really have `ErrorContext` in the same way. Instead it has `KeyValueError`, `QueryError` et al., which perform a similar purpose to `ErrorContext`. 2. It doesn't have a base `CouchbaseException` error. Errors don't derive from `CouchbaseException`, and generic errors that would be just a `CouchbaseException` in another SDK, become a `KeyValueError`, `QueryError` etc. (Assuming the error did originate from the SDK.) We accommodate (2)) in the FIT model by having the Go performer check for all specific exceptions first with e.g. `errors.Is(err, ErrTimeout)`. If these all fail, it then checks if the error is a `QueryError` etc. with `errors.As()`. If one of those succeeds, it's regarded as a generic CouchbaseException. If all those checks fail, the error is classified as `ExceptionOther`. (1) is accommodated by just converted `QueryError` et al. into a serialized `ErrorContext`-esque string, as they are serving very similar purposes.
Used in:
Key-value
Query
Analytics
View
Management
Used as request type in: PerformerService.setCounter
Used as field type in: ,
Each counter gets a unique id (unique to the WorkloadRunRequest, not globally unique). The performer will create these on-demand. Each counter is bound to a WorkloadRunRequest. E.g. concurrent WorkloadRunRequests both referencing "counter1" should have separate isolated counters.
We may need the flexibility to do various forms of counter, e.g.: 1. Aim to do 1m operations across all threads. 2. Each thread does 1m operations. (1) is the simplest and most useful, so is the only one supported for now. And `counterId` lets us do (2) with it anyway.
Used in:
The performer should initialise the counter at this value, and will generally keep going until the counter reaches 0
Used as request type in: PerformerService.disconnectConnections
(message has no fields)
Used as response type in: PerformerService.disconnectConnections
(message has no fields)
Used in: , , , , , , , , , , , , , , , , , , , , , , , , ,
The performer will pick a document from a pool. The performer should generate an integer in [0-poolSize) following selectionStrategy. Then append that to `idPreface` e.g. "${idPreface}${selectedInt}" to get the document id.
Used in:
All documents in the pool start with this.
How many documents are in the pool.
The performer will access the document in this exact location
Used in:
The performer will generate a random UUID for the document id
Used in:
Used in: , , , , ,
Awkward name as Durability already taken
Used in: , , , , , , , ,
Request that the performer Echo a string to the performer logs.
Used as request type in: fit.columnar.ColumnarService.Echo, PerformerService.echo
Used as response type in: fit.columnar.ColumnarService.Echo, PerformerService.echo
(message has no fields)
Used in: , , , ,
If the exception is not represented in SdkException, can return it in raw form here
Used in:
The simple name e.g. "InvalidArgumentException"
Broadly this is the result of outputting the exception. E.g. for Java `ex.toString()`.
Used in: , , , , , , , , ,
The document will expire after the given duration.
The document will expire at a specific time. Given in epoch time.
The performer will run the bounded item until this much time has elapsed.
Used in:
* CustomSerializer defines different serialization strategies using a `oneof`. Currently, it includes a boolean option but is designed to be extended with other serialization methods in the future.
Used in:
Explicitly use the SDK's default JsonSerializer (See https://github.com/couchbaselabs/sdk-rfcs/blob/master/rfc/0055-serializers-transcoders.md#default-jsonserializer) If the SDK does not have this concept, then it can instead not provide any serializer for this operation - which is expected to have the same effect.
* **Custom Serializer** Uses a custom `JsonSerializer` implementation with specific serialization and deserialization logic. **Serialization Logic:** ```java public byte[] serialize(Object input) { // Convert the input object to a JSON string String jsonString = convertObjectToJsonString(input); // Create a JSON object from the string JsonObject jsonObject = parseStringToJsonObject(jsonString); // Add the "Serialized": true field jsonObject.put("Serialized", true); // Convert the JSON object to a byte array and return return convertJsonObjectToByteArray(jsonObject); } ``` **Deserialization Logic:** ```java public <T> T deserialize(Class<T> target, byte[] input) { // Parse the byte array into a JSON object JsonObject jsonObject = parseByteArrayToJsonObject(input); // Upsert the "Serialized" field to false, "Serialized" key may or may not present while deserializing. jsonObject.put("Serialized", false); // Convert the JSON object back to the target type and return return convertJsonObjectToTargetType(jsonObject, target); } ``` **Implementation Details:** - **`convertObjectToJsonString(Object input)`**: - Converts the input object to its JSON string representation. - **`parseStringToJsonObject(String jsonString)`**: - Parses the JSON string into a `JsonObject`. - **`convertJsonObjectToByteArray(JsonObject jsonObject)`**: - Serializes the `JsonObject` into a byte array. - **`parseByteArrayToJsonObject(byte[] input)`**: - Deserializes the byte array back into a `JsonObject`. - **`convertJsonObjectToTargetType(JsonObject jsonObject, Class<T> target)`**: - Converts the `JsonObject` to the specified target type `T`. **Notes for Performers:** - Implementations in other languages should follow the same logical steps using equivalent constructs. - Ensure that the `"Serialized"` flag is appropriately set during serialization and deserialization to track the state. - Proper error handling should be included to manage serialization/deserialization exceptions.
Used in:
(message has no fields)
Note these latches don't work like real CountdownLatches (or equivalent). Each concurrent transaction gets its own version of the latch, and they are synchronized by the driver. Latches are bound to the rpc they are created in. E.g. it should be possible to have two concurrent `transactionStream` rpcs going on, each using the same latch name, but referring to two separate underlying CountdownLatches (or equivalents).
Used in:
Used in:
(message has no fields)
Used in: , ,
Used in: , , , ,
This is a short really, but GRPC doesn't have int16
Used in:
Used in:
Generate a random id in [0-poolSize).
Used in:
Use a counter to select the next document in the pool, starting at 0. The performer should increment the counter each time it uses it. The performer should modulo `poolSize`. E.g. `realCounterResult = currentCounterValue % poolSize`.
Used in:
Used in:
Used in:
(message has no fields)
Used in:
(message has no fields)
Used in:
(message has no fields)
Zone Aware Read from Replica options
Used in: , , ,
Used in:
Used in: , , , ,
Used in: ,
Empty but included anyway per GRPC best practices.
Used as response type in: PerformerService.setCounter
(message has no fields)
Used in:
Whether to run the lost cleanup thread(s).
Whether to run the cleanup thread cleaning up attempts from this client.
Length of the lost cleanup window, in millis.
Additional collections to add to the cleanup set. Can be ignored if not ExtSDKIntegration.
Options that can be overridden at the individual transaction level. Note that pre-ExtSDKIntegration, this struct was empty. Not in the implementation, where PerTransactionConfig existed, but here at the FIT level. So, it will only be populated for ExtSDKIntegration performers.
Used in: ,
Durability to use for all mutating KV operations, both in cleanup and all transactions initiated.
Timeout (nee expirationTime) for all transactions.
Used in:
All the transcoders required by https://github.com/couchbaselabs/sdk-rfcs/blob/master/rfc/0055-serializers-transcoders.md
Used in: , , , , , , , , , , , , ,