Skip to main content

Incompatible API Changes

[5.0.0]

Predicate Expression Filter Replaced by New Filter Expressions

  • Usage
    • New Filter Expressions
      const query = client.query(helper.namespace, helper.set)
      const queryPolicy = { filterExpression: exp.eq(exp.binInt('a'), exp.int(9))}
      const stream = query.foreach(queryPolicy)
    • Deprecated PredicateExpression Filter
      const query = client.query(helper.namespace, helper.set)
      const pexp = Aerospike.predexp
      query.where([pexp.IntVar('a'), pexp.IntValue(9),pexp.stringEqual()])
      const stream = query.foreach()

[4.0.0]

totalTimeout Replaced by timeout Info Policy Option

  • Usage

    • New "timeout" InfoPolicy

      const subject = new Aerospike.InfoPolicy({
      timeout: 1000,
      sendAsIs: true,
      checkBounds: false
      })
    • Deprecated "totalTimeout" InfoPolicy

      const subject = new Aerospike.InfoPolicy({
      totalTimeout: 1000,
      sendAsIs: true,
      checkBounds: false
      })

Version 3.16.0

Percent-Based Sampling Replaced by Max-Records Scan Policy Option

Aerospike server version 4.9 and Node.js client version 3.16 support a new maxRecords scan policy option which limits the number of records the server nodes will return to the client when performing a scan operation. This can be used to perform a random sample of a given namespace/set in the database.

With the introduction of the maxRecords scan policy, the percent scan option has been deprecated. The v3.16.0 client continues to support the percent scan options on server versions older than 4.9, but for server versions 4.9 and newer, the client no longer sends the percent option for scan operations if specified as part of the scan command. Please use the new maxRecords scan policy option instead on server versions 4.9 and newer.

Update: This breaking change was reversed in version 3.16.2. The old percent scan option can also be used with server version 4.9 and later. However, note that scan percent and max_records are mutually exclusive; the client will return an error if both values are set on a scan policy.

Usage

New max records scan policy:

const scanPolicy = new Aerospike.ScanPolicy({
maxRecords: 1000 // return approx. 1,000 records
})
const scan = client.scan(namespace, set)
const stream = scan.foreach(scanPolicy)

Deprecated percent scan option:

const scanOptions = {
percent: 10 // return approx. 10% of all records
}
const scan = client.scan(namespace, set, scanOptions)
const stream = scan.foreach()

Version 3.10.0

Read Consistency Level Changes

Read policy changes for transactions involving AP (availability) namespaces

  • Policy variable consistencyLevel was replaced by readModeAP for the read, batch and, operate policies.
  • In the Aerospike.policy module the following enum values were replaced:
    • consistencyLevel.ONE was replaced by readModeAP.ONE
    • consistencyLevel.ALL was replaced by readModeAP.ALL

Read policy changes for transactions involving SC (strong consistency) namespaces

  • Policy variable linearizeRead was replaced by readModeSC for the read, batch, and operate policies.
  • Added Aerospike.policy.readModeSC enum - see API docs for details.

Version 3.8.0

Shared Memory Layout & Key Changes

Shared memory layout has changed. If you are using shared memory clients, it is critical to change the shared memory key (Config#sharedMemory.key) when upgrading from Node.js client to v3.8.0. The default value for the key has changed from 0xA7000000 to 0xA8000000.

Please refer to the Shared Memory section in the Aerospike C Client's documentation for more information about the client's usage of shared memory.

Version 3.0.0

Removal of LargeList (LDT) Functionality

The Client#LargeList function and all related functionality supporting Large Data Types (LDT) have been removed. Deprecation of LDT was first announced on the Aerospike Blog in November 2016. Aerospike Server v3.14 is the last server release to support LDT functionality.

Promise-based API & Changes in Callback Method Signatures

In addition to callback functions, the v3 client also supports an async API based on Promises. (And async/await when using Node.js v8 or later!) The callback function parameter on all async client commands is now optional. If no callback function is passed, the command will return a Promise instead. A Promise object represents the eventual completion (or failure) of an asynchronous operation, and its resulting value.

In contrast to callback functions, a Promise can only resolve to a single result value. In v2, several of the client's callback functions passed more than one result value. For example, the record callback function used by the v2 Client#get command, passes the record bins, meta data and the keys in three separate parameters to the callback function: recordCallback(error, bin, meta, key).

To harmonize the result values passed to callback functions and the values returned by Promises, all client commands in v3 return a single result value. The method signatures of several callback functions have been updated to combine multiple separate result values into a single result object.

Callbackv2 / v3 Method SignatureAffected Client Commands
Record Callbackv2: cb(error, bins, meta, key) v3: cb(error, record)Client#get, Client#operate, Client#append, Client#prepend, Client#add, Client#select
Batch Record Callbackv2: cb(error, [{status:, key:, bins:, meta:}]) v3: cb(error, [{status:, record:}])Client#batchRead, Client#batchGet, Client#batchSelect
Record Stream data Event Callbackv2: cb(bins, meta, key) v3: cb(record)Query#foreach, Scan#foreach

Note: The record object passed in v3 is an instance of the new Record class, which contains the records bins, key and meta-data.

Update Error Status Codes & Messages

The constants for the error status codes in the Aerospike.status module have been renamed to drop the redundant AEROSPIKE_ prefix. E.g.

  • Aerospike.status.AEROSPIKE_OKAerospike.status.OK
  • Aerospike.status.AEROSPIKE_ERR_RECORD_NOT_FOUNDAerospike.status.ERR_RECORD_NOT_FOUND
  • Aerospike.status.AEROSPIKE_ERR_NO_MORE_CONNECTIONSAerospike.status.ERR_NO_MORE_CONNECTIONS
  • ...

The old contents (with AEROSPIKE_ prefix) still exist for now, but are undocumented; they will be removed in the next major client version.

AerospikeError instances now also have proper, human readable error messages in most cases.

Policy Changes, Improved Timeout & Retry Handling

The v3 client provides separate ES6 classes for all client transaction policies, e.g. Aerospike.ReadPolicy, Aerospike.WritePolicy, etc. Passing policy values as plain objects to client commands is still supported but maybe deprecated at some point in the future. The policy classes will provide additional functionality like validation, support for handling future, backward incompatible policy changes, etc. It is recommended that you start using the new policy classes over plain objects.

Global default policies can be set when creating a new client instance. Default policies need to be set separately for all transaction types, e.g. read, write, operate, etc. Setting global default policy values that apply to all transaction policies is no longer supported.

All [1] client transaction policies are based on a new BasePolicy class which encode some important differences in how the v3 client handles timeouts and automatic retries.

The timeout policy value of the v2 client has been renamed to totalTimeout and specifies the total transaction timeout in milliseconds. The totalTimeout is tracked on the client and sent to the server along with the transaction in the wire protocol. The client will most likely timeout first, but the server also has the capability to timeout the transaction. If totalTimeout is not zero and totalTimeout is reached before the transaction completes, the transaction will return error ERR_TIMEOUT. If totalTimeout is zero, there will be no total time limit. The default value for totalTimeout is 1,000 milliseconds.

The new socketTimeout policy value specifies the socket idle timeout in milliseconds. If socketTimeout is not zero and the socket has been idle for at least socketTimeout, both maxRetries and totalTimeout are checked. If maxRetries and totalTimeout are not exceeded, the transaction is retried. The default value for socketTimeout is zero, i.e. no socket idle time limit.

maxRetries is used to specify the maximum number of retries before aborting the current transaction. The default value for maxRetries is 2. The initial attempt is not counted as a retry. If maxRetries is exceeded, the transaction will return error ERR_TIMEOUT.

WARNING: Database writes that are not idempotent (such as Client#incr) should not be retried because the write operation may be performed multiple times if the client timed out previous transaction attempts. It is important to use a distinct WritePolicy for non-idempotent writes which sets maxRetries to zero.

Example: Using the new policy classes to specify timeout and retry handling:

const Aerospike = require('aerospike')

let defaults = {
socketTimeout: 200,
totalTimeout: 500,
maxRetries: 2
}
let config = {
policies: {
read: new Aerospike.ReadPolicy(defaults),
write: new Aerospike.WritePolicy(defaults)
// timeout: 500 - Can no longer specify global defaults here!
}
}

let key = new Aerospike.Key('test', 'demo', 'k1')

Aerospike.connect(config)
.then(client => {
return client.put(key, {value: 10})
.then(() => {
let policy = new Aerospike.OperatePolicy({ maxRetries: 0 })
return client.incr(key, {value: 20}, {}, policy)
})
.then(() => client.get(key))
.then(record => console.info('Value:', record.bins.value))
.then(() => client.close())
.catch(error => {
client.close()
return Promise.reject(error)
})
})
.catch(error => console.error('Error:', error))

(1) Except InfoPolicy and MapPolicy.

Changed Semantics of Client#exists Command

The Client#exists command now returns a simple boolean value to indicate whether a record exists in the database under the given key. It is no longer necessary, nor possible, to check the transactions's status code for the ERR_RECORD_NOT_FOUND error.

Usage under v2:

let key = new Aerospike.Key('test', 'test', 'noSuchKey')
client.exists(key, error => {
if (error && error.code !== Aerospike.status.ERR_RECORD_NOT_FOUND) {
// An error occurred while executing the command.
} else if (error) {
// The record does not exist.
} else {
// The record for the key exists.
}
})

Usage under v3:

let key = new Aerospike.Key('test', 'test', 'noSuchKey')
client.exists(key, (error, result) => {
if (error) {
// An error occurred while executing the command.
} else if (result) {
// The record for the key exists.
} else {
// The record does not exist.
}
})

Changed Semantics of Client#createIndex and Client#indexRemove Commands

The Client#createIndex command now returns an error with status code ERR_INDEX_FOUND if an index with the same name already exists and/or if an index of any name already exists on the same bin.

The Client#removeIndex command now returns an error with status code ERR_INDEX_NOT_FOUND if no index with the given name exists in the cluster.

Shared Memory Layout & Key Changes

Shared memory layout has changed. If you are using shared memory clients, it is critical to change the shared memory key (Config#sharedMemory.key) when upgrading from Node.js client v2 to v3. The default value for the key has changed from 0xA6000000 to 0xA7000000.

Please refer to the Shared Memory section in the Aerospike C Client's documentation for more information about the client's usage of shared memory.

Removal of Client Functions Deprecated under v2

The following Client functions have been marked as deprecated under v2.x and have been removed in v3:

Removed FunctionReplacementRemarks
Aerospike.Double()new Aerospike.Double()-
Aerospike.filter.geoContains()Aerospike.filter.geoContainsGeoJSONPoint()-
Aerospike.filter.geoWithin()Aerospike.filter.geoWithinGeoJSONRegion()-
Aerospike.indexType.<STRING, NUMERIC, GEO2DSPHERE>Aerospike.indexDataType.<STRING, NUMERIC, GEO2DSPHERE>-
Aerospike.info.parseInfo()Aerospike.info.parse()-
Aerospike.key()new Aerospike.Key()-
Aerospike.operator.<*>Aerospike.operations.<*>-
Aerospike.operator.list<*>Aerospike.lists.<*>-
Client#LargeList()-See "Removal of LDT functionality"
Client#execute()Client#apply()-
Client#info() w/o host paramClient#infoAll()-
Client#udfRegisterWait()UdfJob#wait()Client#udfRegister() & Client#udfRemove() return a UdfJob instance.
Client#createIndexWait()IndexJob#wait()Client#createIndex() & Client#create<*>Index() return an IndexJob instance.
InfoPolicy#send_as_isInfoPolicy#sendAsIs-
InfoPolicy#check_boundsInfoPolicy#checkBounds-
LargeList#*-See "Removal of LDT functionality"
Query#execute()Query#foreach()
Scan#execute()Scan#foreach()

Supported Node.js versions

Node.js v0.12 is no longer supported. Node.js v4 (LTS) or later are required to run Aerospike Node.js client v3.0.

Version 2.6.0

Deprecations

Deprecated FunctionReplacementRemarks
Info#parseInfoInfo#parseparse and parseInfo both parse the info data returned by the Aerospike server; there are some minor differences between the parsed data returned by the two functions for some info keys
Client#udfRegisterWaitUdfJob#waitUntilDoneAn UdfJob instance is passed to the client's udfRegister/udfRemove callback functions.

Version 2.4.4

Deprecation of LargeList Functionality

Aerospike will no longer support the Large Data Type (LDT) feature so all LargeList related functions have been marked as deprecated. Please refer to this article on the Aerospike company blog for more details.

Deprecations

Deprecated FunctionReplacementRemarks
Client#LargeList-see above
LargeList#*-see above

Version 2.4.0

Shared Memory Layout Changes

Multiple client instances running in separate processes on the same machine can use shared memory to share cluster status, including nodes and data partition maps. See sharedMemory config for more information.

In v4.1.0 of the Aerospike C client library, which is included in v2.4.0 of the Aerospike Node.js client, the shared memory layout has changed. The default shm_key config has changed to 0xA6000000 so old client applications do not mix shared memory with new client applications. If you are using shared memory clients with a custom shm_key, it's critical that this key changes when upgrading to v2.4.0 of the Aerospike Node.js client.

Deprecations

Deprecated FunctionReplacementRemarks
InfoPolicy#send_as_isInfoPolicy#sendAsIs-
InfoPolicy#check_boundsInfoPolicy#checkBounds-
ReadPolicy#retry--
WritePolicy#retry--
RemovePolicy#retry--
OperatePolicy#retry--

Notes:

  • The retry policy value for read, write, remove and operate policies has not been effective for any single key read/write commands, the batch read command or query/scan commands in client versions v2.x.

Version 2.1.0

New modules for Scalar, List & Map operations

The Aerospike.operator module has been split into three separate modules for operations on scalar values, lists and maps:

  • Aerospike.operations - Operations on scalar values (Strings, Integers, Doubles, etc.).
  • Aerospike.lists - Operations on Lists, e.g. append, insert, remove.
  • Aerospike.maps - Operations on Sorted Maps, e.g. put, getByKey, removeByIndex.

The old Aerospike.operator module has been deprecated and will be removed in the next major release.

Deprecations

Deprecated FunctionReplacementRemarks
Aerospike.operator.appendAerospike.operations.append-
Aerospike.operator.incrAerospike.operations.incr-
Aerospike.operator.prependAerospike.operations.prepend-
Aerospike.operator.readAerospike.operations.read-
Aerospike.operator.touchAerospike.operations.touch-
Aerospike.operator.writeAerospike.operations.write-
Aerospike.operator.list<*>Aerospike.lists.<*>-

Version 2.0.0

None. But see 2.0.0-alpha.1 through 2.0.0-alpha.3 for list of backward incompatible changes since v1.x.

Version 2.0.0-alpha.3

New Query Interface

The Client API for executing Queries was revised in this release and has several backward incompatible changes.

Processing Query Results

Prior to v2.0.0-alpha.3 the data event on the RecordStream interface would pass a single record object to the event handler function, with two properties bins and meta containing the bin values and the meta data for the record respectively. Starting with v2.0.0-alpha.3, the data event instead pass the bin values and the meta data as two separate parameters into the event handler. (Same as the Scan interface introduced in v2.0.0-alpha.2.)

Before:

# broken code - do not use in v2 client
var statement = {
'filters': [...]
}
var query = client.query('ns', 'set', statement)
var stream = query.execute()
stream.on('error', function (error) {
// handle error
})
stream.on('data', function (record) {
console.log(record.bins)
console.log(record.meta)
})
stream.on('end', function () {
// query completed
})

After:

var statement = {
'filters': [...]
}
var query = client.query('ns', 'set', statement)
var stream = query.foreach()
stream.on('error', function (error) {
// handle error
})
stream.on('data', function (bins, meta) {
console.log(bins)
console.log(meta)
})
stream.on('end', function () {
// query completed
})

Separation of Query and Scan APIs

In Aerospike Node.js client v1.x, both queries (with filter predicates) and scans (without filter predicates) where handled via the Client#query command and the Query#execute method. In v2.0.0-alpha.2, the new Scan API was introduced, and scan operations should now be initiated via Client#scan. Starting with v2.0.0-alpha.3, the Query API will no longer accept any of the properties specific to scans in the query statment when calling Client#query. Including any of the following five keys will result in an exception being raised by the client:

  • UDF
  • concurrent
  • percentage
  • nobins

The concurrent, percentage and nobins values should be set via the Scan API instead and the Lua UDF parameters for applying a Aerospike Record UDF on a background scan should be passed directly to Scan#background.

Before: Executing Background Scan

# broken code - do not use in v2 client
var statement = {
'UDF': {
module: 'myLuaModule',
funcname: 'myLuaFunction',
args: ['some', 'function', 'arguments']
}
}
var query = client.query('ns', 'set', statement)
var stream = query.execute()
stream.on('error', function (error) {
// handle error
})
stream.on('end', function (scanID) {
// retrieve scanID, which can be used to check scan job status
})

After: Executing Background Scan

var udfArgs = ['some', 'function', 'arguments']
var scan = client.scan('ns', 'set')
scan.background('myLuaModule', 'myLuaFunction', udfArgs, function (error, scanJob) {
if (error) {
// handle error
} else {
// use scanJob.info() and/or scanJob.waitUntilDone() to check scan job status
}
})

Before: Setting Scan Concurrent Execution, etc.

# broken code - do not use in v2 client
var statement = {
concurrent: true,
nobins: true,
percentage: 50
}
var query = client.query('ns', 'set', statement)
var stream = query.execute()
stream.on('error', function (error) {
// handle error
})
stream.on('data', function (record) {
// process scan results
})
stream.on('end', function () {
// scan completed
})

After: Setting Scan Concurrent Execution, etc.

var scan = client.scan('ns', 'test')
scan.concurrent = true
scan.nobins = true
scan.percentage = 50
var stream = scan.foreach()
stream.on('error', function (error) {
// handle error
})
stream.on('data', function (bins, meta) {
// process scan results
})
stream.on('end', function () {
// scan completed
})

Query Aggregation using Stream UDFs

Applying a Lua User-Defined Function (UDF) as an Aerospike Stream UDF for query aggregation is now done via the new Query#apply function, rather than by passing the aggregationUDF parameter in the query statement and calling Query#execute. Query#apply returns the aggregation result via asynchronous callback so it is no longer necessary to extract the single result value from a record stream.

Before:

# broken code - do not use in v2 client
var statement = {
aggregationUDF: {
module: 'myLuaModule',
funcname: 'myLuaFunction',
args: ['some', 'function', 'arguments']
}
}
var query = client.query('ns', 'set', statement)
var stream = query.execute()
stream.on('error', function (error) {
// handle error
})
stream.on('data', function (result) {
// handle result
})

After:

var query = client.query('ns', 'set')
var udfArgs = ['some', 'function', 'arguments']
query.apply('myLuaModule', 'myLuaFunction', udfArgs, function (error, result) {
if (error) {
// handle error
} else {
// handle result
}
})
note

Client#query will now throw an exception if the query statement includes an aggregationUDF property.

Deprecations

Deprecated FunctionReplacementRemarks
Aerospike#scanStatusAerospike#jobStatus-
Query#executeQuery#foreach-
Scan#executeScan#foreachScan class was introduced in 2.0.0-alpha.2
Scan#selectBinsScan#selectScan class was introduced in 2.0.0-alpha.2

Version 2.0.0-alpha.2

Deprecations

Deprecated FunctionReplacementRemarks
Client#createIndexWaitIndexTask#waitUntilDone-
Aerospike.filter.geoWithinAerospike.filter.geoWithinGeoJSONRegion-
Aerospike.filter.geoContainsAerospike.filter.geoContainsGeoJSONPoint-

When creating new secondary indexes via the Client#createIndex method (or Client#createIntegerIndex, etc. short-hand methods), the optional info policy should be passed as a separate function parameter instead of passing it in the first options parameter. The options.policy parameter is deprecated.

In the info object returned by Query#info the recordScanned property has been renamed to recordsScanned. For now the info object will contain the same value under both the new and old name but the recordScanned property will be removed in some future release.

Version 2.0.0-alpha.1

Error-first callbacks

Callbacks no longer return an error object with status code AEROSPIKE_OK (0). Instead, if the client command succeeds, the first argument to the callback (the error argument) will be null.

To revert to the previous callback behavior, set the callback handler for the client to the LegacyCallbackHandler using the Client.setCallbackHandler method. You need to set the callback handler, before instantiating any client instances, e.g. using the Aerospike.connect or Aerospike.client methods.

const Aerospike = require('aerospike')
const Client = Aerospike.Client
Client.setCallbackHandler(Client.LegacyCallbackHandler)

Aerospike.connect((error, client) => {
console.log(error) => // { code: 0, message: '', func: '', file: '', line: 0 }
if (error.code !== Aerospike.status.AEROSPIKE_OK) {
// handle error
} else {
// client instance is ready receive commands
client.close()
}
})

Releasing of event loop resources

To handle asynchronous client commands send to the Aerospike server cluster, the client needs to register an async handle on Node.js event loop. This handle needs to be freed explicitly in order for the event loop to exit and the Node.js application to terminate.

Single Aerospike client instance

When working with a single Aerospike Node.js client instance, you can use the client's close method to close the connection to the server nodes and release all event loop resources. It is important to call the client's close method as otherwise the application might not terminate.

Example:

const Aerospike = require('aerospike')

Aerospike.connect((error, client) => {
if (error) throw error
// client instance is ready receive commands
client.close()
})

Multiple (concurrent) Aerospike client instances

When the application needs to instantiate more than one Aerospike client, e.g. to connect to multiple Aerospike server clusters, then the event loop resources should only be released after the last client instance was closed. To prevent automatic release of the event loop resources, the client's close method needs to be called with the releaseEventLoop parameter set to false:

var releaseEventLoop = false
client.close(releaseEventLoop)

Then, after the last client instance was close, the releaseEventLoop method on the Aerospike module needs to be called before the program terminates:

Aerospike.releaseEventLoop()

Example:

const Aerospike = require('aerospike')

// called one or more times to handle a new work request
function handleRequest (request) {
Aerospike.connect((error, client) => {
if (error) throw error
// handle request
client.close(false) // do not release event loop
})
}

// called when application shuts down
function shutdown () {
Aerospike.releaseEventLoop()
}

Supported Node.js versions

Node.js v0.10 is no longer supported. Node.js v0.12 or later are required to run Aerospike Node.js client v2.0.

Deprecations

The following functions have been deprecated and/or replaced:

Deprecated FunctionReplacementRemarks
Aerospike.keynew Aerospike.Key-
Aerospike.Doublenew Aerospike.Double-
Aerospike.GeoJSONnew Aerospike.GeoJSON-
Client#batchExistsClient#batchReadRequires Aerospike server version >= 3.6.0.
Client#batchGetClient#batchReadRequires Aerospike server version >= 3.6.0.
Client#batchSelectClient#batchReadRequires Aerospike server version >= 3.6.0.
Client#executeClient#apply-
Client#addClient#incr-