2 Commits

22 changed files with 10861 additions and 11551 deletions

View File

@ -26,13 +26,6 @@ Install using `npm install node-eventstore-client`
- Node.js >= 4.0 - Node.js >= 4.0
- Modules: [long](https://www.npmjs.org/package/long), [protobufjs](https://www.npmjs.org/package/protobufjs), [uuid](https://www.npmjs.org/package/uuid) (installed via `npm install`) - Modules: [long](https://www.npmjs.org/package/long), [protobufjs](https://www.npmjs.org/package/protobufjs), [uuid](https://www.npmjs.org/package/uuid) (installed via `npm install`)
### Install & run an Eventstore on localhost
See https://eventstore.org/docs/introduction/4.0.2/
*Note: If you are using a version of EventStore prior to 3.9.4, you need to use version 0.1.x of this package `npm install node-eventstore-client@^0.1`.*
### API Documentation ### API Documentation
#### Offline #### Offline
@ -42,7 +35,11 @@ The offline documentation can be found in the module folder `./node_modules/node
#### Online #### Online
The online documentation can be found at [https://dev.nicdex.com/node-eventstore-client/docs/](https://dev.nicdex.com/node-eventstore-client/docs/) The online documentation can be found at [https://dev.nicdex.com/node-eventstore-client/docs/](https://dev.nicdex.com/node-eventstore-client/docs/)
### Install & run an Eventstore on localhost
See http://docs.geteventstore.com/introduction/3.9.0/ .
### Example: Storing an event ### Example: Storing an event
Save to ```app.js:``` Save to ```app.js:```

43
index.d.ts vendored
View File

@ -16,7 +16,7 @@ export class UserCredentials {
} }
export class PersistentSubscriptionSettings { export class PersistentSubscriptionSettings {
constructor(resolveLinkTos: boolean, startFrom: Long|number, extraStatistics: boolean, messageTimeout: number, constructor(resolveLinkTos: boolean, startFrom: number, extraStatistics: boolean, messageTimeout: number,
maxRetryCount: number, liveBufferSize: number, readBatchSize: number, historyBufferSize: number, maxRetryCount: number, liveBufferSize: number, readBatchSize: number, historyBufferSize: number,
checkPointAfter: number, minCheckPointCount: number, maxCheckPointCount: number, checkPointAfter: number, minCheckPointCount: number, maxCheckPointCount: number,
maxSubscriberCount: number, namedConsumerStrategy: string) maxSubscriberCount: number, namedConsumerStrategy: string)
@ -41,7 +41,7 @@ export class WrongExpectedVersionError {
readonly action: string; readonly action: string;
readonly message: string; readonly message: string;
readonly stream?: string; readonly stream?: string;
readonly expectedVersion?: Long; readonly expectedVersion?: number;
readonly transactionId?: Long; readonly transactionId?: Long;
} }
@ -98,16 +98,17 @@ export class FileLogger implements Logger {
error(fmt: string, ...args: any[]): void; error(fmt: string, ...args: any[]): void;
} }
// Expose results //
export interface WriteResult { export interface WriteResult {
readonly nextExpectedVersion: Long; readonly nextExpectedVersion: number;
readonly logPosition: Position; readonly logPosition: Position;
} }
export interface RecordedEvent { export interface RecordedEvent {
readonly eventStreamId: string; readonly eventStreamId: string;
readonly eventId: string; readonly eventId: string;
readonly eventNumber: Long; readonly eventNumber: number;
readonly eventType: string; readonly eventType: string;
readonly createdEpoch: number; readonly createdEpoch: number;
readonly data?: Buffer; readonly data?: Buffer;
@ -122,17 +123,17 @@ export interface ResolvedEvent {
readonly isResolved: boolean; readonly isResolved: boolean;
readonly originalPosition?: Position; readonly originalPosition?: Position;
readonly originalStreamId: string; readonly originalStreamId: string;
readonly originalEventNumber: Long; readonly originalEventNumber: number;
} }
export interface StreamEventsSlice { export interface StreamEventsSlice {
readonly status: string; // TODO: enum readonly status: string; // TODO: enum
readonly stream: string; readonly stream: string;
readonly fromEventNumber: Long; readonly fromEventNumber: number;
readonly readDirection: string; // TODO: enum readonly readDirection: string; // TODO: enum
readonly events: ResolvedEvent[]; readonly events: ResolvedEvent[];
readonly nextEventNumber: Long; readonly nextEventNumber: number;
readonly lastEventNumber: Long; readonly lastEventNumber: number;
readonly isEndOfStream: boolean; readonly isEndOfStream: boolean;
} }
@ -158,7 +159,7 @@ export interface EventStoreTransaction {
export interface EventReadResult { export interface EventReadResult {
readonly status: string; readonly status: string;
readonly stream: string; readonly stream: string;
readonly eventNumber: Long; readonly eventNumber: number;
readonly event: ResolvedEvent | null; readonly event: ResolvedEvent | null;
} }
@ -166,7 +167,7 @@ export interface EventStoreSubscription {
readonly isSubscribedToAll: boolean; readonly isSubscribedToAll: boolean;
readonly streamId: string; readonly streamId: string;
readonly lastCommitPosition: Position; readonly lastCommitPosition: Position;
readonly lastEventNumber: Long; readonly lastEventNumber: number;
close(): void; close(): void;
unsubscribe(): void; unsubscribe(): void;
@ -193,7 +194,7 @@ export interface EventStorePersistentSubscription {
export interface RawStreamMetadataResult { export interface RawStreamMetadataResult {
readonly stream: string; readonly stream: string;
readonly isStreamDeleted: boolean; readonly isStreamDeleted: boolean;
readonly metastreamVersion: Long; readonly metastreamVersion: number;
readonly streamMetadata: any; readonly streamMetadata: any;
} }
@ -248,28 +249,28 @@ export interface EventStoreNodeConnection {
connect(): Promise<void>; connect(): Promise<void>;
close(): void; close(): void;
// write actions // write actions
deleteStream(stream: string, expectedVersion: Long|number, hardDelete?: boolean, userCredentials?: UserCredentials): Promise<DeleteResult>; deleteStream(stream: string, expectedVersion: number, hardDelete?: boolean, userCredentials?: UserCredentials): Promise<DeleteResult>;
appendToStream(stream: string, expectedVersion: Long|number, eventOrEvents: EventData | EventData[], userCredentials?: UserCredentials): Promise<WriteResult>; appendToStream(stream: string, expectedVersion: number, eventOrEvents: EventData | EventData[], userCredentials?: UserCredentials): Promise<WriteResult>;
startTransaction(stream: string, expectedVersion: Long|number, userCredentials?: UserCredentials): Promise<EventStoreTransaction>; startTransaction(stream: string, expectedVersion: number, userCredentials?: UserCredentials): Promise<EventStoreTransaction>;
continueTransaction(transactionId: number, userCredentials?: UserCredentials): EventStoreTransaction; continueTransaction(transactionId: number, userCredentials?: UserCredentials): EventStoreTransaction;
// read actions // read actions
readEvent(stream: string, eventNumber: Long|number, resolveLinkTos?: boolean, userCredentials?: UserCredentials): Promise<EventReadResult>; readEvent(stream: string, eventNumber: number, resolveLinkTos?: boolean, userCredentials?: UserCredentials): Promise<EventReadResult>;
readStreamEventsForward(stream: string, start: Long|number, count: number, resolveLinkTos?: boolean, userCredentials?: UserCredentials): Promise<StreamEventsSlice>; readStreamEventsForward(stream: string, start: number, count: number, resolveLinkTos?: boolean, userCredentials?: UserCredentials): Promise<StreamEventsSlice>;
readStreamEventsBackward(stream: string, start: Long|number, count: number, resolveLinkTos?: boolean, userCredentials?: UserCredentials): Promise<StreamEventsSlice>; readStreamEventsBackward(stream: string, start: number, count: number, resolveLinkTos?: boolean, userCredentials?: UserCredentials): Promise<StreamEventsSlice>;
readAllEventsForward(position: Position, maxCount: number, resolveLinkTos?: boolean, userCredentials?: UserCredentials): Promise<AllEventsSlice>; readAllEventsForward(position: Position, maxCount: number, resolveLinkTos?: boolean, userCredentials?: UserCredentials): Promise<AllEventsSlice>;
readAllEventsBackward(position: Position, maxCount: number, resolveLinkTos?: boolean, userCredentials?: UserCredentials): Promise<AllEventsSlice>; readAllEventsBackward(position: Position, maxCount: number, resolveLinkTos?: boolean, userCredentials?: UserCredentials): Promise<AllEventsSlice>;
// subscription actions // subscription actions
subscribeToStream(stream: string, resolveLinkTos: boolean, eventAppeared: EventAppearedCallback<EventStoreSubscription>, subscriptionDropped?: SubscriptionDroppedCallback<EventStoreSubscription>, userCredentials?: UserCredentials): Promise<EventStoreSubscription>; subscribeToStream(stream: string, resolveLinkTos: boolean, eventAppeared: EventAppearedCallback<EventStoreSubscription>, subscriptionDropped?: SubscriptionDroppedCallback<EventStoreSubscription>, userCredentials?: UserCredentials): Promise<EventStoreSubscription>;
subscribeToStreamFrom(stream: string, lastCheckpoint: Long|number|null, resolveLinkTos: boolean, eventAppeared: EventAppearedCallback<EventStoreCatchUpSubscription>, liveProcessingStarted?: LiveProcessingStartedCallback, subscriptionDropped?: SubscriptionDroppedCallback<EventStoreCatchUpSubscription>, userCredentials?: UserCredentials, readBatchSize?: number): EventStoreCatchUpSubscription; subscribeToStreamFrom(stream: string, lastCheckpoint: number | null, resolveLinkTos: boolean, eventAppeared: EventAppearedCallback<EventStoreCatchUpSubscription>, liveProcessingStarted?: LiveProcessingStartedCallback, subscriptionDropped?: SubscriptionDroppedCallback<EventStoreCatchUpSubscription>, userCredentials?: UserCredentials, readBatchSize?: number): EventStoreCatchUpSubscription;
subscribeToAll(resolveLinkTos: boolean, eventAppeared: EventAppearedCallback<EventStoreSubscription>, subscriptionDropped?: SubscriptionDroppedCallback<EventStoreSubscription>, userCredentials?: UserCredentials): Promise<EventStoreSubscription>; subscribeToAll(resolveLinkTos: boolean, eventAppeared: EventAppearedCallback<EventStoreSubscription>, subscriptionDropped?: SubscriptionDroppedCallback<EventStoreSubscription>, userCredentials?: UserCredentials): Promise<EventStoreSubscription>;
subscribeToAllFrom(lastCheckpoint: Position|null, resolveLinkTos: boolean, eventAppeared: EventAppearedCallback<EventStoreCatchUpSubscription>, liveProcessingStarted?: LiveProcessingStartedCallback, subscriptionDropped?: SubscriptionDroppedCallback<EventStoreCatchUpSubscription>, userCredentials?: UserCredentials, readBatchSize?: number): EventStoreCatchUpSubscription; subscribeToAllFrom(lastCheckpoint: Position | null, resolveLinkTos: boolean, eventAppeared: EventAppearedCallback<EventStoreCatchUpSubscription>, liveProcessingStarted?: LiveProcessingStartedCallback, subscriptionDropped?: SubscriptionDroppedCallback<EventStoreCatchUpSubscription>, userCredentials?: UserCredentials, readBatchSize?: number): EventStoreCatchUpSubscription;
// persistent subscriptions // persistent subscriptions
createPersistentSubscription(stream: string, groupName: string, settings: PersistentSubscriptionSettings, userCredentials?: PersistentSubscriptionSettings): Promise<PersistentSubscriptionCreateResult>; createPersistentSubscription(stream: string, groupName: string, settings: PersistentSubscriptionSettings, userCredentials?: PersistentSubscriptionSettings): Promise<PersistentSubscriptionCreateResult>;
updatePersistentSubscription(stream: string, groupName: string, settings: PersistentSubscriptionSettings, userCredentials?: PersistentSubscriptionSettings): Promise<PersistentSubscriptionUpdateResult>; updatePersistentSubscription(stream: string, groupName: string, settings: PersistentSubscriptionSettings, userCredentials?: PersistentSubscriptionSettings): Promise<PersistentSubscriptionUpdateResult>;
deletePersistentSubscription(stream: string, groupName: string, userCredentials?: PersistentSubscriptionSettings): Promise<PersistentSubscriptionDeleteResult> deletePersistentSubscription(stream: string, groupName: string, userCredentials?: PersistentSubscriptionSettings): Promise<PersistentSubscriptionDeleteResult>
connectToPersistentSubscription(stream: string, groupName: string, eventAppeared: EventAppearedCallback<EventStorePersistentSubscription>, subscriptionDropped?: SubscriptionDroppedCallback<EventStorePersistentSubscription>, userCredentials?: UserCredentials, bufferSize?: number, autoAck?: boolean): Promise<EventStorePersistentSubscription>; connectToPersistentSubscription(stream: string, groupName: string, eventAppeared: EventAppearedCallback<EventStorePersistentSubscription>, subscriptionDropped?: SubscriptionDroppedCallback<EventStorePersistentSubscription>, userCredentials?: UserCredentials, bufferSize?: number, autoAck?: boolean): Promise<EventStorePersistentSubscription>;
// metadata actions // metadata actions
setStreamMetadataRaw(stream: string, expectedMetastreamVersion: Long|number, metadata: any, userCredentials?: UserCredentials): Promise<WriteResult>; setStreamMetadataRaw(stream: string, expectedMetastreamVersion: number, metadata: any, userCredentials?: UserCredentials): Promise<WriteResult>;
getStreamMetadataRaw(stream: string, userCredentials?: UserCredentials): Promise<RawStreamMetadataResult>; getStreamMetadataRaw(stream: string, userCredentials?: UserCredentials): Promise<RawStreamMetadataResult>;
on(event: "connected" | "disconnected" | "reconnecting" | "closed" | "error" | "heartbeatInfo", listener: (arg: Error | string | TcpEndPoint | HeartbeatInfo) => void): this; on(event: "connected" | "disconnected" | "reconnecting" | "closed" | "error" | "heartbeatInfo", listener: (arg: Error | string | TcpEndPoint | HeartbeatInfo) => void): this;

View File

@ -1,6 +1,6 @@
{ {
"name": "node-eventstore-client", "name": "node-eventstore-client",
"version": "0.2.1", "version": "0.1.11",
"description": "A port of the EventStore .Net ClientAPI to Node.js", "description": "A port of the EventStore .Net ClientAPI to Node.js",
"main": "index.js", "main": "index.js",
"types": "index.d.ts", "types": "index.d.ts",

View File

@ -1,5 +1,3 @@
var Long = require('long');
module.exports.notNullOrEmpty = function(value, name) { module.exports.notNullOrEmpty = function(value, name) {
if (value === null) if (value === null)
throw new TypeError(name + " should not be null."); throw new TypeError(name + " should not be null.");
@ -12,18 +10,9 @@ module.exports.notNull = function(value, name) {
throw new TypeError(name + " should not be null."); throw new TypeError(name + " should not be null.");
}; };
function isInteger(value, name) { module.exports.isInteger = function(value, name) {
if (typeof value !== 'number' || value % 1 !== 0) if (typeof value !== 'number' || value % 1 !== 0)
throw new TypeError(name + " should be an integer."); throw new TypeError(name + " should be an integer.");
}
module.exports.isInteger = isInteger;
module.exports.isLongOrInteger = function(value, name) {
if (typeof value === 'number') {
return isInteger(value, name);
} else if (!Long.isLong(value)) {
throw new TypeError(name + " should be a Long|number.");
}
}; };
module.exports.isArrayOf = function(expectedType, value, name) { module.exports.isArrayOf = function(expectedType, value, name) {

View File

@ -9,8 +9,6 @@ var SubscriptionsManager = require('./subscriptionsManager');
var VolatileSubscriptionOperation = require('../clientOperations/volatileSubscriptionOperation'); var VolatileSubscriptionOperation = require('../clientOperations/volatileSubscriptionOperation');
var ConnectToPersistentSubscriptionOperation = require('../clientOperations/connectToPersistentSubscriptionOperation'); var ConnectToPersistentSubscriptionOperation = require('../clientOperations/connectToPersistentSubscriptionOperation');
var messages = require('./messages'); var messages = require('./messages');
var ClientMessage = require('../messages/clientMessage');
var createBufferSegment = require('../common/bufferSegment');
var TcpPackage = require('../systemData/tcpPackage'); var TcpPackage = require('../systemData/tcpPackage');
var TcpCommand = require('../systemData/tcpCommand'); var TcpCommand = require('../systemData/tcpCommand');
@ -30,14 +28,12 @@ const ConnectingPhase = {
EndPointDiscovery: 'endpointDiscovery', EndPointDiscovery: 'endpointDiscovery',
ConnectionEstablishing: 'connectionEstablishing', ConnectionEstablishing: 'connectionEstablishing',
Authentication: 'authentication', Authentication: 'authentication',
Identification: 'identification',
Connected: 'connected' Connected: 'connected'
}; };
const TimerPeriod = 200; const TimerPeriod = 200;
const TimerTickMessage = new messages.TimerTickMessage(); const TimerTickMessage = new messages.TimerTickMessage();
const EmptyGuid = '00000000-0000-0000-0000-000000000000'; const EmptyGuid = '00000000-0000-0000-0000-000000000000';
const ClientVersion = 1;
/** /**
* @private * @private
@ -396,21 +392,10 @@ EventStoreConnectionLogicHandler.prototype._tcpConnectionEstablished = function(
} }
else else
{ {
this._goToIdentifiedState(); this._goToConnectedState();
} }
}; };
EventStoreConnectionLogicHandler.prototype._goToIdentifiedState = function() {
this._connectingPhase = ConnectingPhase.Identification;
this._identityInfo = {
correlationId: uuid.v4(),
timeStamp: Date.now()
};
var dto = new ClientMessage.IdentifyClient({version: ClientVersion, connectionName: this._esConnection.connectionName});
var buf = dto.constructor.encode(dto).finish();
this._connection.enqueueSend(new TcpPackage(TcpCommand.IdentifyClient, TcpFlags.None, this._identityInfo.correlationId, null, null, createBufferSegment(buf)))
};
EventStoreConnectionLogicHandler.prototype._goToConnectedState = function() { EventStoreConnectionLogicHandler.prototype._goToConnectedState = function() {
this._state = ConnectionState.Connected; this._state = ConnectionState.Connected;
this._connectingPhase = ConnectingPhase.Connected; this._connectingPhase = ConnectingPhase.Connected;
@ -514,16 +499,6 @@ EventStoreConnectionLogicHandler.prototype._handleTcpPackage = function(connecti
if (pkg.command === TcpCommand.NotAuthenticated) if (pkg.command === TcpCommand.NotAuthenticated)
this.emit('authenticationFailed', "Not authenticated"); this.emit('authenticationFailed', "Not authenticated");
this._goToIdentifiedState();
return;
}
}
if (pkg.command === TcpCommand.ClientIdentified)
{
if (this._state === ConnectionState.Connecting
&& this._identityInfo.correlationId === pkg.correlationId)
{
this._goToConnectedState(); this._goToConnectedState();
return; return;
} }
@ -643,11 +618,7 @@ EventStoreConnectionLogicHandler.prototype._timerTick = function() {
else if (this._connectingPhase === ConnectingPhase.Authentication && (Date.now() - this._authInfo.timeStamp) >= this._settings.operationTimeout) else if (this._connectingPhase === ConnectingPhase.Authentication && (Date.now() - this._authInfo.timeStamp) >= this._settings.operationTimeout)
{ {
this.emit('authenticationFailed', "Authentication timed out."); this.emit('authenticationFailed', "Authentication timed out.");
if (this._clientVersion === 1) { this._goToConnectedState();
this._goToIdentifiedState();
} else {
this._goToConnectedState();
}
} }
else if (this._connectingPhase === ConnectingPhase.Authentication || this._connectingPhase === ConnectingPhase.Connected) else if (this._connectingPhase === ConnectingPhase.Authentication || this._connectingPhase === ConnectingPhase.Connected)
this._manageHeartbeats(); this._manageHeartbeats();

View File

@ -1,6 +1,5 @@
var util = require('util'); var util = require('util');
var uuid = require('uuid'); var uuid = require('uuid');
var Long = require('long');
var EventEmitter = require('events').EventEmitter; var EventEmitter = require('events').EventEmitter;
var ensure = require('./common/utils/ensure'); var ensure = require('./common/utils/ensure');
@ -102,16 +101,15 @@ EventStoreNodeConnection.prototype.close = function() {
* Delete a stream (async) * Delete a stream (async)
* @public * @public
* @param {string} stream * @param {string} stream
* @param {Long|number} expectedVersion * @param {number} expectedVersion
* @param {boolean} [hardDelete] * @param {boolean} [hardDelete]
* @param {UserCredentials} [userCredentials] * @param {UserCredentials} [userCredentials]
* @returns {Promise.<DeleteResult>} * @returns {Promise.<DeleteResult>}
*/ */
EventStoreNodeConnection.prototype.deleteStream = function(stream, expectedVersion, hardDelete, userCredentials) { EventStoreNodeConnection.prototype.deleteStream = function(stream, expectedVersion, hardDelete, userCredentials) {
ensure.notNullOrEmpty(stream, "stream"); ensure.notNullOrEmpty(stream, "stream");
ensure.isLongOrInteger(expectedVersion, "expectedVersion"); ensure.isInteger(expectedVersion, "expectedVersion");
expectedVersion = Long.fromValue(expectedVersion); hardDelete = !!hardDelete;
hardDelete = Boolean(hardDelete);
userCredentials = userCredentials || null; userCredentials = userCredentials || null;
var self = this; var self = this;
@ -131,15 +129,14 @@ EventStoreNodeConnection.prototype.deleteStream = function(stream, expectedVersi
* Append events to a stream (async) * Append events to a stream (async)
* @public * @public
* @param {string} stream The name of the stream to which to append. * @param {string} stream The name of the stream to which to append.
* @param {Long|number} expectedVersion The version at which we currently expect the stream to be in order that an optimistic concurrency check can be performed. * @param {number} expectedVersion The version at which we currently expect the stream to be in order that an optimistic concurrency check can be performed.
* @param {EventData[]|EventData} events The event(s) to append. * @param {EventData[]|EventData} events The event(s) to append.
* @param {UserCredentials} [userCredentials] User credentials * @param {UserCredentials} [userCredentials] User credentials
* @returns {Promise.<WriteResult>} * @returns {Promise.<WriteResult>}
*/ */
EventStoreNodeConnection.prototype.appendToStream = function(stream, expectedVersion, events, userCredentials) { EventStoreNodeConnection.prototype.appendToStream = function(stream, expectedVersion, events, userCredentials) {
ensure.notNullOrEmpty(stream, "stream"); ensure.notNullOrEmpty(stream, "stream");
ensure.isLongOrInteger(expectedVersion, "expectedVersion"); ensure.isInteger(expectedVersion, "expectedVersion");
expectedVersion = Long.fromValue(expectedVersion);
if (!Array.isArray(events)) if (!Array.isArray(events))
events = [events]; events = [events];
ensure.isArrayOf(EventData, events, "events"); ensure.isArrayOf(EventData, events, "events");
@ -161,14 +158,13 @@ EventStoreNodeConnection.prototype.appendToStream = function(stream, expectedVer
* Start a transaction (async) * Start a transaction (async)
* @public * @public
* @param {string} stream * @param {string} stream
* @param {Long|number} expectedVersion * @param {number} expectedVersion
* @param {UserCredentials} [userCredentials] * @param {UserCredentials} [userCredentials]
* @returns {Promise.<EventStoreTransaction>} * @returns {Promise.<EventStoreTransaction>}
*/ */
EventStoreNodeConnection.prototype.startTransaction = function(stream, expectedVersion, userCredentials) { EventStoreNodeConnection.prototype.startTransaction = function(stream, expectedVersion, userCredentials) {
ensure.notNullOrEmpty(stream, "stream"); ensure.notNullOrEmpty(stream, "stream");
ensure.isLongOrInteger(expectedVersion, "expectedVersion"); ensure.isInteger(expectedVersion, "expectedVersion");
expectedVersion = Long.fromValue(expectedVersion);
userCredentials = userCredentials || null; userCredentials = userCredentials || null;
var self = this; var self = this;
@ -239,20 +235,21 @@ EventStoreNodeConnection.prototype.commitTransaction = function(transaction, use
* Read a single event (async) * Read a single event (async)
* @public * @public
* @param {string} stream * @param {string} stream
* @param {Long|number} eventNumber * @param {number} eventNumber
* @param {boolean} [resolveLinkTos] * @param {boolean} [resolveLinkTos]
* @param {UserCredentials} [userCredentials] * @param {UserCredentials} [userCredentials]
* @returns {Promise.<EventReadResult>} * @returns {Promise.<EventReadResult>}
*/ */
EventStoreNodeConnection.prototype.readEvent = function(stream, eventNumber, resolveLinkTos, userCredentials) { EventStoreNodeConnection.prototype.readEvent = function(stream, eventNumber, resolveLinkTos, userCredentials) {
ensure.notNullOrEmpty(stream, "stream"); ensure.notNullOrEmpty(stream, "stream");
ensure.isLongOrInteger(eventNumber, "eventNumber"); ensure.isInteger(eventNumber, "eventNumber");
eventNumber = Long.fromValue(eventNumber); if (eventNumber < -1) throw new Error("eventNumber out of range.");
resolveLinkTos = Boolean(resolveLinkTos); resolveLinkTos = !!resolveLinkTos;
userCredentials = userCredentials || null; userCredentials = userCredentials || null;
if (typeof stream !== 'string' || stream === '') throw new TypeError("stream must be an non-empty string."); if (typeof stream !== 'string' || stream === '') throw new TypeError("stream must be an non-empty string.");
if (eventNumber.compare(-1) < 0) throw new Error("eventNumber out of range."); if (typeof eventNumber !== 'number' || eventNumber % 1 !== 0) throw new TypeError("eventNumber must be an integer.");
if (eventNumber < -1) throw new Error("eventNumber out of range.");
if (resolveLinkTos && typeof resolveLinkTos !== 'boolean') throw new TypeError("resolveLinkTos must be a boolean."); if (resolveLinkTos && typeof resolveLinkTos !== 'boolean') throw new TypeError("resolveLinkTos must be a boolean.");
var self = this; var self = this;
@ -271,7 +268,7 @@ EventStoreNodeConnection.prototype.readEvent = function(stream, eventNumber, res
* Reading a specific stream forwards (async) * Reading a specific stream forwards (async)
* @public * @public
* @param {string} stream * @param {string} stream
* @param {Long|number} start * @param {number} start
* @param {number} count * @param {number} count
* @param {boolean} [resolveLinkTos] * @param {boolean} [resolveLinkTos]
* @param {UserCredentials} [userCredentials] * @param {UserCredentials} [userCredentials]
@ -281,13 +278,12 @@ EventStoreNodeConnection.prototype.readStreamEventsForward = function(
stream, start, count, resolveLinkTos, userCredentials stream, start, count, resolveLinkTos, userCredentials
) { ) {
ensure.notNullOrEmpty(stream, "stream"); ensure.notNullOrEmpty(stream, "stream");
ensure.isLongOrInteger(start, "start"); ensure.isInteger(start, "start");
start = Long.fromValue(start);
ensure.nonNegative(start, "start"); ensure.nonNegative(start, "start");
ensure.isInteger(count, "count"); ensure.isInteger(count, "count");
ensure.positive(count, "count"); ensure.positive(count, "count");
if (count > MaxReadSize) throw new Error(util.format("Count should be less than %d. For larger reads you should page.", MaxReadSize)); if (count > MaxReadSize) throw new Error(util.format("Count should be less than %d. For larger reads you should page.", MaxReadSize));
resolveLinkTos = Boolean(resolveLinkTos); resolveLinkTos = !!resolveLinkTos;
userCredentials = userCredentials || null; userCredentials = userCredentials || null;
var self = this; var self = this;
@ -306,7 +302,7 @@ EventStoreNodeConnection.prototype.readStreamEventsForward = function(
* Reading a specific stream backwards (async) * Reading a specific stream backwards (async)
* @public * @public
* @param {string} stream * @param {string} stream
* @param {Long|number} start * @param {number} start
* @param {number} count * @param {number} count
* @param {boolean} [resolveLinkTos] * @param {boolean} [resolveLinkTos]
* @param {UserCredentials} [userCredentials] * @param {UserCredentials} [userCredentials]
@ -316,12 +312,11 @@ EventStoreNodeConnection.prototype.readStreamEventsBackward = function(
stream, start, count, resolveLinkTos, userCredentials stream, start, count, resolveLinkTos, userCredentials
) { ) {
ensure.notNullOrEmpty(stream, "stream"); ensure.notNullOrEmpty(stream, "stream");
ensure.isLongOrInteger(start, "start"); ensure.isInteger(start, "start");
start = Long.fromValue(start);
ensure.isInteger(count, "count"); ensure.isInteger(count, "count");
ensure.positive(count, "count"); ensure.positive(count, "count");
if (count > MaxReadSize) throw new Error(util.format("Count should be less than %d. For larger reads you should page.", MaxReadSize)); if (count > MaxReadSize) throw new Error(util.format("Count should be less than %d. For larger reads you should page.", MaxReadSize));
resolveLinkTos = Boolean(resolveLinkTos); resolveLinkTos = !!resolveLinkTos;
userCredentials = userCredentials || null; userCredentials = userCredentials || null;
var self = this; var self = this;
@ -352,7 +347,7 @@ EventStoreNodeConnection.prototype.readAllEventsForward = function(
ensure.isInteger(maxCount, "maxCount"); ensure.isInteger(maxCount, "maxCount");
ensure.positive(maxCount, "maxCount"); ensure.positive(maxCount, "maxCount");
if (maxCount > MaxReadSize) throw new Error(util.format("Count should be less than %d. For larger reads you should page.", MaxReadSize)); if (maxCount > MaxReadSize) throw new Error(util.format("Count should be less than %d. For larger reads you should page.", MaxReadSize));
resolveLinkTos = Boolean(resolveLinkTos); resolveLinkTos = !!resolveLinkTos;
userCredentials = userCredentials || null; userCredentials = userCredentials || null;
var self = this; var self = this;
@ -383,7 +378,7 @@ EventStoreNodeConnection.prototype.readAllEventsBackward = function(
ensure.isInteger(maxCount, "maxCount"); ensure.isInteger(maxCount, "maxCount");
ensure.positive(maxCount, "maxCount"); ensure.positive(maxCount, "maxCount");
if (maxCount > MaxReadSize) throw new Error(util.format("Count should be less than %d. For larger reads you should page.", MaxReadSize)); if (maxCount > MaxReadSize) throw new Error(util.format("Count should be less than %d. For larger reads you should page.", MaxReadSize));
resolveLinkTos = Boolean(resolveLinkTos); resolveLinkTos = !!resolveLinkTos;
userCredentials = userCredentials || null; userCredentials = userCredentials || null;
var self = this; var self = this;
@ -433,7 +428,7 @@ EventStoreNodeConnection.prototype.subscribeToStream = function(
* Subscribe to a stream from position * Subscribe to a stream from position
* @public * @public
* @param {!string} stream * @param {!string} stream
* @param {?number|Position} lastCheckpoint * @param {?number} lastCheckpoint
* @param {!boolean} resolveLinkTos * @param {!boolean} resolveLinkTos
* @param {!function} eventAppeared * @param {!function} eventAppeared
* @param {function} [liveProcessingStarted] * @param {function} [liveProcessingStarted]
@ -447,10 +442,7 @@ EventStoreNodeConnection.prototype.subscribeToStreamFrom = function(
userCredentials, readBatchSize userCredentials, readBatchSize
) { ) {
if (typeof stream !== 'string' || stream === '') throw new TypeError("stream must be a non-empty string."); if (typeof stream !== 'string' || stream === '') throw new TypeError("stream must be a non-empty string.");
if (lastCheckpoint !== null) { if (lastCheckpoint !== null && typeof lastCheckpoint !== 'number') throw new TypeError("lastCheckpoint must be a number or null.");
ensure.isLongOrInteger(lastCheckpoint);
lastCheckpoint = Long.fromValue(lastCheckpoint);
}
if (typeof eventAppeared !== 'function') throw new TypeError("eventAppeared must be a function."); if (typeof eventAppeared !== 'function') throw new TypeError("eventAppeared must be a function.");
var catchUpSubscription = var catchUpSubscription =
@ -540,7 +532,7 @@ EventStoreNodeConnection.prototype.connectToPersistentSubscription = function(
subscriptionDropped = subscriptionDropped || null; subscriptionDropped = subscriptionDropped || null;
userCredentials = userCredentials || null; userCredentials = userCredentials || null;
bufferSize = bufferSize === undefined ? 10 : bufferSize; bufferSize = bufferSize === undefined ? 10 : bufferSize;
autoAck = autoAck === undefined ? true : Boolean(autoAck); autoAck = autoAck === undefined ? true : !!autoAck;
var subscription = new EventStorePersistentSubscription( var subscription = new EventStorePersistentSubscription(
groupName, stream, eventAppeared, subscriptionDropped, userCredentials, this._settings.log, groupName, stream, eventAppeared, subscriptionDropped, userCredentials, this._settings.log,
@ -632,7 +624,7 @@ EventStoreNodeConnection.prototype.setStreamMetadata = function() {
* Set stream metadata with raw object (async) * Set stream metadata with raw object (async)
* @public * @public
* @param {string} stream * @param {string} stream
* @param {Long|number} expectedMetastreamVersion * @param {number} expectedMetastreamVersion
* @param {object} metadata * @param {object} metadata
* @param {UserCredentials} [userCredentials] * @param {UserCredentials} [userCredentials]
* @returns {Promise.<WriteResult>} * @returns {Promise.<WriteResult>}
@ -643,8 +635,6 @@ EventStoreNodeConnection.prototype.setStreamMetadataRaw = function(
ensure.notNullOrEmpty(stream, "stream"); ensure.notNullOrEmpty(stream, "stream");
if (systemStreams.isMetastream(stream)) if (systemStreams.isMetastream(stream))
throw new Error(util.format("Setting metadata for metastream '%s' is not supported.", stream)); throw new Error(util.format("Setting metadata for metastream '%s' is not supported.", stream));
ensure.isLongOrInteger(expectedMetastreamVersion, "expectedMetastreamVersion");
expectedMetastreamVersion = Long.fromValue(expectedMetastreamVersion);
var self = this; var self = this;
return new Promise(function(resolve, reject) { return new Promise(function(resolve, reject) {
function cb(err, result) { function cb(err, result) {
@ -687,12 +677,12 @@ EventStoreNodeConnection.prototype.getStreamMetadataRaw = function(stream, userC
var evnt = res.event.originalEvent; var evnt = res.event.originalEvent;
var version = evnt ? evnt.eventNumber : -1; var version = evnt ? evnt.eventNumber : -1;
var data = evnt ? JSON.parse(evnt.data.toString()) : null; var data = evnt ? JSON.parse(evnt.data.toString()) : null;
return new results.RawStreamMetadataResult(stream, false, Long.fromValue(version), data); return new results.RawStreamMetadataResult(stream, false, version, data);
case results.EventReadStatus.NotFound: case results.EventReadStatus.NotFound:
case results.EventReadStatus.NoStream: case results.EventReadStatus.NoStream:
return new results.RawStreamMetadataResult(stream, false, Long.fromValue(-1), null); return new results.RawStreamMetadataResult(stream, false, -1, null);
case results.EventReadStatus.StreamDeleted: case results.EventReadStatus.StreamDeleted:
return new results.RawStreamMetadataResult(stream, true, Long.fromValue(0x7fffffff), null); return new results.RawStreamMetadataResult(stream, true, 0x7fffffff, null);
default: default:
throw new Error(util.format("Unexpected ReadEventResult: %s.", res.status)); throw new Error(util.format("Unexpected ReadEventResult: %s.", res.status));
} }

View File

@ -1,5 +1,4 @@
var util = require('util'); var util = require('util');
var Long = require('long');
var EventStoreCatchUpSubscription = require('./eventStoreCatchUpSubscription'); var EventStoreCatchUpSubscription = require('./eventStoreCatchUpSubscription');
var SliceReadStatus = require('./sliceReadStatus'); var SliceReadStatus = require('./sliceReadStatus');
@ -15,8 +14,8 @@ function EventStoreStreamCatchUpSubscription(
//Ensure.NotNullOrEmpty(streamId, "streamId"); //Ensure.NotNullOrEmpty(streamId, "streamId");
this._lastProcessedEventNumber = fromEventNumberExclusive === null ? Long.fromNumber(-1) : fromEventNumberExclusive; this._lastProcessedEventNumber = fromEventNumberExclusive === null ? -1 : fromEventNumberExclusive;
this._nextReadEventNumber = fromEventNumberExclusive === null ? Long.fromNumber(0) : fromEventNumberExclusive.add(1); this._nextReadEventNumber = fromEventNumberExclusive === null ? 0 : fromEventNumberExclusive + 1;
} }
util.inherits(EventStoreStreamCatchUpSubscription, EventStoreCatchUpSubscription); util.inherits(EventStoreStreamCatchUpSubscription, EventStoreCatchUpSubscription);
@ -48,14 +47,14 @@ EventStoreStreamCatchUpSubscription.prototype._readEventsTill = function(
return processEvents(slice.events, 0) return processEvents(slice.events, 0)
.then(function() { .then(function() {
self._nextReadEventNumber = slice.nextEventNumber; self._nextReadEventNumber = slice.nextEventNumber;
var done = Promise.resolve(lastEventNumber === null ? slice.isEndOfStream : slice.nextEventNumber.compare(lastEventNumber) > 0); var done = Promise.resolve(lastEventNumber === null ? slice.isEndOfStream : slice.nextEventNumber > lastEventNumber);
if (!done && slice.isEndOfStream) if (!done && slice.isEndOfStream)
return delay(100, false); return delay(100, false);
return done; return done;
}); });
break; break;
case SliceReadStatus.StreamNotFound: case SliceReadStatus.StreamNotFound:
if (lastEventNumber && lastEventNumber.compare(-1) !== 0) if (lastEventNumber && lastEventNumber !== -1)
throw new Error(util.format("Impossible: stream %s disappeared in the middle of catching up subscription.", self.streamId)); throw new Error(util.format("Impossible: stream %s disappeared in the middle of catching up subscription.", self.streamId));
return true; return true;
case SliceReadStatus.StreamDeleted: case SliceReadStatus.StreamDeleted:
@ -81,7 +80,7 @@ EventStoreStreamCatchUpSubscription.prototype._readEventsTill = function(
EventStoreStreamCatchUpSubscription.prototype._tryProcess = function(e) { EventStoreStreamCatchUpSubscription.prototype._tryProcess = function(e) {
var processed = false; var processed = false;
var promise; var promise;
if (e.originalEventNumber.compare(this._lastProcessedEventNumber) > 0) { if (e.originalEventNumber > this._lastProcessedEventNumber) {
promise = this._eventAppeared(this, e); promise = this._eventAppeared(this, e);
this._lastProcessedEventNumber = e.originalEventNumber; this._lastProcessedEventNumber = e.originalEventNumber;
processed = true; processed = true;
@ -89,7 +88,7 @@ EventStoreStreamCatchUpSubscription.prototype._tryProcess = function(e) {
if (this._verbose) if (this._verbose)
this._log.debug("Catch-up Subscription to %s: %s event (%s, %d, %s @ %d).", this._log.debug("Catch-up Subscription to %s: %s event (%s, %d, %s @ %d).",
this.isSubscribedToAll ? '<all>' : this.streamId, processed ? "processed" : "skipping", this.isSubscribedToAll ? '<all>' : this.streamId, processed ? "processed" : "skipping",
e.originalEvent.eventStreamId, e.originalEvent.eventNumber, e.originalEvent.eventType, e.originalEventNumber); e.originalEvent.eventStreamId, e.originalEvent.eventNumber, e.originalEvent.eventType, e.originalEventNumber)
return (promise && promise.then) ? promise : Promise.resolve(); return (promise && promise.then) ? promise : Promise.resolve();
}; };

File diff suppressed because it is too large Load Diff

View File

@ -23,7 +23,7 @@ message NewEvent {
message EventRecord { message EventRecord {
required string event_stream_id = 1; required string event_stream_id = 1;
required int64 event_number = 2; required int32 event_number = 2;
required bytes event_id = 3; required bytes event_id = 3;
required string event_type = 4; required string event_type = 4;
required int32 data_content_type = 5; required int32 data_content_type = 5;
@ -48,7 +48,7 @@ message ResolvedEvent {
message WriteEvents { message WriteEvents {
required string event_stream_id = 1; required string event_stream_id = 1;
required int64 expected_version = 2; required int32 expected_version = 2;
repeated NewEvent events = 3; repeated NewEvent events = 3;
required bool require_master = 4; required bool require_master = 4;
} }
@ -56,16 +56,15 @@ message WriteEvents {
message WriteEventsCompleted { message WriteEventsCompleted {
required OperationResult result = 1; required OperationResult result = 1;
optional string message = 2; optional string message = 2;
required int64 first_event_number = 3; required int32 first_event_number = 3;
required int64 last_event_number = 4; required int32 last_event_number = 4;
optional int64 prepare_position = 5; optional int64 prepare_position = 5;
optional int64 commit_position = 6; optional int64 commit_position = 6;
optional int64 current_version = 7;
} }
message DeleteStream { message DeleteStream {
required string event_stream_id = 1; required string event_stream_id = 1;
required int64 expected_version = 2; required int32 expected_version = 2;
required bool require_master = 3; required bool require_master = 3;
optional bool hard_delete = 4; optional bool hard_delete = 4;
} }
@ -79,7 +78,7 @@ message DeleteStreamCompleted {
message TransactionStart { message TransactionStart {
required string event_stream_id = 1; required string event_stream_id = 1;
required int64 expected_version = 2; required int32 expected_version = 2;
required bool require_master = 3; required bool require_master = 3;
} }
@ -110,15 +109,15 @@ message TransactionCommitCompleted {
required int64 transaction_id = 1; required int64 transaction_id = 1;
required OperationResult result = 2; required OperationResult result = 2;
optional string message = 3; optional string message = 3;
required int64 first_event_number = 4; required int32 first_event_number = 4;
required int64 last_event_number = 5; required int32 last_event_number = 5;
optional int64 prepare_position = 6; optional int64 prepare_position = 6;
optional int64 commit_position = 7; optional int64 commit_position = 7;
} }
message ReadEvent { message ReadEvent {
required string event_stream_id = 1; required string event_stream_id = 1;
required int64 event_number = 2; required int32 event_number = 2;
required bool resolve_link_tos = 3; required bool resolve_link_tos = 3;
required bool require_master = 4; required bool require_master = 4;
} }
@ -142,7 +141,7 @@ message ReadEventCompleted {
message ReadStreamEvents { message ReadStreamEvents {
required string event_stream_id = 1; required string event_stream_id = 1;
required int64 from_event_number = 2; required int32 from_event_number = 2;
required int32 max_count = 3; required int32 max_count = 3;
required bool resolve_link_tos = 4; required bool resolve_link_tos = 4;
required bool require_master = 5; required bool require_master = 5;
@ -161,8 +160,8 @@ message ReadStreamEventsCompleted {
repeated ResolvedIndexedEvent events = 1; repeated ResolvedIndexedEvent events = 1;
required ReadStreamResult result = 2; required ReadStreamResult result = 2;
required int64 next_event_number = 3; required int32 next_event_number = 3;
required int64 last_event_number = 4; required int32 last_event_number = 4;
required bool is_end_of_stream = 5; required bool is_end_of_stream = 5;
required int64 last_commit_position = 6; required int64 last_commit_position = 6;
@ -200,7 +199,7 @@ message CreatePersistentSubscription {
required string subscription_group_name = 1; required string subscription_group_name = 1;
required string event_stream_id = 2; required string event_stream_id = 2;
required bool resolve_link_tos = 3; required bool resolve_link_tos = 3;
required int64 start_from = 4; required int32 start_from = 4;
required int32 message_timeout_milliseconds = 5; required int32 message_timeout_milliseconds = 5;
required bool record_statistics = 6; required bool record_statistics = 6;
required int32 live_buffer_size = 7; required int32 live_buffer_size = 7;
@ -224,7 +223,7 @@ message UpdatePersistentSubscription {
required string subscription_group_name = 1; required string subscription_group_name = 1;
required string event_stream_id = 2; required string event_stream_id = 2;
required bool resolve_link_tos = 3; required bool resolve_link_tos = 3;
required int64 start_from = 4; required int32 start_from = 4;
required int32 message_timeout_milliseconds = 5; required int32 message_timeout_milliseconds = 5;
required bool record_statistics = 6; required bool record_statistics = 6;
required int32 live_buffer_size = 7; required int32 live_buffer_size = 7;
@ -302,7 +301,7 @@ message PersistentSubscriptionNakEvents {
message PersistentSubscriptionConfirmation { message PersistentSubscriptionConfirmation {
required int64 last_commit_position = 1; required int64 last_commit_position = 1;
required string subscription_id = 2; required string subscription_id = 2;
optional int64 last_event_number = 3; optional int32 last_event_number = 3;
} }
message PersistentSubscriptionStreamEventAppeared { message PersistentSubscriptionStreamEventAppeared {
@ -316,7 +315,7 @@ message SubscribeToStream {
message SubscriptionConfirmation { message SubscriptionConfirmation {
required int64 last_commit_position = 1; required int64 last_commit_position = 1;
optional int64 last_event_number = 2; optional int32 last_event_number = 2;
} }
message StreamEventAppeared { message StreamEventAppeared {
@ -376,11 +375,3 @@ message ScavengeDatabaseCompleted {
required int32 total_time_ms = 3; required int32 total_time_ms = 3;
required int64 total_space_saved = 4; required int64 total_space_saved = 4;
} }
message IdentifyClient {
required int32 version = 1;
optional string connection_name = 2;
}
message ClientIdentified {
}

View File

@ -1,6 +1,4 @@
var SystemConsumerStrategies = require('./systemConsumerStrategies'); var SystemConsumerStrategies = require('./systemConsumerStrategies');
var ensure = require('./common/utils/ensure');
var Long = require('long');
function PersistentSubscriptionSettings( function PersistentSubscriptionSettings(
resolveLinkTos, startFrom, extraStatistics, messageTimeout, resolveLinkTos, startFrom, extraStatistics, messageTimeout,
@ -8,9 +6,6 @@ function PersistentSubscriptionSettings(
checkPointAfter, minCheckPointCount, maxCheckPointCount, checkPointAfter, minCheckPointCount, maxCheckPointCount,
maxSubscriberCount, namedConsumerStrategy maxSubscriberCount, namedConsumerStrategy
) { ) {
ensure.isLongOrInteger(startFrom);
startFrom = Long.fromValue(startFrom);
this.resolveLinkTos = resolveLinkTos; this.resolveLinkTos = resolveLinkTos;
this.startFrom = startFrom; this.startFrom = startFrom;
this.extraStatistics = extraStatistics; this.extraStatistics = extraStatistics;

View File

@ -44,7 +44,7 @@ Object.freeze(EventReadStatus);
* @constructor * @constructor
* @property {string} eventStreamId * @property {string} eventStreamId
* @property {string} eventId * @property {string} eventId
* @property {Long} eventNumber * @property {number} eventNumber
* @property {string} eventType * @property {string} eventType
* @property {number} createdEpoch * @property {number} createdEpoch
* @property {?Buffer} data * @property {?Buffer} data
@ -73,7 +73,7 @@ function RecordedEvent(ev) {
* @property {boolean} isResolved * @property {boolean} isResolved
* @property {?Position} originalPosition * @property {?Position} originalPosition
* @property {string} originalStreamId * @property {string} originalStreamId
* @property {Long} originalEventNumber * @property {number} originalEventNumber
*/ */
function ResolvedEvent(ev) { function ResolvedEvent(ev) {
this.event = ev.event === null ? null : new RecordedEvent(ev.event); this.event = ev.event === null ? null : new RecordedEvent(ev.event);
@ -90,12 +90,12 @@ function ResolvedEvent(ev) {
* *
* @param {string} status * @param {string} status
* @param {string} stream * @param {string} stream
* @param {Long} eventNumber * @param {number} eventNumber
* @param {object} event * @param {object} event
* @constructor * @constructor
* @property {string} status * @property {string} status
* @property {string} stream * @property {string} stream
* @property {Long} eventNumber * @property {number} eventNumber
* @property {ResolvedEvent} event * @property {ResolvedEvent} event
*/ */
function EventReadResult(status, stream, eventNumber, event) { function EventReadResult(status, stream, eventNumber, event) {
@ -110,7 +110,7 @@ function EventReadResult(status, stream, eventNumber, event) {
* @param {number} nextExpectedVersion * @param {number} nextExpectedVersion
* @param {Position} logPosition * @param {Position} logPosition
* @constructor * @constructor
* @property {Long} nextExpectedVersion * @property {number} nextExpectedVersion
* @property {Position} logPosition * @property {Position} logPosition
*/ */
function WriteResult(nextExpectedVersion, logPosition) { function WriteResult(nextExpectedVersion, logPosition) {
@ -122,20 +122,20 @@ function WriteResult(nextExpectedVersion, logPosition) {
/** /**
* @param {string} status * @param {string} status
* @param {string} stream * @param {string} stream
* @param {Long} fromEventNumber * @param {number} fromEventNumber
* @param {string} readDirection * @param {string} readDirection
* @param {object[]} events * @param {object[]} events
* @param {Long} nextEventNumber * @param {number} nextEventNumber
* @param {Long} lastEventNumber * @param {number} lastEventNumber
* @param {boolean} isEndOfStream * @param {boolean} isEndOfStream
* @constructor * @constructor
* @property {string} status * @property {string} status
* @property {string} stream * @property {string} stream
* @property {Long} fromEventNumber * @property {number} fromEventNumber
* @property {string} readDirection * @property {string} readDirection
* @property {ResolvedEvent[]} events * @property {ResolvedEvent[]} events
* @property {Long} nextEventNumber * @property {number} nextEventNumber
* @property {Long} lastEventNumber * @property {number} lastEventNumber
* @property {boolean} isEndOfStream * @property {boolean} isEndOfStream
*/ */
function StreamEventsSlice( function StreamEventsSlice(
@ -185,12 +185,12 @@ function DeleteResult(logPosition) {
/** /**
* @param {string} stream * @param {string} stream
* @param {boolean} isStreamDeleted * @param {boolean} isStreamDeleted
* @param {Long} metastreamVersion * @param {number} metastreamVersion
* @param {object} streamMetadata * @param {object} streamMetadata
* @constructor * @constructor
* @property {string} stream * @property {string} stream
* @property {boolean} isStreamDeleted * @property {boolean} isStreamDeleted
* @property {Long} metastreamVersion * @property {number} metastreamVersion
* @property {object} streamMetadata * @property {object} streamMetadata
*/ */
function RawStreamMetadataResult(stream, isStreamDeleted, metastreamVersion, streamMetadata) { function RawStreamMetadataResult(stream, isStreamDeleted, metastreamVersion, streamMetadata) {

View File

@ -71,9 +71,7 @@ const TcpCommand = {
NotHandled: 0xF1, NotHandled: 0xF1,
Authenticate: 0xF2, Authenticate: 0xF2,
Authenticated: 0xF3, Authenticated: 0xF3,
NotAuthenticated: 0xF4, NotAuthenticated: 0xF4
IdentifyClient: 0xF5,
ClientIdentified: 0xF6
}; };
var _reverseLookup = {}; var _reverseLookup = {};

View File

@ -1,17 +1,13 @@
var uuid = require('uuid'); var uuid = require('uuid');
var client = require('../src/client'); var client = require('../src/client');
var Long = require('long');
var ANY_VERSION = Long.fromNumber(client.expectedVersion.any);
var NOSTREAM_VERSION = Long.fromNumber(client.expectedVersion.noStream);
module.exports = { module.exports = {
'Append One Event To Stream Happy Path': function(test) { 'Append One Event To Stream Happy Path': function(test) {
test.expect(2); test.expect(2);
var event = client.createJsonEventData(uuid.v4(), {a: Math.random(), b: uuid.v4()}, null, 'testEvent'); var event = client.createJsonEventData(uuid.v4(), {a: Math.random(), b: uuid.v4()}, null, 'testEvent');
this.conn.appendToStream(this.testStreamName, ANY_VERSION, event) this.conn.appendToStream(this.testStreamName, client.expectedVersion.any, event)
.then(function(result) { .then(function(result) {
test.areEqual("nextExpectedVersion", result.nextExpectedVersion, Long.fromNumber(0)); test.areEqual("nextExpectedVersion", result.nextExpectedVersion, 0);
test.ok(result.logPosition, "No log position in result."); test.ok(result.logPosition, "No log position in result.");
test.done(); test.done();
}) })
@ -29,9 +25,9 @@ module.exports = {
else else
events.push(client.createJsonEventData(uuid.v4(), {b: Math.random(), a: uuid.v4()}, null, 'otherEvent')); events.push(client.createJsonEventData(uuid.v4(), {b: Math.random(), a: uuid.v4()}, null, 'otherEvent'));
} }
this.conn.appendToStream(this.testStreamName, ANY_VERSION, events) this.conn.appendToStream(this.testStreamName, client.expectedVersion.any, events)
.then(function(result) { .then(function(result) {
test.areEqual("result.nextExpectedVersion", result.nextExpectedVersion, Long.fromNumber(expectedVersion)); test.areEqual("result.nextExpectedVersion", result.nextExpectedVersion, expectedVersion);
test.ok(result.logPosition, "No log position in result."); test.ok(result.logPosition, "No log position in result.");
test.done(); test.done();
}) })
@ -49,9 +45,9 @@ module.exports = {
else else
events.push(client.createJsonEventData(uuid.v4(), {b: Math.random(), a: uuid.v4()}, null, 'otherEvent')); events.push(client.createJsonEventData(uuid.v4(), {b: Math.random(), a: uuid.v4()}, null, 'otherEvent'));
} }
this.conn.appendToStream(this.testStreamName, ANY_VERSION, events) this.conn.appendToStream(this.testStreamName, client.expectedVersion.any, events)
.then(function(result) { .then(function(result) {
test.areEqual("result.nextExpectedVersion", result.nextExpectedVersion, Long.fromNumber(expectedVersion)); test.areEqual("result.nextExpectedVersion", result.nextExpectedVersion, expectedVersion);
test.ok(result.logPosition, "No log position in result."); test.ok(result.logPosition, "No log position in result.");
test.done(); test.done();
}) })
@ -64,9 +60,9 @@ module.exports = {
const largeData = Buffer.alloc(3 * 1024 *1024, " "); const largeData = Buffer.alloc(3 * 1024 *1024, " ");
const event = client.createJsonEventData(uuid.v4(), {a: largeData.toString()}, null, 'largePayloadEvent'); const event = client.createJsonEventData(uuid.v4(), {a: largeData.toString()}, null, 'largePayloadEvent');
this.conn.appendToStream(this.testStreamName, ANY_VERSION, event) this.conn.appendToStream(this.testStreamName, client.expectedVersion.any, event)
.then(function(result) { .then(function(result) {
test.areEqual("result.nextExpectedVersion", result.nextExpectedVersion, Long.fromNumber(0)); test.areEqual("result.nextExpectedVersion", result.nextExpectedVersion, 0);
test.ok(result.logPosition, "No log position in result."); test.ok(result.logPosition, "No log position in result.");
test.done(); test.done();
}) })
@ -77,7 +73,7 @@ module.exports = {
'Append To Stream Wrong Expected Version': function(test) { 'Append To Stream Wrong Expected Version': function(test) {
test.expect(1); test.expect(1);
var event = client.createJsonEventData(uuid.v4(), {a: Math.random(), b: uuid.v4()}, null, 'testEvent'); var event = client.createJsonEventData(uuid.v4(), {a: Math.random(), b: uuid.v4()}, null, 'testEvent');
this.conn.appendToStream(this.testStreamName, Long.fromNumber(10), event) this.conn.appendToStream(this.testStreamName, 10, event)
.then(function(result) { .then(function(result) {
test.fail("Append succeeded but should have failed."); test.fail("Append succeeded but should have failed.");
test.done(); test.done();
@ -92,10 +88,10 @@ module.exports = {
'Append To Stream Deleted': function(test) { 'Append To Stream Deleted': function(test) {
test.expect(1); test.expect(1);
var self = this; var self = this;
this.conn.deleteStream(this.testStreamName, NOSTREAM_VERSION, true) this.conn.deleteStream(this.testStreamName, client.expectedVersion.noStream, true)
.then(function() { .then(function() {
var event = client.createJsonEventData(uuid.v4(), {a: Math.random(), b: uuid.v4()}, null, 'testEvent'); var event = client.createJsonEventData(uuid.v4(), {a: Math.random(), b: uuid.v4()}, null, 'testEvent');
return self.conn.appendToStream(self.testStreamName, ANY_VERSION, event) return self.conn.appendToStream(self.testStreamName, client.expectedVersion.any, event)
}) })
.then(function(result) { .then(function(result) {
test.fail("Append succeeded but should have failed."); test.fail("Append succeeded but should have failed.");
@ -112,10 +108,10 @@ module.exports = {
test.expect(1); test.expect(1);
var self = this; var self = this;
var metadata = {$acl: {$w: "$admins"}}; var metadata = {$acl: {$w: "$admins"}};
this.conn.setStreamMetadataRaw(this.testStreamName, NOSTREAM_VERSION, metadata) this.conn.setStreamMetadataRaw(this.testStreamName, client.expectedVersion.noStream, metadata)
.then(function() { .then(function() {
var event = client.createJsonEventData(uuid.v4(), {a: Math.random(), b: uuid.v4()}, null, 'testEvent'); var event = client.createJsonEventData(uuid.v4(), {a: Math.random(), b: uuid.v4()}, null, 'testEvent');
return self.conn.appendToStream(self.testStreamName, ANY_VERSION, event) return self.conn.appendToStream(self.testStreamName, client.expectedVersion.any, event)
}) })
.then(function(result) { .then(function(result) {
test.fail("Append succeeded but should have failed."); test.fail("Append succeeded but should have failed.");

View File

@ -78,7 +78,7 @@ function testLiveEvent(name, event, evNumber) {
this.ok(event.originalPosition instanceof client.Position, name + ".originalPosition is not an instance of Position"); this.ok(event.originalPosition instanceof client.Position, name + ".originalPosition is not an instance of Position");
this.ok(event.originalStreamId, name + ".originalStreamId not defined (or null)"); this.ok(event.originalStreamId, name + ".originalStreamId not defined (or null)");
if (typeof evNumber === 'number') { if (typeof evNumber === 'number') {
this.ok(event.originalEventNumber.toNumber() === evNumber, name + '.originalEventNumber expected ' + evNumber + ' got ' + event.originalEventNumber); this.ok(event.originalEventNumber === evNumber, name + '.originalEventNumber expected ' + evNumber + ' got ' + event.originalEventNumber);
} else { } else {
this.ok(typeof event.originalEventNumber === 'number', name + ".originalEventNumber is not a number"); this.ok(typeof event.originalEventNumber === 'number', name + ".originalEventNumber is not a number");
} }
@ -91,7 +91,7 @@ function testReadEvent(name, event, evNumber) {
this.ok(event.originalPosition === null, name + ".originalPosition is not null"); this.ok(event.originalPosition === null, name + ".originalPosition is not null");
this.ok(event.originalStreamId, name + ".originalStreamId not defined (or null)"); this.ok(event.originalStreamId, name + ".originalStreamId not defined (or null)");
if (typeof evNumber === 'number') { if (typeof evNumber === 'number') {
this.ok(event.originalEventNumber.toNumber() === evNumber, name + '.originalEventNumber expected ' + evNumber + ' got ' + event.originalEventNumber); this.ok(event.originalEventNumber === evNumber, name + '.originalEventNumber expected ' + evNumber + ' got ' + event.originalEventNumber);
} else { } else {
this.ok(typeof event.originalEventNumber === 'number', name + ".originalEventNumber is not a number"); this.ok(typeof event.originalEventNumber === 'number', name + ".originalEventNumber is not a number");
} }

View File

@ -1,6 +1,5 @@
var uuid = require('uuid'); var uuid = require('uuid');
var client = require('../src/client'); var client = require('../src/client');
var Long = require('long');
module.exports = { module.exports = {
setUp: function(cb) { setUp: function(cb) {
@ -17,7 +16,7 @@ module.exports = {
'Test Delete Stream Soft Happy Path': function(test) { 'Test Delete Stream Soft Happy Path': function(test) {
test.expect(4); test.expect(4);
var self = this; var self = this;
this.conn.deleteStream(this.testStreamName, Long.fromNumber(1), false) this.conn.deleteStream(this.testStreamName, 1, false)
.then(function(result) { .then(function(result) {
test.ok(result.logPosition, "No log position in result."); test.ok(result.logPosition, "No log position in result.");
return self.conn.getStreamMetadataRaw(self.testStreamName); return self.conn.getStreamMetadataRaw(self.testStreamName);
@ -35,7 +34,7 @@ module.exports = {
'Test Delete Stream Hard Happy Path': function(test) { 'Test Delete Stream Hard Happy Path': function(test) {
test.expect(4); test.expect(4);
var self = this; var self = this;
this.conn.deleteStream(this.testStreamName, Long.fromNumber(1), true) this.conn.deleteStream(this.testStreamName, 1, true)
.then(function(result) { .then(function(result) {
test.ok(result.logPosition, "No log position in result."); test.ok(result.logPosition, "No log position in result.");
return self.conn.getStreamMetadataRaw(self.testStreamName); return self.conn.getStreamMetadataRaw(self.testStreamName);
@ -52,7 +51,7 @@ module.exports = {
}, },
'Test Delete Stream With Wrong Expected Version': function(test) { 'Test Delete Stream With Wrong Expected Version': function(test) {
test.expect(1); test.expect(1);
this.conn.deleteStream(this.testStreamName, Long.fromNumber(10)) this.conn.deleteStream(this.testStreamName, 10)
.then(function(result) { .then(function(result) {
test.fail("Delete succeeded but should have failed."); test.fail("Delete succeeded but should have failed.");
test.done(); test.done();
@ -69,7 +68,7 @@ module.exports = {
var self = this; var self = this;
this.conn.setStreamMetadataRaw(this.testStreamName, client.expectedVersion.any, {$acl: {$d: "$admins"}}) this.conn.setStreamMetadataRaw(this.testStreamName, client.expectedVersion.any, {$acl: {$d: "$admins"}})
.then(function() { .then(function() {
return self.conn.deleteStream(self.testStreamName, Long.fromNumber(10)); return self.conn.deleteStream(self.testStreamName, 10);
}) })
.then(function(result) { .then(function(result) {
test.fail("Delete succeeded but should have failed."); test.fail("Delete succeeded but should have failed.");
@ -87,7 +86,7 @@ module.exports = {
var self = this; var self = this;
this.conn.deleteStream(this.testStreamName, 1, true) this.conn.deleteStream(this.testStreamName, 1, true)
.then(function() { .then(function() {
return self.conn.deleteStream(self.testStreamName, Long.fromNumber(1), true); return self.conn.deleteStream(self.testStreamName, 1, true);
}) })
.then(function(result) { .then(function(result) {
test.fail("Delete succeeded but should have failed."); test.fail("Delete succeeded but should have failed.");

View File

@ -1,11 +1,10 @@
var util = require('util');
var uuid = require('uuid');
var client = require('../src/client'); var client = require('../src/client');
const Long = require('long');
const EMPTY_VERSION = Long.fromNumber(client.expectedVersion.emptyStream);
module.exports = { module.exports = {
'Test Set Stream Metadata Raw': function(test) { 'Test Set Stream Metadata Raw': function(test) {
this.conn.setStreamMetadataRaw(this.testStreamName, EMPTY_VERSION, {$maxCount: 100}) this.conn.setStreamMetadataRaw(this.testStreamName, client.expectedVersion.emptyStream, {$maxCount: 100})
.then(function(result) { .then(function(result) {
test.done(); test.done();
}) })

View File

@ -1,9 +1,7 @@
var util = require('util');
var uuid = require('uuid'); var uuid = require('uuid');
var client = require('../src/client'); var client = require('../src/client');
var Long = require('long');
var NOSTREAM_VERSION = Long.fromNumber(client.expectedVersion.noStream);
var ANY_VERSION = Long.fromNumber(client.expectedVersion.any);
module.exports = { module.exports = {
setUp: function(cb) { setUp: function(cb) {
@ -14,7 +12,7 @@ module.exports = {
this.expectedEventType = 'anEvent'; this.expectedEventType = 'anEvent';
this.expectedEventId = uuid.v4(); this.expectedEventId = uuid.v4();
var event = client.createJsonEventData(this.expectedEventId, this.expectedEvent, null, this.expectedEventType); var event = client.createJsonEventData(this.expectedEventId, this.expectedEvent, null, this.expectedEventType);
this.conn.appendToStream(this.testStreamName, NOSTREAM_VERSION, event) this.conn.appendToStream(this.testStreamName, client.expectedVersion.noStream, event)
.then(function() { .then(function() {
cb(); cb();
}) })
@ -23,11 +21,11 @@ module.exports = {
'Read Event Happy Path': function(test) { 'Read Event Happy Path': function(test) {
test.expect(8); test.expect(8);
var self = this; var self = this;
this.conn.readEvent(this.testStreamName, Long.fromNumber(0)) this.conn.readEvent(this.testStreamName, 0)
.then(function(result) { .then(function(result) {
test.areEqual('status', result.status, client.eventReadStatus.Success); test.areEqual('status', result.status, client.eventReadStatus.Success);
test.areEqual('stream', result.stream, self.testStreamName); test.areEqual('stream', result.stream, self.testStreamName);
test.areEqual('eventNumber', result.eventNumber, Long.fromNumber(0)); test.areEqual('eventNumber', result.eventNumber, 0);
test.ok(result.event !== null, "event is null."); test.ok(result.event !== null, "event is null.");
test.ok(result.event.originalEvent !== null, "event.originalEvent is null."); test.ok(result.event.originalEvent !== null, "event.originalEvent is null.");
var event = JSON.parse(result.event.originalEvent.data.toString()); var event = JSON.parse(result.event.originalEvent.data.toString());
@ -43,11 +41,11 @@ module.exports = {
'Read Event From Non-Existing Stream': function(test) { 'Read Event From Non-Existing Stream': function(test) {
test.expect(4); test.expect(4);
var anotherStream = 'test' + uuid.v4(); var anotherStream = 'test' + uuid.v4();
this.conn.readEvent(anotherStream, Long.fromNumber(0)) this.conn.readEvent(anotherStream, 0)
.then(function(result) { .then(function(result) {
test.areEqual('status', result.status, client.eventReadStatus.NoStream); test.areEqual('status', result.status, client.eventReadStatus.NoStream);
test.areEqual('stream', result.stream, anotherStream); test.areEqual('stream', result.stream, anotherStream);
test.areEqual('eventNumber', result.eventNumber, Long.fromNumber(0)); test.areEqual('eventNumber', result.eventNumber, 0);
test.areEqual('event', result.event, null); test.areEqual('event', result.event, null);
test.done(); test.done();
}) })
@ -60,12 +58,12 @@ module.exports = {
var self = this; var self = this;
this.conn.deleteStream(this.testStreamName, 0, true) this.conn.deleteStream(this.testStreamName, 0, true)
.then(function() { .then(function() {
return self.conn.readEvent(self.testStreamName, Long.fromNumber(0)) return self.conn.readEvent(self.testStreamName, 0)
}) })
.then(function(result) { .then(function(result) {
test.areEqual('status', result.status, client.eventReadStatus.StreamDeleted); test.areEqual('status', result.status, client.eventReadStatus.StreamDeleted);
test.areEqual('stream', result.stream, self.testStreamName); test.areEqual('stream', result.stream, self.testStreamName);
test.areEqual('eventNumber', result.eventNumber, Long.fromNumber(0)); test.areEqual('eventNumber', result.eventNumber, 0);
test.areEqual('event', result.event, null); test.areEqual('event', result.event, null);
test.done(); test.done();
}) })
@ -76,11 +74,11 @@ module.exports = {
'Read Event With Inexisting Version': function(test) { 'Read Event With Inexisting Version': function(test) {
test.expect(4); test.expect(4);
var self = this; var self = this;
return self.conn.readEvent(self.testStreamName, Long.fromNumber(1)) return self.conn.readEvent(self.testStreamName, 1)
.then(function(result) { .then(function(result) {
test.areEqual('status', result.status, client.eventReadStatus.NotFound); test.areEqual('status', result.status, client.eventReadStatus.NotFound);
test.areEqual('stream', result.stream, self.testStreamName); test.areEqual('stream', result.stream, self.testStreamName);
test.areEqual('eventNumber', result.eventNumber, Long.fromNumber(1)); test.areEqual('eventNumber', result.eventNumber, 1);
test.areEqual('event', result.event, null); test.areEqual('event', result.event, null);
test.done(); test.done();
}) })
@ -96,9 +94,9 @@ module.exports = {
$r: '$admins' $r: '$admins'
} }
}; };
this.conn.setStreamMetadataRaw(self.testStreamName, NOSTREAM_VERSION, metadata) this.conn.setStreamMetadataRaw(self.testStreamName, client.expectedVersion.noStream, metadata)
.then(function() { .then(function() {
return self.conn.readEvent(self.testStreamName, Long.fromNumber(0)); return self.conn.readEvent(self.testStreamName, 0);
}) })
.then(function(result) { .then(function(result) {
test.fail("readEvent succeeded but should have failed."); test.fail("readEvent succeeded but should have failed.");
@ -120,13 +118,13 @@ module.exports = {
a: largeData.toString() a: largeData.toString()
}, null, 'largePayloadEvent'); }, null, 'largePayloadEvent');
this.conn.appendToStream(this.testStreamName, ANY_VERSION, largeEvent) this.conn.appendToStream(this.testStreamName, client.expectedVersion.any, largeEvent)
.then(function(result) { .then(function(result) {
self.conn.readEvent(self.testStreamName, Long.fromNumber(1)) self.conn.readEvent(self.testStreamName, 1)
.then(function(result) { .then(function(result) {
test.areEqual('status', result.status, client.eventReadStatus.Success); test.areEqual('status', result.status, client.eventReadStatus.Success);
test.areEqual('stream', result.stream, self.testStreamName); test.areEqual('stream', result.stream, self.testStreamName);
test.areEqual('eventNumber', result.eventNumber, Long.fromNumber(1)); test.areEqual('eventNumber', result.eventNumber, 1);
test.ok(result.event !== null, "event is null."); test.ok(result.event !== null, "event is null.");
test.ok(result.event.originalEvent !== null, "event.originalEvent is null."); test.ok(result.event.originalEvent !== null, "event.originalEvent is null.");
var event = JSON.parse(result.event.originalEvent.data.toString()); var event = JSON.parse(result.event.originalEvent.data.toString());

View File

@ -1,17 +1,15 @@
var util = require('util');
var uuid = require('uuid'); var uuid = require('uuid');
var client = require('../src/client'); var client = require('../src/client');
var Long = require('long');
const streamSize = 100; const streamSize = 100;
var NOSTREAM_VERSION = Long.fromNumber(client.expectedVersion.noStream);
module.exports = { module.exports = {
setUp: function(cb) { setUp: function(cb) {
this.eventsData = []; this.eventsData = [];
for(var i = 0; i < streamSize; i++) for(var i = 0; i < streamSize; i++)
this.eventsData.push(client.createJsonEventData(uuid.v4(), {a: uuid.v4(), b: Math.random()}, null, 'anEvent')); this.eventsData.push(client.createJsonEventData(uuid.v4(), {a: uuid.v4(), b: Math.random()}, null, 'anEvent'));
this.conn.appendToStream(this.testStreamName, NOSTREAM_VERSION, this.eventsData) this.conn.appendToStream(this.testStreamName, client.expectedVersion.noStream, this.eventsData)
.then(function() { .then(function() {
cb(); cb();
}) })
@ -20,19 +18,19 @@ module.exports = {
'Read Stream Events Backward Happy Path': function(test) { 'Read Stream Events Backward Happy Path': function(test) {
test.expect(7 + (streamSize * 6)); test.expect(7 + (streamSize * 6));
var self = this; var self = this;
this.conn.readStreamEventsBackward(this.testStreamName, Long.fromNumber(streamSize-1), streamSize) this.conn.readStreamEventsBackward(this.testStreamName, streamSize-1, streamSize)
.then(function(slice) { .then(function(slice) {
test.areEqual('slice.status', slice.status, client.eventReadStatus.Success); test.areEqual('slice.status', slice.status, client.eventReadStatus.Success);
test.areEqual('slice.stream', slice.stream, self.testStreamName); test.areEqual('slice.stream', slice.stream, self.testStreamName);
test.areEqual('slice.fromEventNumber', slice.fromEventNumber, Long.fromNumber(streamSize-1)); test.areEqual('slice.fromEventNumber', slice.fromEventNumber, streamSize-1);
test.areEqual('slice.readDirection', slice.readDirection, 'backward'); test.areEqual('slice.readDirection', slice.readDirection, 'backward');
test.areEqual('slice.nextEventNumber', slice.nextEventNumber, Long.fromNumber(-1)); test.areEqual('slice.nextEventNumber', slice.nextEventNumber, -1);
test.areEqual('slice.lastEventNumber', slice.lastEventNumber, Long.fromNumber(streamSize-1)); test.areEqual('slice.lastEventNumber', slice.lastEventNumber, streamSize-1);
test.areEqual('slice.isEndOfStream', slice.isEndOfStream, true); test.areEqual('slice.isEndOfStream', slice.isEndOfStream, true);
for(var i = 0; i < streamSize; i++) { for(var i = 0; i < streamSize; i++) {
var reverseIndex = streamSize - i - 1; var reverseIndex = streamSize - i - 1;
test.eventEqualEventData('slice.events[' + i + ']', slice.events[i], self.eventsData[reverseIndex]); test.eventEqualEventData('slice.events[' + i + ']', slice.events[i], self.eventsData[reverseIndex]);
test.areEqual('slice.events[' + i + '].originalEventNumber', slice.events[i].originalEventNumber, Long.fromNumber(reverseIndex)); test.areEqual('slice.events[' + i + '].originalEventNumber', slice.events[i].originalEventNumber, reverseIndex);
} }
test.done(); test.done();
}) })
@ -43,11 +41,11 @@ module.exports = {
'Read Stream Events Backward With Non-Existing Stream': function(test) { 'Read Stream Events Backward With Non-Existing Stream': function(test) {
test.expect(4); test.expect(4);
var anotherStream = 'test' + uuid.v4(); var anotherStream = 'test' + uuid.v4();
this.conn.readStreamEventsBackward(anotherStream, Long.fromNumber(streamSize-1), streamSize) this.conn.readStreamEventsBackward(anotherStream, streamSize-1, streamSize)
.then(function(slice) { .then(function(slice) {
test.areEqual('slice.status', slice.status, client.sliceReadStatus.StreamNotFound); test.areEqual('slice.status', slice.status, client.sliceReadStatus.StreamNotFound);
test.areEqual('slice.stream', slice.stream, anotherStream); test.areEqual('slice.stream', slice.stream, anotherStream);
test.areEqual('slice.fromEventNumber', slice.fromEventNumber, Long.fromNumber(streamSize-1)); test.areEqual('slice.fromEventNumber', slice.fromEventNumber, streamSize-1);
test.areEqual('slice.events.length', slice.events.length, 0); test.areEqual('slice.events.length', slice.events.length, 0);
test.done(); test.done();
}) })
@ -58,14 +56,14 @@ module.exports = {
'Read Stream Events Backward With Deleted Stream': function(test) { 'Read Stream Events Backward With Deleted Stream': function(test) {
test.expect(4); test.expect(4);
var self = this; var self = this;
this.conn.deleteStream(this.testStreamName, Long.fromNumber(streamSize-1), true) this.conn.deleteStream(this.testStreamName, streamSize-1, true)
.then(function() { .then(function() {
return self.conn.readStreamEventsBackward(self.testStreamName, Long.fromNumber(streamSize-1), streamSize) return self.conn.readStreamEventsBackward(self.testStreamName, streamSize-1, streamSize)
}) })
.then(function(slice) { .then(function(slice) {
test.areEqual('slice.status', slice.status, client.eventReadStatus.StreamDeleted); test.areEqual('slice.status', slice.status, client.eventReadStatus.StreamDeleted);
test.areEqual('slice.stream', slice.stream, self.testStreamName); test.areEqual('slice.stream', slice.stream, self.testStreamName);
test.areEqual('slice.fromEventNumber', slice.fromEventNumber, Long.fromNumber(streamSize-1)); test.areEqual('slice.fromEventNumber', slice.fromEventNumber, streamSize-1);
test.areEqual('slice.events.length', slice.events.length, 0); test.areEqual('slice.events.length', slice.events.length, 0);
test.done(); test.done();
}) })
@ -76,11 +74,11 @@ module.exports = {
'Read Stream Events Backward With Inexisting Version': function(test) { 'Read Stream Events Backward With Inexisting Version': function(test) {
test.expect(4); test.expect(4);
var self = this; var self = this;
return self.conn.readStreamEventsBackward(self.testStreamName, Long.fromNumber(streamSize * 2), streamSize) return self.conn.readStreamEventsBackward(self.testStreamName, streamSize * 2, streamSize)
.then(function(slice) { .then(function(slice) {
test.areEqual('slice.status', slice.status, client.eventReadStatus.Success); test.areEqual('slice.status', slice.status, client.eventReadStatus.Success);
test.areEqual('slice.stream', slice.stream, self.testStreamName); test.areEqual('slice.stream', slice.stream, self.testStreamName);
test.areEqual('slice.fromEventNumber', slice.fromEventNumber, Long.fromNumber(streamSize*2)); test.areEqual('slice.fromEventNumber', slice.fromEventNumber, streamSize*2);
test.areEqual('slice.events.length', slice.events.length, 0); test.areEqual('slice.events.length', slice.events.length, 0);
test.done(); test.done();
}) })
@ -92,9 +90,9 @@ module.exports = {
test.expect(1); test.expect(1);
var self = this; var self = this;
var metadata = {$acl: {$r: '$admins'}}; var metadata = {$acl: {$r: '$admins'}};
this.conn.setStreamMetadataRaw(self.testStreamName, NOSTREAM_VERSION, metadata) this.conn.setStreamMetadataRaw(self.testStreamName, client.expectedVersion.noStream, metadata)
.then(function(){ .then(function(){
return self.conn.readStreamEventsBackward(self.testStreamName, Long.fromNumber(streamSize-1), streamSize); return self.conn.readStreamEventsBackward(self.testStreamName, streamSize-1, streamSize);
}) })
.then(function(slice) { .then(function(slice) {
test.fail("readStreamEventsBackward succeeded but should have failed."); test.fail("readStreamEventsBackward succeeded but should have failed.");

View File

@ -1,17 +1,15 @@
var util = require('util');
var uuid = require('uuid'); var uuid = require('uuid');
var client = require('../src/client'); var client = require('../src/client');
var Long = require('long');
const streamSize = 100; const streamSize = 100;
var NOSTREAM_VERSION = Long.fromNumber(client.expectedVersion.noStream);
module.exports = { module.exports = {
setUp: function(cb) { setUp: function(cb) {
this.eventsData = []; this.eventsData = [];
for(var i = 0; i < streamSize; i++) for(var i = 0; i < streamSize; i++)
this.eventsData.push(client.createJsonEventData(uuid.v4(), {a: uuid.v4(), b: Math.random()}, null, 'anEvent')); this.eventsData.push(client.createJsonEventData(uuid.v4(), {a: uuid.v4(), b: Math.random()}, null, 'anEvent'));
this.conn.appendToStream(this.testStreamName, NOSTREAM_VERSION, this.eventsData) this.conn.appendToStream(this.testStreamName, client.expectedVersion.noStream, this.eventsData)
.then(function() { .then(function() {
cb(); cb();
}) })
@ -20,14 +18,14 @@ module.exports = {
'Read Stream Events Forward Happy Path': function(test) { 'Read Stream Events Forward Happy Path': function(test) {
test.expect(7 + (streamSize * 11)); test.expect(7 + (streamSize * 11));
var self = this; var self = this;
this.conn.readStreamEventsForward(this.testStreamName, Long.fromNumber(0), streamSize) this.conn.readStreamEventsForward(this.testStreamName, 0, streamSize)
.then(function(slice) { .then(function(slice) {
test.areEqual('slice.status', slice.status, client.eventReadStatus.Success); test.areEqual('slice.status', slice.status, client.eventReadStatus.Success);
test.areEqual('slice.stream', slice.stream, self.testStreamName); test.areEqual('slice.stream', slice.stream, self.testStreamName);
test.areEqual('slice.fromEventNumber', slice.fromEventNumber, Long.fromNumber(0)); test.areEqual('slice.fromEventNumber', slice.fromEventNumber, 0);
test.areEqual('slice.readDirection', slice.readDirection, 'forward'); test.areEqual('slice.readDirection', slice.readDirection, 'forward');
test.areEqual('slice.nextEventNumber', slice.nextEventNumber, Long.fromNumber(streamSize)); test.areEqual('slice.nextEventNumber', slice.nextEventNumber, streamSize);
test.areEqual('slice.lastEventNumber', slice.lastEventNumber, Long.fromNumber(streamSize-1)); test.areEqual('slice.lastEventNumber', slice.lastEventNumber, streamSize-1);
test.areEqual('slice.isEndOfStream', slice.isEndOfStream, true); test.areEqual('slice.isEndOfStream', slice.isEndOfStream, true);
for(var i = 0; i < streamSize; i++) { for(var i = 0; i < streamSize; i++) {
test.eventEqualEventData('slice.events[' + i + ']', slice.events[i], self.eventsData[i]); test.eventEqualEventData('slice.events[' + i + ']', slice.events[i], self.eventsData[i]);
@ -42,11 +40,11 @@ module.exports = {
'Read Stream Events Forward With Non-Existing Stream': function(test) { 'Read Stream Events Forward With Non-Existing Stream': function(test) {
test.expect(4); test.expect(4);
var anotherStream = 'test' + uuid.v4(); var anotherStream = 'test' + uuid.v4();
this.conn.readStreamEventsForward(anotherStream, Long.fromNumber(0), streamSize) this.conn.readStreamEventsForward(anotherStream, 0, streamSize)
.then(function(slice) { .then(function(slice) {
test.areEqual('slice.status', slice.status, client.sliceReadStatus.StreamNotFound); test.areEqual('slice.status', slice.status, client.sliceReadStatus.StreamNotFound);
test.areEqual('slice.stream', slice.stream, anotherStream); test.areEqual('slice.stream', slice.stream, anotherStream);
test.areEqual('slice.fromEventNumber', slice.fromEventNumber, Long.fromNumber(0)); test.areEqual('slice.fromEventNumber', slice.fromEventNumber, 0);
test.areEqual('slice.events.length', slice.events.length, 0); test.areEqual('slice.events.length', slice.events.length, 0);
test.done(); test.done();
}) })
@ -57,14 +55,14 @@ module.exports = {
'Read Stream Events Forward With Deleted Stream': function(test) { 'Read Stream Events Forward With Deleted Stream': function(test) {
test.expect(4); test.expect(4);
var self = this; var self = this;
this.conn.deleteStream(this.testStreamName, Long.fromNumber(streamSize-1), true) this.conn.deleteStream(this.testStreamName, streamSize-1, true)
.then(function() { .then(function() {
return self.conn.readStreamEventsForward(self.testStreamName, Long.fromNumber(0), streamSize) return self.conn.readStreamEventsForward(self.testStreamName, 0, streamSize)
}) })
.then(function(slice) { .then(function(slice) {
test.areEqual('slice.status', slice.status, client.eventReadStatus.StreamDeleted); test.areEqual('slice.status', slice.status, client.eventReadStatus.StreamDeleted);
test.areEqual('slice.stream', slice.stream, self.testStreamName); test.areEqual('slice.stream', slice.stream, self.testStreamName);
test.areEqual('slice.fromEventNumber', slice.fromEventNumber, Long.fromNumber(0)); test.areEqual('slice.fromEventNumber', slice.fromEventNumber, 0);
test.areEqual('slice.events.length', slice.events.length, 0); test.areEqual('slice.events.length', slice.events.length, 0);
test.done(); test.done();
}) })
@ -75,11 +73,11 @@ module.exports = {
'Read Stream Events Forward With Inexisting Version': function(test) { 'Read Stream Events Forward With Inexisting Version': function(test) {
test.expect(4); test.expect(4);
var self = this; var self = this;
return self.conn.readStreamEventsForward(self.testStreamName, Long.fromNumber(streamSize * 2), streamSize) return self.conn.readStreamEventsForward(self.testStreamName, streamSize * 2, streamSize)
.then(function(slice) { .then(function(slice) {
test.areEqual('slice.status', slice.status, client.eventReadStatus.Success); test.areEqual('slice.status', slice.status, client.eventReadStatus.Success);
test.areEqual('slice.stream', slice.stream, self.testStreamName); test.areEqual('slice.stream', slice.stream, self.testStreamName);
test.areEqual('slice.fromEventNumber', slice.fromEventNumber, Long.fromNumber(streamSize*2)); test.areEqual('slice.fromEventNumber', slice.fromEventNumber, streamSize*2);
test.areEqual('slice.events.length', slice.events.length, 0); test.areEqual('slice.events.length', slice.events.length, 0);
test.done(); test.done();
}) })
@ -91,9 +89,9 @@ module.exports = {
test.expect(1); test.expect(1);
var self = this; var self = this;
var metadata = {$acl: {$r: '$admins'}}; var metadata = {$acl: {$r: '$admins'}};
this.conn.setStreamMetadataRaw(self.testStreamName, NOSTREAM_VERSION, metadata) this.conn.setStreamMetadataRaw(self.testStreamName, client.expectedVersion.noStream, metadata)
.then(function(){ .then(function(){
return self.conn.readStreamEventsForward(self.testStreamName, Long.fromNumber(0), streamSize); return self.conn.readStreamEventsForward(self.testStreamName, 0, streamSize);
}) })
.then(function(slice) { .then(function(slice) {
test.fail("readStreamEventsForward succeeded but should have failed."); test.fail("readStreamEventsForward succeeded but should have failed.");

View File

@ -1,6 +1,6 @@
var util = require('util');
var uuid = require('uuid'); var uuid = require('uuid');
var client = require('../src/client'); var client = require('../src/client');
var Long = require('long');
function createRandomEvent() { function createRandomEvent() {
return client.createJsonEventData(uuid.v4(), {a: uuid.v4(), b: Math.random()}, {createdAt: Date.now()}, 'testEvent'); return client.createJsonEventData(uuid.v4(), {a: uuid.v4(), b: Math.random()}, {createdAt: Date.now()}, 'testEvent');
@ -22,7 +22,7 @@ function delayOnlyFirst(count, action) {
module.exports = { module.exports = {
'Test Subscribe to Stream From Beginning (null)': function(test) { 'Test Subscribe to Stream From Beginning (null)': function(test) {
test.expect(32); test.expect(36);
var self = this; var self = this;
var liveProcessing = false; var liveProcessing = false;
var catchUpEvents = []; var catchUpEvents = [];
@ -57,11 +57,15 @@ module.exports = {
} }
function subscriptionDropped(connection, reason, error) { function subscriptionDropped(connection, reason, error) {
test.ok(liveEvents.length === 2, "Expecting 2 live event, got " + liveEvents.length); test.ok(liveEvents.length === 2, "Expecting 2 live event, got " + liveEvents.length);
test.testLiveEvent('liveEvents[0]', liveEvents[0], 2); test.testLiveEvent('liveEvents[0]', liveEvents[0]);
test.testLiveEvent('liveEvents[1]', liveEvents[1], 3); test.testLiveEvent('liveEvents[1]', liveEvents[1]);
test.ok(liveEvents[0].originalEventNumber, 2);
test.ok(liveEvents[1].originalEventNumber, 3);
test.ok(catchUpEvents.length === 2, "Expecting 2 catchUp event, got " + catchUpEvents.length); test.ok(catchUpEvents.length === 2, "Expecting 2 catchUp event, got " + catchUpEvents.length);
test.testReadEvent('catchUpEvents[0]', catchUpEvents[0], 0); test.testReadEvent('catchUpEvents[0]', catchUpEvents[0]);
test.testReadEvent('catchUpEvents[1]', catchUpEvents[1], 1); test.testReadEvent('catchUpEvents[1]', catchUpEvents[1]);
test.ok(liveEvents[0].originalEventNumber, 0);
test.ok(liveEvents[1].originalEventNumber, 1);
done(error); done(error);
} }
@ -78,7 +82,7 @@ module.exports = {
.catch(test.done); .catch(test.done);
}, },
'Test Subscribe to Stream From 0': function(test) { 'Test Subscribe to Stream From 0': function(test) {
test.expect(26); test.expect(29);
var self = this; var self = this;
var liveProcessing = false; var liveProcessing = false;
var catchUpEvents = []; var catchUpEvents = [];
@ -113,17 +117,20 @@ module.exports = {
} }
function subscriptionDropped(connection, reason, error) { function subscriptionDropped(connection, reason, error) {
test.ok(liveEvents.length === 2, "Expecting 2 live event, got " + liveEvents.length); test.ok(liveEvents.length === 2, "Expecting 2 live event, got " + liveEvents.length);
test.testLiveEvent('liveEvents[0]', liveEvents[0], 2); test.testLiveEvent('liveEvents[0]', liveEvents[0]);
test.testLiveEvent('liveEvents[1]', liveEvents[1], 3); test.testLiveEvent('liveEvents[1]', liveEvents[1]);
test.ok(liveEvents[0].originalEventNumber, 2);
test.ok(liveEvents[1].originalEventNumber, 3);
test.ok(catchUpEvents.length === 1, "Expecting 1 catchUp event, got " + catchUpEvents.length); test.ok(catchUpEvents.length === 1, "Expecting 1 catchUp event, got " + catchUpEvents.length);
test.testReadEvent('catchUpEvents[0]', catchUpEvents[0], 1); test.testReadEvent('catchUpEvents[0]', catchUpEvents[0]);
test.ok(liveEvents[0].originalEventNumber, 1);
done(error); done(error);
} }
var events = [createRandomEvent(), createRandomEvent()]; var events = [createRandomEvent(), createRandomEvent()];
this.conn.appendToStream(self.testStreamName, client.expectedVersion.noStream, events) this.conn.appendToStream(self.testStreamName, client.expectedVersion.noStream, events)
.then(function() { .then(function() {
var subscription = self.conn.subscribeToStreamFrom(self.testStreamName, Long.fromNumber(0), false, eventAppeared, liveProcessingStarted, subscriptionDropped); var subscription = self.conn.subscribeToStreamFrom(self.testStreamName, 0, false, eventAppeared, liveProcessingStarted, subscriptionDropped);
test.areEqual("subscription.streamId", subscription.streamId, self.testStreamName); test.areEqual("subscription.streamId", subscription.streamId, self.testStreamName);
test.areEqual("subscription.isSubscribedToAll", subscription.isSubscribedToAll, false); test.areEqual("subscription.isSubscribedToAll", subscription.isSubscribedToAll, false);

View File

@ -1,6 +1,5 @@
const uuid = require('uuid'); const uuid = require('uuid');
const client = require('../src/client'); const client = require('../src/client');
const Long = require('long');
function delay(ms) { function delay(ms) {
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
@ -59,7 +58,7 @@ module.exports = {
.then(function(subscription) { .then(function(subscription) {
test.areEqual("subscription.streamId", subscription.streamId, self.testStreamName); test.areEqual("subscription.streamId", subscription.streamId, self.testStreamName);
test.areEqual("subscription.isSubscribedToAll", subscription.isSubscribedToAll, false); test.areEqual("subscription.isSubscribedToAll", subscription.isSubscribedToAll, false);
test.areEqual("subscription.lastEventNumber", subscription.lastEventNumber, Long.fromNumber(client.expectedVersion.emptyStream)); test.areEqual("subscription.lastEventNumber", subscription.lastEventNumber, client.expectedVersion.emptyStream);
return self.conn.appendToStream(self.testStreamName, client.expectedVersion.emptyStream, publishedEvents); return self.conn.appendToStream(self.testStreamName, client.expectedVersion.emptyStream, publishedEvents);
}) })

View File

@ -2,17 +2,13 @@ var uuid = require('uuid');
var Long = require('long'); var Long = require('long');
var client = require('../src/client'); var client = require('../src/client');
var ANY_VERSION = Long.fromNumber(client.expectedVersion.any);
var NOSTREAM_VERSION = Long.fromNumber(client.expectedVersion.noStream);
var EMPTY_VERSION = Long.fromNumber(client.expectedVersion.emptyStream);
module.exports = { module.exports = {
setUp: function(cb) { setUp: function(cb) {
cb(); cb();
}, },
'Start A Transaction Happy Path': function(test) { 'Start A Transaction Happy Path': function(test) {
test.expect(1); test.expect(1);
this.conn.startTransaction(this.testStreamName, NOSTREAM_VERSION) this.conn.startTransaction(this.testStreamName, client.expectedVersion.noStream)
.then(function(trx) { .then(function(trx) {
test.ok(Long.isLong(trx.transactionId), "trx.transactionId should be a Long."); test.ok(Long.isLong(trx.transactionId), "trx.transactionId should be a Long.");
test.done(); test.done();
@ -36,7 +32,7 @@ module.exports = {
var self = this; var self = this;
this.conn.deleteStream(this.testStreamName, client.expectedVersion.emptyStream) this.conn.deleteStream(this.testStreamName, client.expectedVersion.emptyStream)
.then(function() { .then(function() {
return self.conn.startTransaction(self.testStreamName, ANY_VERSION); return self.conn.startTransaction(self.testStreamName, client.expectedVersion.any);
}) })
.then(function(trx) { .then(function(trx) {
test.fail("Start Transaction with deleted stream succeeded."); test.fail("Start Transaction with deleted stream succeeded.");
@ -54,9 +50,9 @@ module.exports = {
test.expect(1); test.expect(1);
var self = this; var self = this;
var metadata = {$acl: {$w: "$admins"}}; var metadata = {$acl: {$w: "$admins"}};
this.conn.setStreamMetadataRaw(this.testStreamName, EMPTY_VERSION, metadata) this.conn.setStreamMetadataRaw(this.testStreamName, -1, metadata)
.then(function() { .then(function() {
return self.conn.startTransaction(self.testStreamName, ANY_VERSION); return self.conn.startTransaction(self.testStreamName, client.expectedVersion.any);
}) })
.then(function(trx) { .then(function(trx) {
test.fail("Start Transaction with no access succeeded."); test.fail("Start Transaction with no access succeeded.");
@ -71,7 +67,7 @@ module.exports = {
}, },
'Continue A Transaction Happy Path': function(test) { 'Continue A Transaction Happy Path': function(test) {
var self = this; var self = this;
this.conn.startTransaction(this.testStreamName, EMPTY_VERSION) this.conn.startTransaction(this.testStreamName, client.expectedVersion.emptyStream)
.then(function(trx) { .then(function(trx) {
return trx.write(client.createJsonEventData(uuid.v4(), {a: Math.random()}, null, 'anEvent')) return trx.write(client.createJsonEventData(uuid.v4(), {a: Math.random()}, null, 'anEvent'))
.then(function () { .then(function () {
@ -92,7 +88,7 @@ module.exports = {
'Write/Commit Transaction Happy Path': function(test) { 'Write/Commit Transaction Happy Path': function(test) {
test.expect(2); test.expect(2);
var self = this; var self = this;
this.conn.startTransaction(this.testStreamName, EMPTY_VERSION) this.conn.startTransaction(this.testStreamName, client.expectedVersion.emptyStream)
.then(function(trx) { .then(function(trx) {
self.events = []; self.events = [];
for(var i = 0; i < 15; i++) { for(var i = 0; i < 15; i++) {
@ -115,7 +111,7 @@ module.exports = {
}) })
.then(function(result) { .then(function(result) {
test.ok(result.logPosition, "Missing result.logPosition"); test.ok(result.logPosition, "Missing result.logPosition");
test.areEqual("result.nextExpectedVersion", result.nextExpectedVersion, Long.fromNumber(self.events.length-1)); test.areEqual("result.nextExpectedVersion", result.nextExpectedVersion, self.events.length-1);
test.done(); test.done();
}) })
.catch(test.done); .catch(test.done);
@ -143,9 +139,9 @@ module.exports = {
'Write/Commit Transaction With Deleted Stream': function(test) { 'Write/Commit Transaction With Deleted Stream': function(test) {
test.expect(1); test.expect(1);
var self = this; var self = this;
this.conn.deleteStream(this.testStreamName, EMPTY_VERSION, true) this.conn.deleteStream(this.testStreamName, client.expectedVersion.emptyStream, true)
.then(function() { .then(function() {
return self.conn.startTransaction(self.testStreamName, ANY_VERSION); return self.conn.startTransaction(self.testStreamName, client.expectedVersion.any);
}) })
.then(function(trx) { .then(function(trx) {
return trx.write(client.createJsonEventData(uuid.v4(), {a: Math.random(), b: uuid.v4()}, null, 'anEvent')) return trx.write(client.createJsonEventData(uuid.v4(), {a: Math.random(), b: uuid.v4()}, null, 'anEvent'))
@ -167,10 +163,10 @@ module.exports = {
'Write/Commit Transaction With No Write Access': function(test) { 'Write/Commit Transaction With No Write Access': function(test) {
test.expect(1); test.expect(1);
var self = this; var self = this;
this.conn.startTransaction(this.testStreamName, ANY_VERSION) this.conn.startTransaction(this.testStreamName, client.expectedVersion.any)
.then(function(trx) { .then(function(trx) {
var metadata = {$acl: {$w: "$admins"}}; var metadata = {$acl: {$w: "$admins"}};
return self.conn.setStreamMetadataRaw(self.testStreamName, EMPTY_VERSION, metadata) return self.conn.setStreamMetadataRaw(self.testStreamName, -1, metadata)
.then(function () { .then(function () {
return trx.write(client.createJsonEventData(uuid.v4(), {a: Math.random(), b: uuid.v4()}, null, 'anEvent')) return trx.write(client.createJsonEventData(uuid.v4(), {a: Math.random(), b: uuid.v4()}, null, 'anEvent'))
.then(function () { .then(function () {