I think I’ve found a bug related to transactions and querying by regex in the JavaScript gRPC client. Here are the steps:
- Start a transaction.
- Insert a node.
- Query for the node by UID, and it will be found.
- Query for the node by regex, and it will not be found.
- Abort the transaction.
If I do this instead, there’s no problem:
- Start a transaction.
- Insert a node.
- Commit and discard the transaction.
- Start a new transaction
- Query for the node by UID, and it will be found.
- Query for the node by regex, and it will be found.
I know what follows is a lot of code, but it precisely reproduces the problem I’m seeing. I tried to write this code so that anyone could copy/paste it into a file, say regex.js
, and then simply execute node regex.js
to see what I’m seeing:
const { DgraphClient, DgraphClientStub, Mutation, Operation } = require('dgraph-js')
test()
async function test() {
const stub = new DgraphClientStub('localhost:9080')
const client = new DgraphClient(stub)
await setSchema(client)
await failure(client)
await success(client)
stub.close()
}
async function failure(client) {
const txn = client.newTxn()
const alice = await insertUser(txn, 'Alice')
const aliceByUid = await findUserByUid(txn, alice.uid)
const aliceByName = await findUsersByName(txn, 'lic', 10)
await txn.discard()
console.log('failure:')
console.log(' aliceByUid is:', aliceByUid)
console.log(' aliceByName is:', aliceByName)
}
async function success(client) {
let txn = client.newTxn()
const alice = await insertUser(txn, 'Alice')
await txn.commit()
await txn.discard()
txn = client.newTxn()
const aliceByUid = await findUserByUid(txn, alice.uid)
const aliceByName = await findUsersByName(txn, 'lic', 10)
console.log('success:')
console.log(' aliceByUid is:', aliceByUid)
console.log(' aliceByName is:', aliceByName)
}
function setSchema(client) {
const operation = new Operation()
operation.setSchema(`
type User {
User.name
}
User.name: string @index(trigram) .
`)
return client.alter(operation)
}
async function insertUser(txn, name) {
const user = {
'dgraph.type': 'User',
'User.name': name,
uid: '_:user'
}
const mutation = new Mutation()
mutation.setSetJson(user)
const response = await txn.mutate(mutation)
user.uid = response.getUidsMap().get('user')
return user
}
async function findUserByUid(txn, uid) {
const query = `
query user($uid: string) {
user(func: uid($uid)) {
User.name
uid
}
}
`
const response = await txn.queryWithVars(query, { $uid: uid })
return response.getJson().user[0]
}
async function findUsersByName(txn, name, limit) {
const query = `
query users($regex: string, $limit: int) {
users(func: regexp(User.name, $regex), first: $limit) {
User.name
uid
}
}
`
const response = await txn.queryWithVars(query, { $regex: `/${name}/i`, $limit: `${limit}` })
return response.getJson()?.users
}
Here’s what prints to my console:
failure:
aliceByUid is: { 'User.name': 'Alice', uid: '0xc365' }
aliceByName is: []
success:
aliceByUid is: { 'User.name': 'Alice', uid: '0xc366' }
aliceByName is: [ { 'User.name': 'Alice', uid: '0xc366' } ]
Am I doing something wrong, or is it a legitimate bug that the regex query doesn’t work in the “failure” case?