gRPC API
ArcadeDB exposes a gRPC interface for high-performance, strongly-typed access from any language with gRPC support (Java, Python, Go, C++, Node.js, Rust, C#, and more). The gRPC API provides two services with 67 RPCs covering queries, record operations, transactions, graph bulk loading, vector and full-text search, time series, and server administration.
Proto definition: arcadedb-server.proto
Enabling the gRPC server
The gRPC module is bundled in the full distribution, but the server is implemented as a plugin (com.arcadedb.server.grpc.GrpcServerPlugin) that is not started by default. If the server is not listening on any gRPC port, it is because the plugin has not been registered yet.
Enable it by adding the plugin to the arcadedb.server.plugins setting, then start the server:
-Darcadedb.server.plugins=gRPC:com.arcadedb.server.grpc.GrpcServerPlugin
The format is <pluginName>:<pluginFullClass> (comma-separated when registering several plugins). Once enabled, the server listens on port 50051 by default. Confirm it started by looking for a gRPC server started line in the server log, or with grpcurl -plaintext localhost:50051 list.
Host, port, TLS, message size and the other gRPC options are the arcadedb.grpc.* settings - see gRPC settings for the full list. Since v26.10.2 every one of them is a registered server setting, read like arcadedb.server.plugins from the server configuration file, from environment variables and from JVM system properties (-Darcadedb.grpc.*). In v26.10.1 and earlier only arcadedb.grpc.port was; the others were read as JVM system properties only, so a grpc.tls.enabled written in the configuration file was ignored.
(Since v26.10.2.) arcadedb.grpc.host binds the standard gRPC server to every local address the name resolves to (in v26.10.1 and earlier
it was read but never applied, so the server listened on every interface); the xDS server (grpc.mode xds or
both) has no host setting and still listens on every interface.
Services
ArcadeDbService
The main service for database operations: querying, record CRUD, bulk inserts, transactions, graph bulk loading, search, and time series.
| RPC | Request | Response | Description |
|---|---|---|---|
|
|
stream |
Execute a query and stream results back row by row |
|
|
|
Execute a DDL/DML command (CREATE, INSERT, UPDATE, DELETE) |
|
|
|
Execute a query and return all results at once |
|
|
|
Create a new record (vertex, edge, or document) |
|
|
|
Update an existing record by RID |
|
|
|
Look up a record by its Record ID |
|
|
|
Delete a record by RID |
|
|
|
Insert multiple records in a single request |
|
stream |
|
Client-streaming insert for large datasets |
|
stream |
stream |
Bidirectional streaming for insert with per-record feedback |
|
|
|
Begin an explicit transaction |
|
|
|
Commit the current transaction |
|
|
|
Roll back the current transaction |
|
stream |
|
Client-streaming bulk load of vertices and edges (see below) |
|
|
|
Since 26.10.1. k-nearest-neighbor search over a dense or sparse vector index |
|
|
|
Since 26.10.1. Fused vector, full-text, and graph-expansion search |
|
|
|
Since 26.10.1. Lucene-syntax search over a |
|
|
|
Since 26.10.1. Write a batch of time-series points |
|
stream |
|
Since 26.10.1. Client-streaming time-series ingest |
|
|
stream |
Since 26.10.1. Range query, raw or aggregated into buckets, streamed back |
|
|
|
Since 26.10.1. Latest sample of a time-series type, optionally filtered by tags |
A record that a BeforeRecordCreateListener or a BeforeRecordUpdateListener vetoed was refused on purpose, and the replies say so
instead of reporting it as written. The bulk inserts (BulkInsert, InsertStream, InsertBidirectional) count it as ignored, and a
vetoed update under CONFLICT_UPDATE does not insert a second record for the key. UpdateRecord answers success = false and
updated = false, which is what the drivers return to the caller as "the record was updated". CreateRecord has to answer a RID, so
it fails with INVALID_ARGUMENT naming the refusal.
Before v26.11.1 UpdateRecord answered success = true and updated = true for an update a listener vetoed, and CreateRecord
of a vetoed edge failed with INTERNAL carrying the text of a NullPointerException.
|
Graph batch load
GraphBatchLoad streams GraphBatchChunk messages, each carrying GraphBatchRecord entries of kind VERTEX or
EDGE. The first chunk must name the database and carry the GraphBatchOptions (batch size, light edges, WAL,
commit frequency, vertex_batch_size, commit retries, and return_id_mapping); options on later chunks are ignored.
Vertices declare a temp_id, and edges reference their endpoints by temp_id or by an existing RID (#bucket:pos)
in from_ref / to_ref. All VERTEX records must precede every EDGE record across the whole stream: interleaving
is an error. On a replicated cluster the load must run on the leader; a follower refuses it.
GraphBatchResult reports vertices_created, edges_created, elapsed_ms and, depending on return_id_mapping,
the temp_id to RID map in id_mapping (when the map is not returned, id_mapping_omitted is set and
id_mapping_size still reports its size). The load commits incrementally, so a failure is not a rollback: the counts
already durable at the point of failure travel in the arcadedb-graph-batch-result-bin trailer of the failed call,
with partial_commit set.
Vector, hybrid, and full-text search
Since 26.10.1. These three unary RPCs run the same server-side implementation as the HTTP /api/v1/vector/*
routes and the MCP search tools, so a request that is legal on one protocol is legal on all of them and is rejected
with the same message. Every hit is a SearchHit with rid, record, and either distance (dense index, lower is
better) or score (sparse, full-text, or fused, higher is better); the response’s scoring field says which.
The hit’s record properties are encoded like the values of a query result, so a list, set or array property is a
list_value and an embedded map is a map_value (since 26.11.1).
| RPC | Key request fields |
|---|---|
|
|
|
The vector fields above ( |
|
|
All three accept an optional transaction: when it names a live transaction the search reads exactly what that
transaction reads, including its uncommitted changes. A transaction id the server no longer knows is refused with
FAILED_PRECONDITION. See also Full-text index.
Time series
Since 26.10.1. The time-series RPCs read and write TIMESERIES types (see Time series).
-
TimeSeriesWrite/TimeSeriesWriteStream: eachTimeSeriesPointcarriestype(the measurement, defaulting to the request or chunktype),timestamp, andtags/fieldsmaps ofGrpcValue.precisiondefaults toTS_PRECISION_MILLISECONDS(unlike the HTTP line-protocol endpoint, which defaults to nanoseconds). The streaming variant needsdatabaseon the first chunk only and applies back-pressure, pulling one chunk at a time. A write is not atomic: each measurement’s batch commits as it is appended.TimeSeriesWriteSummaryreportsreceived,written, anddropped(written + dropped == received), and lists dropped points' types underunknown_types,non_time_series_types, orunavailable_types. (Since v26.10.2.)undeclared_keys(field 8) lists, as<measurement>.<key> (tag|field), the tag or field keys a measurement’sTIMESERIEStype does not declare in that role: the points carrying them are dropped unless the database setsarcadedb.timeSeriesUndeclaredKeys=ignore.unreadable_values(field 9) lists, as<measurement>.<column> (tag|field): <reason>, values a column cannot store. Both lists are capped at 100 entries, whiledroppedstill counts every point. The HTTP line-protocol endpoint reports the same lists asundeclaredKeysandunreadableValuesin its400partial-write body, described by theTimeSeriesWriteErrorschema of the OpenAPI definition. -
TimeSeriesQuery:type, inclusivefrom_timestamp/to_timestamp(unset means unbounded),fieldsprojection (an unknown name is refused withINVALID_ARGUMENT),tags(TimeSeriesTagFilter, a conjunction of equality predicates on TAG columns; a non-TAG name is refused withINVALID_ARGUMENT),limit,batch_size(rows per streamed message, default 1000), and optionalaggregation(bucket_interval_ms> 0, at least oneTimeSeriesAggregationRequestofTS_AGG_SUM,AVG,MIN,MAXorCOUNT, and an optionalbucket_origin_ms). The answer streams asTimeSeriesQueryResultmessages carryingrows(raw) orbuckets(aggregated); the last message haslastset, andtruncatedwhen the limit cut the answer short. The server-side ceilingarcadedb.server.grpcTimeSeriesMaxResultRows(default 1000000) cannot be raised by the client: alimitabove it is refused withRESOURCE_EXHAUSTEDbefore the first message. -
TimeSeriesLatest:typeand optionaltags.TimeSeriesLatestResponsereturnscolumns,found, and thelatestrow (unset whenfoundisfalse).
TimeSeriesQuery and TimeSeriesLatest accept an optional transaction; when set, the read sees that
transaction’s uncommitted points. An unresolvable transaction id is refused with FAILED_PRECONDITION (the HTTP
time-series read routes instead fall back to reading outside the transaction).
ArcadeDbAdminService
Administration service for server and database management. Every admin RPC runs the same implementation as the HTTP control plane, so the two protocols behave the same way.
Authentication and authorization. Every request is authenticated from its credentials field, except Health
and Ready, which are unauthenticated like GET /api/v1/health and GET /api/v1/ready. Ping, GetServerInfo,
ListDatabases, ExistsDatabase, and GetDatabaseInfo need any valid account; GetProgress needs an account
granted the named database; every other RPC requires the root user and otherwise fails with PERMISSION_DENIED.
Leader routing. On a replicated cluster, CreateDatabase, DropDatabase, CreateUser, UpdateUser,
DeleteUser, SaveGroup, DeleteGroup, CreateApiToken, DeleteApiToken, RestoreBackup, RestoreDatabase,
and ImportDatabase are refused on a follower with FAILED_PRECONDITION and the leader’s address in the
arcadedb-leader-* trailers. gRPC has no request proxy, so the client redirects itself. (Since v26.10.2.) The
streaming inserts of ArcadeDbService (InsertStream and InsertBidirectional, and the rows of a BulkInsert)
report a write a follower refused differently: the refused row or commit comes back as an InsertError with code
NOT_LEADER and the leader’s address in leader_address, rather than through the arcadedb-leader-* trailers (see
Insert operations).
Server info and databases
| RPC | Request | Response | Description |
|---|---|---|---|
|
|
|
Health check |
|
|
|
Server version, uptime, and configuration |
|
|
|
List all databases |
|
|
|
Check if a database exists |
|
|
|
Create a new database (see below) |
|
|
|
Drop an existing database (see below) |
|
|
|
Since 26.10.1. Open the named database |
|
|
|
Since 26.10.1. Close the named database’s open instance; the files stay, and a later request reopens it |
|
|
|
Since 26.10.1. Run |
|
|
|
Schema, types, and database statistics |
|
|
|
Since 26.10.1. Long-running operations (CHECK DATABASE, REBUILD INDEX, backup, import, …) running on the database, as |
GetDatabaseInfoResponse.records is the sum of the record counts of the database’s types, read from the bucket counters
rather than by a scan. (Since v26.11.1) a type whose records cannot be counted - a time series type whose storage engine
did not open, for one - is named in uncounted_types and left out of the sum, so a non-empty list says the total is short
by an unknown amount rather than that the database holds fewer records; and a schema that cannot be read fails the call
instead of answering zero classes (issue #10877).
CreateDatabase and DropDatabase answer the no-op case the way the HTTP create database and drop database
commands do: a name already taken is refused with ALREADY_EXISTS, a name that does not exist with NOT_FOUND.
Set if_not_exists on CreateDatabaseRequest, or if_exists on DropDatabaseRequest, to make the call idempotent
instead. Either way the response says what happened: CreateDatabaseResponse.created is true only when this call
created the database, and DropDatabaseResponse.dropped only when it dropped one, so a provisioning tool can tell
"created for me" from "already there" rather than reading an empty OK as ownership. Database names are exact and
never case-folded. The Java client exposes the two forms as createDatabase / createDatabaseIfMissing and
dropDatabase / dropDatabaseIfExists; the IfMissing / IfExists variants return the boolean.
(Since v26.11.1) ListDatabases, ExistsDatabase, GetDatabaseInfo, CreateDatabase with if_not_exists and DropDatabase with
if_exists see the databases that are on disk but not open (closed for idleness, or not opened at startup because
arcadedb.server.databaseLoadAtStartup is false) as existing, since the first request that names one opens it. Before, they answered
as if such a database did not exist. A database closed with the close database server command, being restored or being dropped is still not listed. See
Databases on disk that are not open.
(Since v26.12.1, issue #11310) A database closed with the close database server command, being restored or being dropped exists
for ExistsDatabase, CreateDatabase and DropDatabase too: ExistsDatabase answers true, CreateDatabase with if_not_exists
answers created=false (and without it ALREADY_EXISTS), DropDatabase drops a database closed with close database and refuses
one a restore or a drop holds with ABORTED and the reason, and GetDatabaseInfo answers UNAVAILABLE with the reason rather than
NOT_FOUND. Before, they answered as if it did not exist: DropDatabase with if_exists answered dropped=false and left the
database on disk, while CreateDatabase with if_not_exists failed ALREADY_EXISTS.
Users, groups, and API tokens
| RPC | Request | Response | Description |
|---|---|---|---|
|
|
|
Create a new user. A name already taken is |
|
|
|
Since 26.10.1. Update a user’s |
|
|
|
Delete a user |
|
|
|
Since 26.10.1. List users with their per-database groups. Password hashes are never included |
|
|
|
Since 26.10.1. The whole group document, as JSON in |
|
|
|
Since 26.10.1. Create or replace one group of a database ( |
|
|
|
Since 26.10.1. Delete one group of a database |
|
|
|
Since 26.10.1. List API tokens as |
|
|
|
Since 26.10.1. Mint an API token. The plaintext |
|
|
|
Since 26.10.1. Revoke a token by its |
Settings
| RPC | Request | Response | Description |
|---|---|---|---|
|
|
|
Since 26.10.1. Set a server setting. |
|
|
|
Since 26.10.1. Set a setting of one database |
Backup, restore, and import
| RPC | Request | Response | Description |
|---|---|---|---|
|
|
|
Since 26.10.1. Auto-backup configuration as JSON, and whether the auto-backup plugin is running |
|
|
|
Since 26.10.1. Save the auto-backup configuration from |
|
|
|
Since 26.10.1. Backup archives of a database, with retention totals |
|
|
|
Since 26.10.1. Back up a database now; returns the archive path |
|
|
|
Since 26.10.1. Delete one archive by plain file name (path separators and traversal are refused) |
|
|
stream |
Since 26.10.1. Restore a database’s backup archive into |
|
|
stream |
Since 26.10.1. Create a new database from an archive at a |
|
|
stream |
Since 26.10.1. Create a new database and import the source at a |
The three restore and import RPCs are server-streaming: they send progress messages while the operation runs, then
one final message with completed = true (ImportProgress.result_json carries the importer’s final report). A
failure ends the stream with an error status instead. Cancelling the call stops the progress messages, not the
operation. Unless arcadedb.server.restoreImportAllowLocalUrls is enabled, only http/https URLs to non-private
hosts are accepted. See also Backup.
Query profiler
| RPC | Request | Response | Description |
|---|---|---|---|
|
|
|
Since 26.10.1. Start recording. |
|
|
|
Since 26.10.1. Stop recording and return the run as JSON |
|
|
|
Since 26.10.1. Reset the profiler |
|
|
|
Since 26.10.1. Current profiler results as JSON, without stopping |
|
|
|
Since 26.10.1. Saved profiler runs on disk, newest first |
|
|
|
Since 26.10.1. Load a saved run by file name |
Server lifecycle and cluster
| RPC | Request | Response | Description |
|---|---|---|---|
|
|
|
Since 26.10.1. Server events as a JSON array, from the current event file or a named one, plus the list of event files |
|
|
|
Since 26.10.1. Shut down this server (empty |
|
|
|
Since 26.10.1. Disconnect this server from the cluster. |
|
|
|
Since 26.10.2. Root only. Lifts the quarantine, and its read floor, standing on |
|
|
|
Since 26.10.2. Root only. Lifts the node-wide stale-snapshot read floor of a node that is the only voter of its cluster, accepting its databases as they are without a resync. The response carries |
|
|
|
Since 26.10.1. Join the server at |
|
|
|
Since 26.10.1. Open HTTP authentication sessions, including their bearer tokens. Enable TLS before calling it across an untrusted network |
Health probes
| RPC | Request | Response | Description |
|---|---|---|---|
|
|
|
Since 26.10.1. Unauthenticated liveness probe; |
|
|
|
Since 26.10.1. Unauthenticated readiness probe; a not-ready node answers |
Error statuses
A refused admin call answers the status of the refusal whatever the server wrapped it in on its way out: a name
already taken is ALREADY_EXISTS, a user, group or token that does not exist NOT_FOUND, a security policy
refusing an argument PERMISSION_DENIED, failed authentication UNAUTHENTICATED, a backup, restore or import
already running on the database ABORTED, a malformed argument INVALID_ARGUMENT, an operation this server’s
configuration does not support FAILED_PRECONDITION, and a transient failure such as a Raft quorum not reached
UNAVAILABLE, which a client retries. The description is the refusal’s own sentence, also in production mode, except
for a generic argument, authentication or retry failure raised underneath another error: that one keeps its status
but its text is concealed in production mode, because it may come from a library and carry internal details. A
statement stopped on request is CANCELLED, as on the data-plane RPCs (see Cancellation).
Only an unexpected server fault is INTERNAL, and in production mode its description is concealed.
On the data-plane RPCs, the arcadedb-exception-class trailer names the exception that decided the status rather
than the one wrapped around it, so the Java client rebuilds the engine’s own type: a SchemaException for a missing
type (not the RecordNotFoundException that NOT_FOUND alone reads as), or a DuplicatedKeyException carrying its
index name.
(Since v26.11.1) A command that creates, or renames onto, a schema object name already taken (a type, property, index, bucket, view,
…) answers ALREADY_EXISTS, with the arcadedb-already-exists-kind trailer naming the kind. The Java client rebuilds it as
AlreadyExistsException, a SchemaException. Before, it was INTERNAL, or NOT_FOUND for some of them. The admin RPCs answer
a taken user, token or database name as before, and the Java client raises RemoteAlreadyExistsException for it on every admin
call, ImportDatabase included.
|
In v26.10.2 and earlier, only the leader-redirect refusal was recognised under a wrapper. Any other refusal the
server raised under one (for example inside a commit or a backup) answered |
Cancellation and running statements
Since 26.10.2. The ArcadeDbService RPCs (such as ExecuteQuery, ExecuteCommand, StreamQuery, BulkInsert,
the search RPCs and TimeSeriesQuery, but not BeginTransaction and RollbackTransaction) are listed, while they
run, by the HTTP list queries server command and by Cypher
SHOW TRANSACTIONS, with protocol grpc, and can be stopped by terminate query,
TERMINATE TRANSACTIONS or Studio. A BulkInsert stops between two rows.
The client-streaming loads (InsertStream, InsertBidirectional, GraphBatchLoad and TimeSeriesWriteStream) are
listed from the first chunk, which names the database, to the end of the stream, including while the stream is idle
between two chunks, and terminate query stops them there too. A terminated load ends with status CANCELLED, and
what the load already wrote depends on its transaction mode:
-
PER_STREAMandPER_REQUEST: the open transaction is rolled back, so nothing the stream sent is committed. -
PER_BATCH: the open batch is rolled back; batches committed before the termination stay committed. -
PER_ROW: the rows committed before the termination stay, the rest are not applied. -
A load that writes into a client transaction (
BeginTransaction) rolls that transaction back and ends it. -
GraphBatchLoadcommits incrementally: what is already durable is reported in thearcadedb-graph-batch-result-bintrailer withpartial_commitset.TimeSeriesWriteStreamstops appending; batches already appended stay.
In v26.10.1 and earlier the client-streaming loads were not listed and could not be terminated.
A client that cancels a call, or whose deadline expires, or whose connection drops, terminates the server-side work too: the server stops it at its next check instead of running it to the end for an answer nobody reads.
A terminated call ends with status CANCELLED and the trailer arcadedb-exception-class set to
com.arcadedb.exception.QueryTerminatedException; the gRPC Java client raises that exception, which it does not retry.
A statement terminated inside a client-managed transaction (BeginTransaction) ends that transaction: it is rolled
back, and a later CommitTransaction answers committed = false.
Metrics
The gRPC server records three meters per RPC, exported with the other server meters (see Metrics depth):
| Meter | Tags | Meaning |
|---|---|---|
|
|
Calls received |
|
|
Time from the call to its close |
|
|
Calls that failed: closed with a status other than |
(Since v26.11.1) Authentication faults are visible. When the server cannot read the credentials of an admin request, or the security backend fails unexpectedly, the call still fails closed as UNAUTHENTICATED, but it is logged at SEVERE with the cause and the method name (before, at FINE, which the default level hides) and counted on the Micrometer counter grpc.auth.faults.total, tagged stage = admin-credential-read, authenticate or intercept. The counters are registered at zero. An unexpected failure inside the security backend answers "Authentication error: the server could not evaluate the credentials (server fault, see the server log)" on the data plane and the admin service, instead of "Invalid credentials"; a wrong password, a missing grant and a lockout answer as before. A linkage error such as NoClassDefFoundError during authentication is reported the same way.
(Since v26.11.1) grpc.errors.total counts every call closed with status OK whose response message declares a top-level boolean
success field and sends it false, such as an UpdateRecord or a DeleteRecord that a listener vetoed. Such a call is counted
with status OK. Before, only an ExecuteCommandResponse with success = false was counted, and the other in-band failures read
as successes (issue #11054).
Message Types
Connection & Authentication
|
Database name, username, and password for per-request authentication |
Value Types
The GrpcValue message uses a oneof to represent any ArcadeDB value:
| Field | ArcadeDB Type |
|---|---|
|
Boolean |
|
Integer |
|
Long |
|
Float |
|
Double |
|
String |
|
Binary / byte array |
|
Datetime (google.protobuf.Timestamp) |
|
List / array |
|
Map / embedded document |
|
RID reference (bucket:position) |
|
Decimal (string-encoded) |
|
Null |
A GrpcValue can also carry a logical_type tag that says which ArcadeDB type it stands for. A client that ignores the
tag still reads the plain string or timestamp.
logical_type |
Carried as |
|---|---|
|
|
|
|
|
|
|
|
Text tagged with one of these types that cannot be parsed is returned as a plain string.
GrpcRecord wraps a record with its RID, type name, and a map of property name to GrpcValue.
Enums
| Enum | Values |
|---|---|
|
|
|
|
|
|
|
|
|
|
BeginTransaction accepts READ_COMMITTED and REPEATABLE_READ, the two levels the engine provides, and
READ_UNCOMMITTED, which is the proto default and runs at the stronger READ_COMMITTED. The level the transaction really
runs at is returned in BeginTransactionResponse.effective_isolation. SERIALIZABLE is not supported: it is refused with
INVALID_ARGUMENT, as is a value the server does not know, instead of starting the transaction at a weaker level than the
one asked for (since v26.11.1). HTTP, SQL, openCypher and PostgreSQL refuse it the same way.
|
PAGED retrieval keeps the ORDER BY your query specifies. When the query specifies none, rows are ordered by
@rid, because cutting pages needs a stable order or a row could be skipped or repeated across pages. PAGED also
reserves the parameter names _skip and _limit, and applies to SQL only: a query in another language falls back to
CURSOR. If you order by a column with duplicate values, rows that tie can still move between pages, since every page
re-runs the query; add a unique tie-break such as ORDER BY createdAt DESC, @rid when pages must be reproducible.
|
Projected records
StreamQueryRequest, ExecuteQueryRequest and ExecuteCommandRequest accept an optional ProjectionSettings that says how a
record the query projects as a value is sent:
| Field | Meaning |
|---|---|
|
When |
|
|
|
A soft bound, in bytes, on the projected records of the request. Past it, the remaining properties of a record are left out (MAP), and a record whose JSON is larger is sent as its RID (JSON). Unset or |
A request without ProjectionSettings gets the records in JSON, with no limit.
(Since v26.11.1) A projected value that holds records - a graph traversal (SELECT out() AS n, and likewise in(), outE(),
inE(), both(), bothE()), a list, a map, an array or a nested result row - is encoded like a top-level projected record, with
the request’s ProjectionSettings, and soft_limit_bytes is one budget for the whole response, shared by every record, nested
ones included, in both MAP and JSON encoding. A traversal is a list_value, empty for a vertex with no edges. A nested result row
that wraps a record is sent as that record, @rid and @type included; if the row has columns of its own (a subquery that
projects only some properties, for instance), those columns are sent next to @rid and @type instead of the record’s
properties. This is what HTTP returns for the same query.
Before v26.11.1 out(), in(), outE() and inE() reached a gRPC client as a Java class name string, such as
com.arcadedb.graph.GraphEngine$10@63e44da5, and the records inside a list (both()) as bare RIDs whatever the
ProjectionSettings asked for (issues #11044, #11048).
|
Insert Operations
|
Batch of records with type name, properties, and insert options |
|
A chunk of records for client-streaming inserts |
|
Per-record request/response for bidirectional streaming |
|
Result summary: |
|
One failed row or commit, see below |
|
Transaction mode, conflict handling, and batch size configuration |
A row that cannot be applied does not fail the call: it is counted in failed and reported as an InsertError, and the
rest of the batch still goes in.
| Field | Number | Meaning |
|---|---|---|
|
1 |
The engine’s error text. In |
|
2 |
Index of the row within the chunk, or |
|
3 |
Machine-readable code, see below |
|
4 |
The offending field, when known |
|
5 |
Since 26.10.2. Set only when |
| Code | Meaning |
|---|---|
|
The row’s key is already taken ( |
|
Any other failure of one row or chunk |
|
Since 26.10.2. The node is a follower and refused the write; |
|
A transaction commit failed for a reason other than a duplicated key or a leader refusal |
|
The stream broke the protocol, for example its options changed mid-stream |
|
The chunk named a transaction id the server does not know or has expired |
|
|
|
An edge row has no |
Command Results & Write Statistics
ExecuteCommand returns an ExecuteCommandResponse:
| Field | Meaning |
|---|---|
|
Whether the command succeeded, and an optional message |
|
Server-computed count of affected elements and numeric scalars |
|
Server-side execution time |
|
Optional row payload, returned when |
|
A |
QueryUpdateStats carries the same write counters the HTTP stats object and the Bolt result summary expose, including counts aggregated across OpenCypher UNION branches and CALL { … } subqueries:
| Field | Meaning |
|---|---|
|
Vertices created / deleted |
|
Edges created / deleted |
|
Properties assigned a value |
|
Type/label memberships added / removed |
|
Indexes created / dropped |
|
Constraints added / removed |
|
|
The equivalent HTTP response object is documented at Write statistics.
Connecting from Python
import grpc
import arcadedb_server_pb2 as pb
import arcadedb_server_pb2_grpc as rpc
channel = grpc.insecure_channel('localhost:50051')
stub = rpc.ArcadeDbServiceStub(channel)
# Execute a query
request = pb.ExecuteQueryRequest(
credentials=pb.DatabaseCredentials(
database='mydb', username='root', password='arcadedb'
),
language='sql',
command='SELECT FROM V LIMIT 10',
)
response = stub.ExecuteQuery(request)
for record in response.records:
print(record)
Connecting from Node.js
const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');
const packageDef = protoLoader.loadSync('arcadedb-server.proto');
const proto = grpc.loadPackageDefinition(packageDef).arcadedb;
const client = new proto.ArcadeDbService(
'localhost:50051', grpc.credentials.createInsecure()
);
client.ExecuteQuery({
credentials: { database: 'mydb', username: 'root', password: 'arcadedb' },
language: 'sql',
command: 'SELECT FROM V LIMIT 10',
}, (err, response) => {
console.log(response.records);
});
Further Reading
-
HTTP/JSON API — Alternative REST-based access
-
PostgreSQL Protocol — Alternative wire protocol