Skip to content

Commit c6aa5fd

Browse files
authored
Merge pull request #18 from dgraph-io/readonly/besteffort
Needed for Ratel #104 - Added readOnly and bestEffort options to query
2 parents 90b4ce3 + 619cbb4 commit c6aa5fd

File tree

12 files changed

+107
-31
lines changed

12 files changed

+107
-31
lines changed

README.md

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,21 @@ and understand how to run and work with Dgraph.
1414

1515
## Table of contents
1616

17-
- [Install](#install)
18-
- [Quickstart](#quickstart)
19-
- [Using a client](#using-a-client)
20-
- [Create a client](#create-a-client)
21-
- [Alter the database](#alter-the-database)
22-
- [Create a transaction](#create-a-transaction)
23-
- [Run a mutation](#run-a-mutation)
24-
- [Run a query](#run-a-query)
25-
- [Commit a transaction](#commit-a-transaction)
26-
- [Check request latency](#check-request-latency)
27-
- [Debug mode](#debug-mode)
28-
- [Development](#development)
29-
- [Building the source](#building-the-source)
30-
- [Running tests](#running-tests)
17+
- [Install](#install)
18+
- [Quickstart](#quickstart)
19+
- [Using a client](#using-a-client)
20+
- [Create a client](#create-a-client)
21+
- [Login into Dgraph](#login-into-dgraph)
22+
- [Alter the database](#alter-the-database)
23+
- [Create a transaction](#create-a-transaction)
24+
- [Run a mutation](#run-a-mutation)
25+
- [Run a query](#run-a-query)
26+
- [Commit a transaction](#commit-a-transaction)
27+
- [Check request latency](#check-request-latency)
28+
- [Debug mode](#debug-mode)
29+
- [Development](#development)
30+
- [Building the source](#building-the-source)
31+
- [Running tests](#running-tests)
3132

3233
## Install
3334

@@ -148,6 +149,16 @@ try {
148149
}
149150
```
150151

152+
You can make queries read-only and best effort by passing ```options``` to ```DgraphClient#newTxn```. For example:
153+
154+
```js
155+
const options = { readOnly: true, bestEffort: true };
156+
const res = await dgraphClient.newTxn(options).query(query);
157+
```
158+
159+
Read-only transactions are useful to increase read speed because they can circumvent the usual consensus protocol. Best effort queries can also increase read speed in read bound system. Please note that best effort requires readonly.
160+
161+
151162
### Run a mutation
152163

153164
`Txn#mutate(Mutation)` runs a mutation. It takes in a `Mutation` object, which
@@ -182,6 +193,7 @@ mutation must be immediately committed.
182193
await txn.mutate({ setJson: p, commitNow: true });
183194
```
184195

196+
185197
### Run a query
186198

187199
You can run a query by calling `Txn#query(string)`. You will need to pass in a
@@ -229,6 +241,7 @@ Number of people named "Alice": 1
229241
Alice
230242
```
231243

244+
232245
### Commit a transaction
233246

234247
A transaction can be committed using the `Txn#commit()` method. If your transaction

lib/client.d.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { DgraphClientStub } from "./clientStub";
22
import { Txn } from "./txn";
3-
import { Operation, Payload, UiKeywords } from "./types";
3+
import { Operation, Payload, UiKeywords, TxnOptions } from "./types";
44
export declare class DgraphClient {
55
private readonly clients;
66
private debugMode;
@@ -11,7 +11,7 @@ export declare class DgraphClient {
1111
alter(op: Operation): Promise<Payload>;
1212
login(userid: string, password: string): Promise<boolean>;
1313
logout(): void;
14-
newTxn(): Txn;
14+
newTxn(options?: TxnOptions): Txn;
1515
setDebugMode(mode?: boolean): void;
1616
fetchUiKeywords(): Promise<UiKeywords>;
1717
debug(msg: string): void;

lib/client.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
"use strict";
22
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
34
return new (P || (P = Promise))(function (resolve, reject) {
45
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
56
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6-
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
7+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
78
step((generator = generator.apply(thisArg, _arguments || [])).next());
89
});
910
};
@@ -82,8 +83,8 @@ var DgraphClient = (function () {
8283
this.debug("Logout");
8384
this.clients.forEach(function (c) { return c.logout(); });
8485
};
85-
DgraphClient.prototype.newTxn = function () {
86-
return new txn_1.Txn(this);
86+
DgraphClient.prototype.newTxn = function (options) {
87+
return new txn_1.Txn(this, options);
8788
};
8889
DgraphClient.prototype.setDebugMode = function (mode) {
8990
if (mode === void 0) { mode = true; }

lib/clientStub.js

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,11 @@ var __assign = (this && this.__assign) || function () {
1111
return __assign.apply(this, arguments);
1212
};
1313
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
14+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
1415
return new (P || (P = Promise))(function (resolve, reject) {
1516
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
1617
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
17-
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
18+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
1819
step((generator = generator.apply(thisArg, _arguments || [])).next());
1920
});
2021
};
@@ -139,6 +140,18 @@ var DgraphClientStub = (function () {
139140
value: "true",
140141
});
141142
}
143+
if (req.readOnly) {
144+
params.push({
145+
key: "ro",
146+
value: "true",
147+
});
148+
}
149+
if (req.bestEffort) {
150+
params.push({
151+
key: "be",
152+
value: "true",
153+
});
154+
}
142155
if (params.length > 0) {
143156
url += "?";
144157
url += params.map(function (_a) {
@@ -258,7 +271,7 @@ var DgraphClientStub = (function () {
258271
version: "1.0.x",
259272
}];
260273
}
261-
return [2, __assign({}, JSON.parse(text), { health: "OK" })];
274+
return [2, __assign(__assign({}, JSON.parse(text)), { health: "OK" })];
262275
}
263276
});
264277
});

lib/txn.d.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { DgraphClient } from "./client";
2-
import { Assigned, Mutation, Response } from "./types";
2+
import { Assigned, Mutation, Response, TxnOptions } from "./types";
33
export declare class Txn {
44
private readonly dc;
55
private readonly ctx;
66
private finished;
77
private mutated;
8-
constructor(dc: DgraphClient);
8+
constructor(dc: DgraphClient, options?: TxnOptions);
99
query(q: string, options?: {
1010
debug?: boolean;
1111
}): Promise<Response>;

lib/txn.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
"use strict";
22
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
34
return new (P || (P = Promise))(function (resolve, reject) {
45
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
56
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6-
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
7+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
78
step((generator = generator.apply(thisArg, _arguments || [])).next());
89
});
910
};
@@ -38,14 +39,20 @@ Object.defineProperty(exports, "__esModule", { value: true });
3839
var errors_1 = require("./errors");
3940
var util_1 = require("./util");
4041
var Txn = (function () {
41-
function Txn(dc) {
42+
function Txn(dc, options) {
4243
this.finished = false;
4344
this.mutated = false;
4445
this.dc = dc;
46+
if (options && options.bestEffort && !options.readOnly) {
47+
this.dc.debug('Best effort only works with read-only queries.');
48+
throw errors_1.ERR_ABORTED;
49+
}
4550
this.ctx = {
4651
start_ts: 0,
4752
keys: [],
4853
preds: [],
54+
readOnly: options && options.readOnly,
55+
bestEffort: options && options.bestEffort
4956
};
5057
}
5158
Txn.prototype.query = function (q, options) {
@@ -67,6 +74,8 @@ var Txn = (function () {
6774
startTs: this.ctx.start_ts,
6875
timeout: this.dc.getQueryTimeout(),
6976
debug: options.debug,
77+
readOnly: this.ctx.readOnly,
78+
bestEffort: this.ctx.bestEffort
7079
};
7180
if (vars !== undefined) {
7281
varsObj_1 = {};

lib/types.d.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ export interface Request {
1414
startTs?: number;
1515
timeout?: number;
1616
debug?: boolean;
17+
readOnly?: boolean;
18+
bestEffort?: boolean;
1719
}
1820
export interface Response {
1921
data: {};
@@ -59,9 +61,15 @@ export interface TxnContext {
5961
aborted?: boolean | null;
6062
keys?: string[] | null;
6163
preds?: string[] | null;
64+
readOnly: boolean;
65+
bestEffort: boolean;
6266
}
6367
export interface Latency {
6468
parsing_ns?: number | null;
6569
processing_ns?: number | null;
6670
encoding_ns?: number | null;
6771
}
72+
export interface TxnOptions {
73+
readOnly?: boolean;
74+
bestEffort?: boolean;
75+
}

src/client.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { DgraphClientStub } from "./clientStub";
22
import { ERR_NO_CLIENTS } from "./errors";
33
import { Txn } from "./txn";
4-
import { Operation, Payload, UiKeywords } from "./types";
4+
import { Operation, Payload, UiKeywords, TxnOptions } from "./types";
55
import { stringifyMessage } from "./util";
66

77
/**
@@ -76,8 +76,8 @@ export class DgraphClient {
7676
/**
7777
* newTxn creates a new transaction.
7878
*/
79-
public newTxn(): Txn {
80-
return new Txn(this);
79+
public newTxn(options?: TxnOptions): Txn {
80+
return new Txn(this, options);
8181
}
8282

8383
/**

src/clientStub.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,18 @@ export class DgraphClientStub {
109109
value: "true",
110110
});
111111
}
112+
if (req.readOnly) {
113+
params.push({
114+
key: "ro",
115+
value: "true",
116+
});
117+
}
118+
if (req.bestEffort) {
119+
params.push({
120+
key: "be",
121+
value: "true",
122+
});
123+
}
112124
if (params.length > 0) {
113125
url += "?";
114126
url += params.map(

src/errors.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
export const ERR_NO_CLIENTS = new Error("No clients provided in DgraphClient constructor");
22
export const ERR_FINISHED = new Error("Transaction has already been committed or discarded");
33
export const ERR_ABORTED = new Error("Transaction has been aborted. Please retry");
4+
export const ERR_BEST_EFFORT_REQUIRED_READ_ONLY = new Error("Best effort only works for read-only queries");
45

56
/**
67
* CustomError is base class used for defining custom error classes.

0 commit comments

Comments
 (0)