aerospike
Version:
Aerospike Client Library
214 lines (172 loc) • 7.79 kB
text/typescript
// *****************************************************************************
// Copyright 2013-2024 Aerospike, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License")
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// *****************************************************************************
/* eslint-env mocha */
/* global expect */
import Aerospike, { status as statusModule, Client as Cli, Key as K, RecordMetadata, AerospikeRecord, AerospikeError, ReadPolicy, AerospikeBins} from 'aerospike';
import { expect } from 'chai';
import * as helper from './test_helper';
const keygen: any = helper.keygen
const metagen: any = helper.metagen
const recgen: any = helper.recgen
const status: typeof statusModule = Aerospike.status
describe('client.get()', function () {
const client: Cli = helper.client
it('should read the record', function (done) {
const key: K = keygen.string(helper.namespace, helper.set, { prefix: 'test/get/' })()
const meta: RecordMetadata = metagen.constant({ ttl: 1000 })()
const record: AerospikeRecord = recgen.constant({ i: 123, s: 'abc' })()
client.put(key, record, meta, function (err?: AerospikeError) {
if (err) throw err
client.get(key, function (err?: AerospikeError, record?: AerospikeRecord) {
if (err) throw err
client.remove(key, function (err?: AerospikeError, key?: K) {
if (err) throw err
done()
})
})
})
})
it('should not find the record', function (done) {
const key: K = keygen.string(helper.namespace, helper.set, { prefix: 'test/not_found/' })()
client.get(key, function (err?: AerospikeError, record?: AerospikeRecord) {
expect(err?.code).to.equal(status.ERR_RECORD_NOT_FOUND)
done()
})
})
context('with ReadPolicy', function () {
context('with deserialize: false', function () {
it('should return lists and maps as raw bytes', function () {
const key: K = keygen.string(helper.namespace, helper.set, { prefix: 'test/get/' })()
const bins: AerospikeBins = {
i: 123,
s: 'abc',
l: [1, 2, 3],
m: { a: 1, b: 2, c: 3 }
}
const policy: ReadPolicy = new Aerospike.ReadPolicy({
deserialize: false
})
return client.put(key, bins)
.then(() => client.get(key, policy))
.then((record: AerospikeRecord) => {
const bins: AerospikeBins = record.bins
expect(bins.i).to.eql(123)
expect(bins.s).to.eql('abc')
expect(bins.l).to.eql(Buffer.from([0x93, 0x01, 0x02, 0x03]))
expect(bins.m).to.eql(Buffer.from([0x84, 0xc7, 0x00, 0x01, 0xc0, 0xa2, 0x03, 0x61, 0x01, 0xa2, 0x03, 0x62, 0x02, 0xa2, 0x03, 0x63, 0x03]))
})
})
})
context('readTouchTtlPercent policy', function () {
helper.skipUnlessVersion('>= 7.1.0', this)
this.timeout(4000)
it('100% touches record', async function () {
const key: K = keygen.integer(helper.namespace, helper.set)()
const policy: ReadPolicy = new Aerospike.ReadPolicy({
readTouchTtlPercent: 100
})
await client.put(key, { i: 2 }, { ttl: 10 })
await new Promise((resolve: any) => setTimeout(resolve, 3000))
let record: AerospikeRecord = await client.get(key, policy)
expect(record.bins).to.eql({ i: 2 })
expect(record.ttl).to.be.within(5, 8)
record = await client.get(key, policy)
expect(record.bins).to.eql({ i: 2 })
expect(record.ttl).to.be.within(9, 11)
await client.remove(key)
})
it('80% touches record', async function () {
const key: K = keygen.integer(helper.namespace, helper.set)()
const policy: ReadPolicy = new Aerospike.ReadPolicy({
readTouchTtlPercent: 80
})
await client.put(key, { i: 2 }, { ttl: 10 })
await new Promise((resolve: any) => setTimeout(resolve, 3000))
let record: AerospikeRecord = await client.get(key, policy)
expect(record.bins).to.eql({ i: 2 })
expect(record.ttl).to.be.within(5, 8)
record = await client.get(key, policy)
expect(record.bins).to.eql({ i: 2 })
expect(record.ttl).to.be.within(9, 11)
await client.remove(key)
})
it('60% never touches record', async function () {
const key: K = keygen.integer(helper.namespace, helper.set)()
const policy: ReadPolicy = new Aerospike.ReadPolicy({
readTouchTtlPercent: 60
})
await client.put(key, { i: 2 }, { ttl: 10 })
await new Promise((resolve: any) => setTimeout(resolve, 3000))
let record: AerospikeRecord = await client.get(key, policy)
expect(record.bins).to.eql({ i: 2 })
expect(record.ttl).to.be.within(5, 8)
record = await client.get(key, policy)
expect(record.bins).to.eql({ i: 2 })
expect(record.ttl).to.be.within(5, 8)
await client.remove(key)
})
it('0% never touches record', async function () {
const key: K = keygen.integer(helper.namespace, helper.set)()
const policy: ReadPolicy = new Aerospike.ReadPolicy({
readTouchTtlPercent: 0
})
await client.put(key, { i: 2 }, { ttl: 10 })
await new Promise((resolve: any) => setTimeout(resolve, 3000))
let record: AerospikeRecord = await client.get(key, policy)
expect(record.bins).to.eql({ i: 2 })
expect(record.ttl).to.be.within(5, 8)
record = await client.get(key, policy)
expect(record.bins).to.eql({ i: 2 })
expect(record.ttl).to.be.within(5, 8)
await client.remove(key)
})
})
})
it('should return the TTL for a never expiring record as Aerospike.ttl.NEVER_EXPIRE', function (done) {
const key: K = keygen.string(helper.namespace, helper.set, { prefix: 'test/get/' })()
const meta: RecordMetadata = metagen.constant({ ttl: Aerospike.ttl.NEVER_EXPIRE })()
const record: AerospikeRecord = recgen.constant({ i: 123, s: 'abc' })()
client.put(key, record, meta, function (err?: AerospikeError) {
if (err) throw err
client.get(key, function (err?: AerospikeError, record?: AerospikeRecord) {
if (err) throw err
expect(record?.ttl).to.equal(Aerospike.ttl.NEVER_EXPIRE)
client.remove(key, function (err?: AerospikeError) {
if (err) throw err
done()
})
})
})
})
it('should return a Promise that resolves to a Record', function () {
const key: K = keygen.string(helper.namespace, helper.set, { prefix: 'test/get/' })()
return client.put(key, { i: 42 })
.then(() => client.get(key))
.then((record: AerospikeRecord) => expect(record.bins).to.eql({ i: 42 }))
.then(() => client.remove(key))
})
it('fetches a record given the digest', function () {
const key: K = new Aerospike.Key(helper.namespace, helper.set, 'digestOnly')
client.put(key, { foo: 'bar' })
.then(() => {
const digest: Buffer = key.digest!;
const key2: K = new Aerospike.Key(helper.namespace, undefined, null, digest)
return client.get(key2)
.then((record: AerospikeRecord) => expect(record.bins.foo).to.equal('bar'))
})
})
})