Skip to content

Commit 291954b

Browse files
Added upsert tests (#67)
* Added upsert tests - Re-used the acctUpsert tests with doRequest - Added test for successful upsert
1 parent c2edddc commit 291954b

File tree

1 file changed

+287
-0
lines changed

1 file changed

+287
-0
lines changed

tests/integration/upsert.spec.ts

Lines changed: 287 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,287 @@
1+
import * as dgraph from "../../src";
2+
3+
import { setSchema, setup } from "../helper";
4+
5+
const concurrency = 3;
6+
const FIVE_MINUTES_IN_SECONDS = 5 * 60 * 1000; // 5 minutes in milliseconds
7+
8+
// tslint:disable-next-line no-string-based-set-timeout
9+
jest.setTimeout(FIVE_MINUTES_IN_SECONDS * 2);
10+
11+
let client: dgraph.DgraphClient;
12+
13+
const firsts = ["Paul", "Eric", "Jack", "John", "Martin"];
14+
const lasts = ["Brown", "Smith", "Robinson", "Waters", "Taylor"];
15+
const ages = [20, 25, 30, 35];
16+
17+
type Account = {
18+
first: string;
19+
last: string;
20+
age: number;
21+
};
22+
const accounts: Account[] = [];
23+
24+
firsts.forEach((first: string): void => lasts.forEach((last: string): void => ages.forEach((age: number): void => {
25+
accounts.push({
26+
first,
27+
last,
28+
age,
29+
});
30+
})));
31+
32+
async function tryUpsert(query: string, mutation: dgraph.Mutation, blankNodeLabel: string): Promise<void> {
33+
const txn = client.newTxn();
34+
35+
const req = new dgraph.Request();
36+
req.setQuery(query);
37+
req.setMutationsList([mutation]);
38+
req.setCommitNow(true);
39+
40+
let uid: string;
41+
try {
42+
// Update account only if matching uid found.
43+
const response = await txn.doRequest(req);
44+
uid = response.getUidsMap().get(blankNodeLabel);
45+
expect(uid).not.toEqual("");
46+
} finally {
47+
await txn.discard();
48+
}
49+
}
50+
51+
let startStatus = 0; // set at the start of doUpserts
52+
let lastStatus = 0;
53+
let cancelled = false; // cancelled due to timeout
54+
55+
let successCount = 0;
56+
let retryCount = 0;
57+
58+
function conditionalLog(): void {
59+
const now = new Date().getTime();
60+
if (now - lastStatus > 1000 && !cancelled) {
61+
// tslint:disable-next-line no-console
62+
console.log(`Success: ${successCount}, Retries: ${retryCount}, Total Time: ${now - startStatus} ms`);
63+
lastStatus = now;
64+
}
65+
}
66+
67+
async function upsert(account: Account): Promise<void> {
68+
let done = false;
69+
const query = `query {
70+
account as var(func: eq(first, "${account.first}")) @filter(eq(last, "${account.last}") AND eq(age, "${account.age}"))
71+
}`;
72+
const mu = new dgraph.Mutation();
73+
mu.setSetNquads(`
74+
uid(account) <first> "${account.first}" .
75+
uid(account) <last> "${account.last}" .
76+
uid(account) <age> "${account.age}"^^<xs:int> .
77+
`);
78+
const blankNodeLabel = `uid(account)`;
79+
while (!done && !cancelled) {
80+
try {
81+
await tryUpsert(query, mu, blankNodeLabel);
82+
successCount += 1;
83+
done = true;
84+
} catch (e) {
85+
expect(e).toBe(dgraph.ERR_ABORTED);
86+
retryCount += 1;
87+
}
88+
89+
conditionalLog();
90+
}
91+
92+
if (!done) {
93+
throw new Error(`Timeout elapsed: ${FIVE_MINUTES_IN_SECONDS / 1000}s`);
94+
}
95+
}
96+
97+
async function doUpserts(): Promise<void> {
98+
const promises: Promise<void>[] = [];
99+
for (const account of accounts) {
100+
for (let i = 0; i < concurrency; i += 1) {
101+
promises.push(upsert(account));
102+
}
103+
}
104+
105+
startStatus = new Date().getTime();
106+
const id = setTimeout(
107+
() => {
108+
cancelled = true;
109+
},
110+
FIVE_MINUTES_IN_SECONDS,
111+
);
112+
113+
await Promise.all(promises).then(() => {
114+
clearTimeout(id);
115+
});
116+
}
117+
118+
async function checkIntegrity(): Promise<void> {
119+
const res = await client.newTxn().query(`{
120+
all(func: anyofterms(first, "${firsts.join(" ")}")) {
121+
first
122+
last
123+
age
124+
}
125+
}`);
126+
127+
const data: {
128+
all: Account[];
129+
} = res.getJson(); // tslint:disable-line no-unsafe-any
130+
131+
const accountSet: { [key: string]: boolean } = {};
132+
for (const account of data.all) {
133+
expect(account.first).toBeTruthy();
134+
expect(account.last).toBeTruthy();
135+
expect(account.age).toBeTruthy();
136+
accountSet[`${account.first}_${account.last}_${account.age}`] = true; }
137+
138+
for (const account of accounts) {
139+
expect(accountSet[`${account.first}_${account.last}_${account.age}`]).toBe(true);
140+
}
141+
}
142+
143+
type Profile = {
144+
name: string;
145+
email: string;
146+
age: number;
147+
};
148+
const profiles: Profile[] = [
149+
{ name: "Alice", email: "[email protected]", age: 25 },
150+
{ name: "Bob", email: "[email protected]", age: 28 },
151+
{ name: "Prashant", email: "[email protected]", age: 23 },
152+
];
153+
const names: string[] = [];
154+
profiles.forEach((profile: Profile): void => {
155+
names.push(profile.name);
156+
});
157+
158+
async function doUpsert(): Promise<void> {
159+
await performMutation(profiles[0]);
160+
await performMutation(profiles[1]);
161+
await performMutation(profiles[2]);
162+
await checkMutationIntegrity();
163+
const updatedProfile: Profile = {
164+
name: "Prashant Shahi",
165+
166+
age: 24,
167+
};
168+
await performUpsert(updatedProfile);
169+
await checkUpsertIntegrity();
170+
}
171+
172+
async function performMutation(profile: Profile): Promise<void> {
173+
const txn = client.newTxn();
174+
const mu = new dgraph.Mutation();
175+
const blankNodeLabel = `_:${profile.name.toLocaleLowerCase()}`;
176+
177+
mu.setSetNquads(`
178+
${blankNodeLabel} <name> "${profile.name}" .
179+
${blankNodeLabel} <email> "${profile.email}" .
180+
${blankNodeLabel} <age> "${profile.age}"^^<xs:int> .
181+
`);
182+
183+
const ag = await txn.mutate(mu);
184+
await txn.commit();
185+
const uid = ag.getUidsMap().get(blankNodeLabel);
186+
expect(uid).not.toEqual("");
187+
}
188+
189+
async function performUpsert(profile: Profile): Promise<void> {
190+
const query = `query {
191+
profile as var(func: eq(email, "${profile.email}"))
192+
}`;
193+
const mu = new dgraph.Mutation();
194+
mu.setSetNquads(`
195+
uid(profile) <name> "${profile.name}" .
196+
uid(profile) <email> "${profile.email}" .
197+
uid(profile) <age> "${profile.age}"^^<xs:int> .
198+
`);
199+
const blankNodeLabel = `uid(profile)`;
200+
201+
await tryUpsert(query, mu, blankNodeLabel);
202+
}
203+
204+
async function checkMutationIntegrity(): Promise<void> {
205+
const query = `{
206+
all(func: anyofterms(name, "${names.join(" ")}")) {
207+
uid
208+
name
209+
email
210+
age
211+
}
212+
}`;
213+
const res = await client.newTxn().query(query);
214+
215+
const data: {
216+
all: Profile[];
217+
} = res.getJson(); // tslint:disable-line no-unsafe-any
218+
219+
const profileSet: { [key: string]: boolean } = {};
220+
for (const profile of data.all) {
221+
expect(profile.name).toBeTruthy();
222+
expect(profile.email).toBeTruthy();
223+
expect(profile.age).toBeTruthy();
224+
profileSet[`${profile.name}_${profile.email}_${profile.age}`] = true;
225+
}
226+
227+
for (const profile of profiles) {
228+
expect(profileSet[`${profile.name}_${profile.email}_${profile.age}`]).toBe(true);
229+
}
230+
}
231+
232+
async function checkUpsertIntegrity(): Promise<void> {
233+
const query = `{
234+
all(func: eq(email, "[email protected]")) {
235+
name
236+
email
237+
age
238+
}
239+
}`;
240+
const res = await client.newTxn().query(query);
241+
242+
const data: {
243+
all: Profile[];
244+
} = res.getJson(); // tslint:disable-line no-unsafe-any
245+
246+
const profileSet: { [key: string]: boolean } = {};
247+
for (const profile of data.all) {
248+
expect(profile.name).toBeTruthy();
249+
expect(profile.email).toBeTruthy();
250+
expect(profile.age).toBeTruthy();
251+
profileSet[`${profile.name}_${profile.email}_${profile.age}`] = true;
252+
}
253+
254+
const receivedObject: Profile = data.all[0];
255+
const expectedObject: Profile = {
256+
name: "Prashant Shahi",
257+
258+
age: 24,
259+
};
260+
261+
expect(Object.keys(profileSet).length).toEqual(1);
262+
expect(receivedObject).toEqual(expectedObject);
263+
}
264+
265+
describe("upsert using doRequest", () => {
266+
it("should successfully perform upsert load test", async () => {
267+
client = await setup();
268+
await setSchema(client, `
269+
first: string @index(term) .
270+
last: string @index(hash) .
271+
age: int @index(int) .
272+
when: int .
273+
`);
274+
await doUpserts();
275+
await checkIntegrity();
276+
});
277+
278+
it("should successfully perform upsert", async () => {
279+
client = await setup();
280+
await setSchema(client, `
281+
name: string @index(term) .
282+
email: string @index(exact) .
283+
age: int @index(int) .
284+
`);
285+
await doUpsert();
286+
});
287+
});

0 commit comments

Comments
 (0)