Compare commits
	
		
			88 Commits
		
	
	
		
			v3-compat
			...
			9bbc961d52
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					9bbc961d52 | ||
| 
						 | 
					a48e4fa386 | ||
| 
						 | 
					c422057f5f | ||
| 6159cd56b8 | |||
| cbf3c7bb5e | |||
| 
						 | 
					b17ab0c77a | ||
| 
						 | 
					c67d0d25a2 | ||
| 
						 | 
					5bc2aaa093 | ||
| 
						 | 
					401f6c3190 | ||
| 
						 | 
					40736d9da3 | ||
| 
						 | 
					853ae875b8 | ||
| 
						 | 
					da6d059547 | ||
| 
						 | 
					e9834daa31 | ||
| 
						 | 
					f79a0444f6 | ||
| 
						 | 
					eb56e077f9 | ||
| 
						 | 
					11f882501f | ||
| 
						 | 
					7b7ccc2eef | ||
| 
						 | 
					6b75d241fc | ||
| 
						 | 
					7da398eae8 | ||
| 195a6d40ce | |||
| 55b9ddd856 | |||
| fe82aebfec | |||
| 
						 | 
					3f7798d46e | ||
| 
						 | 
					6ad2d34114 | ||
| 
						 | 
					67dab18d53 | ||
| 
						 | 
					78677ba53e | ||
| 
						 | 
					bbf25ee8b5 | ||
| 
						 | 
					732b691e40 | ||
| 
						 | 
					941f671ed2 | ||
| 
						 | 
					343eaa85df | ||
| 
						 | 
					e0fcf9a72d | ||
| 
						 | 
					02642c5cfb | ||
| 
						 | 
					d64f181dbb | ||
| 
						 | 
					9e31b17c44 | ||
| 
						 | 
					4ae4c1e010 | ||
| 76a405ace2 | |||
| 
						 | 
					930b900426 | ||
| 
						 | 
					934251d7fa | ||
| 
						 | 
					1449b43b8d | ||
| 
						 | 
					2f4850680f | ||
| 
						 | 
					8f68923008 | ||
| 
						 | 
					8e54a22cd2 | ||
| 
						 | 
					6663b42903 | ||
| 
						 | 
					ad8d16d112 | ||
| 
						 | 
					bebd04a398 | ||
| 
						 | 
					4d981596eb | ||
| 
						 | 
					7ccced45aa | ||
| 
						 | 
					88df807508 | ||
| 
						 | 
					35f720f94f | ||
| 
						 | 
					6d49f51e7d | ||
| 
						 | 
					d8baed4c5d | ||
| 
						 | 
					7e5327c278 | ||
| 
						 | 
					bb53c01fe8 | ||
| 
						 | 
					20818869f1 | ||
| 
						 | 
					16f172c6f2 | ||
| 
						 | 
					7db060af6e | ||
| 
						 | 
					2c272a19f5 | ||
| 
						 | 
					7dc4658719 | ||
| 
						 | 
					811368c1af | ||
| 
						 | 
					fcf27fba20 | ||
| 
						 | 
					e9d86a3c4d | ||
| 
						 | 
					0db2b93b79 | ||
| 
						 | 
					ef26ed636f | ||
| 2893454e8a | |||
| a0642ab081 | |||
| 760d31cc31 | |||
| c1f17a7d99 | |||
| 96145fbe49 | |||
| 
						 | 
					5ac4a206ad | ||
| 
						 | 
					e1f99cecbc | ||
| 
						 | 
					0a64b37b6f | ||
| 
						 | 
					3421d41068 | ||
| 215708014c | |||
| 
						 | 
					c3a63ff8b7 | ||
| 
						 | 
					d8c0bfb03a | ||
| 34e8262dc8 | |||
| bc2fbe14e3 | |||
| 9fc5d64ceb | |||
| 
						 | 
					2bdd74e041 | ||
| 
						 | 
					fde6ad2e77 | ||
| 4a2065c0a7 | |||
| 67dd275b5d | |||
| 8997a8c398 | |||
| a5807483a2 | |||
| e79ad8f9c4 | |||
| 
						 | 
					4584517ede | ||
| 
						 | 
					e6af223f0d | ||
| 
						 | 
					990351738c | 
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -34,6 +34,7 @@ node_modules
 | 
			
		||||
 | 
			
		||||
# InteliJ
 | 
			
		||||
.idea/workspace.xml
 | 
			
		||||
.idea/shelf
 | 
			
		||||
.vscode
 | 
			
		||||
 | 
			
		||||
lib/
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										11
									
								
								.idea/codeStyles/Project.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								.idea/codeStyles/Project.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
<component name="ProjectCodeStyleConfiguration">
 | 
			
		||||
  <code_scheme name="Project" version="173">
 | 
			
		||||
    <codeStyleSettings language="JavaScript">
 | 
			
		||||
      <indentOptions>
 | 
			
		||||
        <option name="INDENT_SIZE" value="2" />
 | 
			
		||||
        <option name="CONTINUATION_INDENT_SIZE" value="2" />
 | 
			
		||||
        <option name="TAB_SIZE" value="2" />
 | 
			
		||||
      </indentOptions>
 | 
			
		||||
    </codeStyleSettings>
 | 
			
		||||
  </code_scheme>
 | 
			
		||||
</component>
 | 
			
		||||
							
								
								
									
										5
									
								
								.idea/codeStyles/codeStyleConfig.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								.idea/codeStyles/codeStyleConfig.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
<component name="ProjectCodeStyleConfiguration">
 | 
			
		||||
  <state>
 | 
			
		||||
    <option name="USE_PER_PROJECT_SETTINGS" value="true" />
 | 
			
		||||
  </state>
 | 
			
		||||
</component>
 | 
			
		||||
							
								
								
									
										2
									
								
								.idea/misc.xml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								.idea/misc.xml
									
									
									
										generated
									
									
									
								
							@@ -1,6 +1,6 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<project version="4">
 | 
			
		||||
  <component name="JavaScriptSettings">
 | 
			
		||||
    <option name="languageLevel" value="ES5" />
 | 
			
		||||
    <option name="languageLevel" value="ES6" />
 | 
			
		||||
  </component>
 | 
			
		||||
</project>
 | 
			
		||||
							
								
								
									
										78
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										78
									
								
								README.md
									
									
									
									
									
								
							@@ -1,11 +1,14 @@
 | 
			
		||||
# node-eventstore-client
 | 
			
		||||
A port of the EventStore .Net ClientAPI to Node.js
 | 
			
		||||
 | 
			
		||||
## Learning
 | 
			
		||||
 | 
			
		||||
If you want to learn more about EventSourcing/EventModeling, you can join one of the monthly virtual workshops offered by my employer Adaptech Group, see info at [https://adaptechgroup.com/#workshop](https://adaptechgroup.com/#workshop).
 | 
			
		||||
 | 
			
		||||
## Status
 | 
			
		||||
 | 
			
		||||
### Missing features:
 | 
			
		||||
 | 
			
		||||
- Ssl connection
 | 
			
		||||
- Set system settings
 | 
			
		||||
 | 
			
		||||
### Areas to improve
 | 
			
		||||
@@ -21,10 +24,25 @@ A port of the EventStore .Net ClientAPI to Node.js
 | 
			
		||||
 | 
			
		||||
Install using `npm install node-eventstore-client`
 | 
			
		||||
 | 
			
		||||
Versions to install to match EventStore versions:
 | 
			
		||||
 | 
			
		||||
- 0.1.x for ES prior to 3.9.4
 | 
			
		||||
- 0.2.x for ES from 3.9.4 to 5.x
 | 
			
		||||
- 20.10.x for ES 20.10 LTS
 | 
			
		||||
- 21.10.x for ES 21.10 LTS
 | 
			
		||||
- 22.10.x for ES 22.10 LTS
 | 
			
		||||
 | 
			
		||||
### Dependencies
 | 
			
		||||
 | 
			
		||||
- 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`)
 | 
			
		||||
- Node.js >= 14
 | 
			
		||||
- Modules: [long](https://www.npmjs.org/package/long), [protobufjs](https://www.npmjs.org/package/protobufjs), [uuid](https://www.npmjs.org/package/uuid), [strict-event-emitter-types](https://www.npmjs.com/package/strict-event-emitter-types) (installed via `npm install`)
 | 
			
		||||
 | 
			
		||||
### Install and run an Eventstore on localhost
 | 
			
		||||
 | 
			
		||||
See https://eventstore.com
 | 
			
		||||
 | 
			
		||||
*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
 | 
			
		||||
 | 
			
		||||
@@ -35,11 +53,7 @@ The offline documentation can be found in the module folder `./node_modules/node
 | 
			
		||||
#### Online
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
Save to ```app.js:```
 | 
			
		||||
@@ -110,14 +124,60 @@ To generate a test event, open a separate console and run:
 | 
			
		||||
 | 
			
		||||
## Running the tests
 | 
			
		||||
 | 
			
		||||
### Local testing
 | 
			
		||||
 | 
			
		||||
To run the tests it is recommended that you use an in-memory instance of the eventstore so you don't pollute your dev instance.
 | 
			
		||||
 | 
			
		||||
    EventStore.ClusterNode.exe --run-projections=all --memdb
 | 
			
		||||
    EventStore.ClusterNode.exe --run-projections=all --memdb –certificate-file=yourcert.pfx
 | 
			
		||||
    or
 | 
			
		||||
    ./run-node.sh --run-projections=all --memdb –certificate-file=yourcert.p12
 | 
			
		||||
 | 
			
		||||
You can also use docker-compose :
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
# start the single node cluster
 | 
			
		||||
npm run compose:single:start
 | 
			
		||||
# if you want to wait for the cluster to be available
 | 
			
		||||
npm run compose:wait
 | 
			
		||||
# run the tests
 | 
			
		||||
npm run test
 | 
			
		||||
# to cleanup (stop containres, delete volumes)
 | 
			
		||||
npm run compose:single:stop
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
For SSL setup see:
 | 
			
		||||
 | 
			
		||||
https://eventstore.org/docs/server/setting_up_ssl/  
 | 
			
		||||
or  
 | 
			
		||||
https://eventstore.org/docs/server/setting_up_ssl_linux/
 | 
			
		||||
 | 
			
		||||
To execute the tests suites simply run
 | 
			
		||||
 | 
			
		||||
    npm test
 | 
			
		||||
 | 
			
		||||
### Isolated environment
 | 
			
		||||
 | 
			
		||||
To be able to run the tests for different connection types (tcp, gossip, cluster) docker-compose files are available to setup the environment and run the tests.
 | 
			
		||||
 | 
			
		||||
#### Prerequisites
 | 
			
		||||
 | 
			
		||||
* docker
 | 
			
		||||
* docker-compose
 | 
			
		||||
 | 
			
		||||
#### Run
 | 
			
		||||
 | 
			
		||||
To execute the tests suites for single node cluster (tcp connection) simply run
 | 
			
		||||
 | 
			
		||||
    npm run test:single
 | 
			
		||||
 | 
			
		||||
To execute the tests suites for multiple nodes cluster (gossip connection) simply run
 | 
			
		||||
 | 
			
		||||
    npm run test:gossip
 | 
			
		||||
 | 
			
		||||
To execute the tests suites for multiple nodes cluster (dns discovery connection) simply run
 | 
			
		||||
 | 
			
		||||
    npm run test:cluster
 | 
			
		||||
 | 
			
		||||
## Porting .Net Task to Node.js
 | 
			
		||||
 | 
			
		||||
Any async commands returns a [Promise](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise) object in replacement of .Net Task.  
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										11
									
								
								build-and-test.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										11
									
								
								build-and-test.sh
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
 | 
			
		||||
set -e
 | 
			
		||||
 | 
			
		||||
if [[ -d /var/code/src ]]; then
 | 
			
		||||
  cp -R /var/code/{src,test,*.js,*.json} .
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
npm i
 | 
			
		||||
npm run build
 | 
			
		||||
npm run test-debug
 | 
			
		||||
							
								
								
									
										23
									
								
								certs/ca/ca.crt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								certs/ca/ca.crt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
			
		||||
-----BEGIN CERTIFICATE-----
 | 
			
		||||
MIIDzTCCArWgAwIBAgIRAJD0c8z8ITssbEkzjx4ZmRowDQYJKoZIhvcNAQELBQAw
 | 
			
		||||
YjELMAkGA1UEBhMCVUsxGDAWBgNVBAoTD0V2ZW50IFN0b3JlIEx0ZDE5MDcGA1UE
 | 
			
		||||
AxMwRXZlbnRTdG9yZURCIENBIDkwZjQ3M2NjZmMyMTNiMmM2YzQ5MzM4ZjFlMTk5
 | 
			
		||||
OTFhMB4XDTIyMTAyMjEzNTA1N1oXDTI3MTAyMjEzNTA1N1owYjELMAkGA1UEBhMC
 | 
			
		||||
VUsxGDAWBgNVBAoTD0V2ZW50IFN0b3JlIEx0ZDE5MDcGA1UEAxMwRXZlbnRTdG9y
 | 
			
		||||
ZURCIENBIDkwZjQ3M2NjZmMyMTNiMmM2YzQ5MzM4ZjFlMTk5OTFhMIIBIjANBgkq
 | 
			
		||||
hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA17JM4jAG4fM4dtA6mpatLVkYhS42wwHC
 | 
			
		||||
RbG7dQINSE9wMKpoy2u4sDvZQrsudOvdeclPkIL1JgUtk7lDlqRMXZ6HnP7zTCKn
 | 
			
		||||
SQCXzvc3IIU0cGlkffuIS/kuAGBePvmmTwFE3ByDneydlHpSUGEvQY1KEAKwpgSO
 | 
			
		||||
LX1NtthP3kKT+bq0NdQlgOjm9dEkSYWwfCM7Of9cJdh8bCO4zJ1taGqchxluWlpo
 | 
			
		||||
DJL6TTHsZDvDjhfzBxhjuRax4S8B8xLaq6LirTFEFGpqFBhqzGGhRl42ZylKqVo9
 | 
			
		||||
fKhhywwq81ItROmB14OGKa8gyJi7pWGSKRI4M6Ngn89D50Q49K1QdQIDAQABo34w
 | 
			
		||||
fDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBAjApBgNVHQ4EIgQg
 | 
			
		||||
/3vmZ5JvcSlcqyaNXgrQZ5FOXlZ9HvYr9x+Tbrs3Mx4wKwYDVR0jBCQwIoAg/3vm
 | 
			
		||||
Z5JvcSlcqyaNXgrQZ5FOXlZ9HvYr9x+Tbrs3Mx4wDQYJKoZIhvcNAQELBQADggEB
 | 
			
		||||
AIMQR/3BHnVYAuG6DSdDPVYkPR9Fvwi9G9U1nybMHY9uSnEOp6yASrRc/cD7pIbP
 | 
			
		||||
Ax7cvD5f0829fAUFupXtp2T/yNOA7/eis7l6Y0ZZf+QEk9XhZXHVTFLFDb9Fyc6r
 | 
			
		||||
+i/lXnatGsYwOns0RFSG6tzxi2lxUPwlXauacwTBW4jrphtn0vC3q/n85JOEi2ib
 | 
			
		||||
aIlXaXUTREJFiFnS22/SX4dSRaeimL34rrd9AjX53Ne6pUiVBGgd2aSUkBh65EYk
 | 
			
		||||
VCIZwuWLx0jgcT8NI/EeId7FN4CWq73dze5eY2QU00rXidyYDeC2aZcU5e2RTQqn
 | 
			
		||||
5dGqFGAd/xCopGYdWfusqKM=
 | 
			
		||||
-----END CERTIFICATE-----
 | 
			
		||||
							
								
								
									
										27
									
								
								certs/ca/ca.key
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								certs/ca/ca.key
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
			
		||||
-----BEGIN RSA PRIVATE KEY-----
 | 
			
		||||
MIIEpQIBAAKCAQEA17JM4jAG4fM4dtA6mpatLVkYhS42wwHCRbG7dQINSE9wMKpo
 | 
			
		||||
y2u4sDvZQrsudOvdeclPkIL1JgUtk7lDlqRMXZ6HnP7zTCKnSQCXzvc3IIU0cGlk
 | 
			
		||||
ffuIS/kuAGBePvmmTwFE3ByDneydlHpSUGEvQY1KEAKwpgSOLX1NtthP3kKT+bq0
 | 
			
		||||
NdQlgOjm9dEkSYWwfCM7Of9cJdh8bCO4zJ1taGqchxluWlpoDJL6TTHsZDvDjhfz
 | 
			
		||||
BxhjuRax4S8B8xLaq6LirTFEFGpqFBhqzGGhRl42ZylKqVo9fKhhywwq81ItROmB
 | 
			
		||||
14OGKa8gyJi7pWGSKRI4M6Ngn89D50Q49K1QdQIDAQABAoIBAQCbeiKBSC0t4avp
 | 
			
		||||
uN8FX2clMPvDxDQlDLeElUCSbxAz907fRXaUaumN3xYUS+iIzxuuFbYMbNlYtpLL
 | 
			
		||||
0NcvVu7U7NjECeJGFxSOQqcqwHg0MNBD1zRgu1bbrJnEG7LTohCHElsYblVRGKXd
 | 
			
		||||
yO5ckjEGB1pDgCzk/pOdppzGF9Y6Vl/6WfZQgdGV6B1Qh9Vxs+1CGbK/6YqMM3av
 | 
			
		||||
9AJTEXgXbHOPyqNwixjxihpz79hXx0lOznL/CeosHKj7+ZY/knWZcDBmNq3ZA3Nz
 | 
			
		||||
w3p0fDkBtY7zQglh5nTSYoLtpcJvzkAI8uD6eJ4ThwIGUbLlvq0c3yaHZwIqrmEq
 | 
			
		||||
py09FA8BAoGBAPnuy+ehTBXV5k8icPZjI50Bjr5Alres01OjHxAA5bZJACwVbjMQ
 | 
			
		||||
a2464yb6DMA6NDrUevfHvKn3rw8OoceNrlaEua0qE5IweRpROf+ENqW9Yhcg4O1G
 | 
			
		||||
bSUPf5M1JusCSznAJu+gKsqHq0pTtdssh8Xb655xgd3gNMi0lLPlw5+tAoGBANzu
 | 
			
		||||
vidC8LRH+4JRrb+7PUZi1AR8vtCpabkLuVe7AZJl1wXFvYJTyFcW/e0WTvETcclf
 | 
			
		||||
9dhy1c0lH44571L4kpKRRKF4U3lcESbiLPDwjvfnls1rYzfzjY1YWoERwGYxL54H
 | 
			
		||||
2BBYPjKocnHZOnyiBxYn4ysK2O3dYlFxgJy/1GzpAoGBAM4HzW1HqRoC91Va1fY2
 | 
			
		||||
aaA/LXWmdtg5DwhOWwftRXAMI6kzjWFo8rauspxp2uMH2BB7Ildp/xu6A0SNUk3X
 | 
			
		||||
fNTzmsCmA/YqIVrRhNcfHZFpWhgo0WKoAMdhTFCEq21lua+EuFQnG79TMaAW+74O
 | 
			
		||||
qmovzb8SYPUPo1OkkUTvbmENAoGAODTg2Zo1JJhfiyL+ghW/nAWOjOmzneBLzlEG
 | 
			
		||||
QSSJXNZd4tEQynRINqfZyBRx1vEsdJ/eKsfkTsGQCp4AneoxV+pvPGkhS3G5x1up
 | 
			
		||||
NU7uAHHBstcMMfLbY0dEFywN97GxvJGgTWA1yquCGia6s3SBOwjAyXWEBNfaqH+o
 | 
			
		||||
ybgf8ekCgYEA3/Vx/CZ/VB0Fr47cpZGckJWH6lDWkzBEcaAT22VYlhL4CZ0CRDWj
 | 
			
		||||
6+LSiQDuI3+JwEhZlIkTvfZSo5bhNeUHoEL+15yg2RvsWFzorDxBfvZ//29BQg/Q
 | 
			
		||||
bN+vlKHpn7V7T9LQg/Tp107mfW6Z/TG4UYIVJyxY/JUjXjQLcFPvTVE=
 | 
			
		||||
-----END RSA PRIVATE KEY-----
 | 
			
		||||
							
								
								
									
										20
									
								
								certs/eventstore-local.crt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								certs/eventstore-local.crt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,20 @@
 | 
			
		||||
-----BEGIN CERTIFICATE-----
 | 
			
		||||
MIIDSzCCAjMCFAxEesn/oIrU2T7DOU9cWCyoCCqfMA0GCSqGSIb3DQEBCwUAMGIx
 | 
			
		||||
CzAJBgNVBAYTAkNBMQswCQYDVQQIDAJCQzESMBAGA1UEBwwJVmFuY291dmVyMRcw
 | 
			
		||||
FQYDVQQKDA5BZGFwdGVjaCBHcm91cDEZMBcGA1UEAwwQZXZlbnRzdG9yZS5sb2Nh
 | 
			
		||||
bDAeFw0yMTA1MDYyMDAyMzZaFw0zMTA1MDQyMDAyMzZaMGIxCzAJBgNVBAYTAkNB
 | 
			
		||||
MQswCQYDVQQIDAJCQzESMBAGA1UEBwwJVmFuY291dmVyMRcwFQYDVQQKDA5BZGFw
 | 
			
		||||
dGVjaCBHcm91cDEZMBcGA1UEAwwQZXZlbnRzdG9yZS5sb2NhbDCCASIwDQYJKoZI
 | 
			
		||||
hvcNAQEBBQADggEPADCCAQoCggEBANbNrVQ91TFVsrfFV39/1MjxM/UIP78FaX+S
 | 
			
		||||
kxAzcpAJKP9PbHLwFXxkl0Bam+3ekE6+hc3qT8o4ksOdzwz+dJbdZF8gblLda7vq
 | 
			
		||||
JnPjkAZuhojRLPfXvaJZbManEkB30+JIvb/XWhMf34+kvyZaOnKqidzNAuLAFQ+6
 | 
			
		||||
KCCXYnTUFimumr6AsrZvA9UzN3edrk1pqxMYNT+8MBOUnNfkdHX78aTzdWvq4+Ro
 | 
			
		||||
+58MT3NpqdI+1cY423JlG2qj8PAqPsgdE4XvmtqDtLndH+VflR1M1Rkn41cofgSh
 | 
			
		||||
lo7PE2SNn4hSv8m+1HJMfcegJEXKE3LIGHJtV6qT6S+pRtJd9mcCAwEAATANBgkq
 | 
			
		||||
hkiG9w0BAQsFAAOCAQEAlhKziHmYm81vrx+EHqIZXvmoUp3I1A9STvFqUdHrv9sa
 | 
			
		||||
8tKD7wW0owTVaxXBW3380ZFRpG3JVJFUgOyFIhi4IccWoqVsBCE0BBR96tlRXrKT
 | 
			
		||||
UZTAHLEk/SdLL+qfhKgY7F7+M9Wtf5HldiRfNoTqYn6YVXMJMgcwehhHho/fCHzj
 | 
			
		||||
tzOMfKFjGAq+n8cScLrTaW92JbbxjFPJJ7uQDH4OjAHx6pT885+RJf0rNqboAErA
 | 
			
		||||
lRLcEjtihslWKD7nelOlJE1egkum/m7MLVFpZPqEBp+x1zXdwacENwIhiRrQQhKi
 | 
			
		||||
8Qw36BuSCZ3CZK18kGyhtxl/uUP/wx7XXc1U0W2Wtw==
 | 
			
		||||
-----END CERTIFICATE-----
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								certs/eventstore.p12
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								certs/eventstore.p12
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										24
									
								
								certs/node1/node1.crt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								certs/node1/node1.crt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
			
		||||
-----BEGIN CERTIFICATE-----
 | 
			
		||||
MIIECDCCAvCgAwIBAgIQI83qjs8Vn2iLbeUZbTPRcTANBgkqhkiG9w0BAQsFADBi
 | 
			
		||||
MQswCQYDVQQGEwJVSzEYMBYGA1UEChMPRXZlbnQgU3RvcmUgTHRkMTkwNwYDVQQD
 | 
			
		||||
EzBFdmVudFN0b3JlREIgQ0EgOTBmNDczY2NmYzIxM2IyYzZjNDkzMzhmMWUxOTk5
 | 
			
		||||
MWEwHhcNMjMwMTMwMTUyMzM0WhcNMjQwMTMwMTUyMzM0WjAcMRowGAYDVQQDExFl
 | 
			
		||||
dmVudHN0b3JlZGItbm9kZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
 | 
			
		||||
AL3CBeNLxZDvUA4WMRACrM+kxvrlD8ahs9MOFfAJHCNLoNR4mWAvh+BUDHsG7E56
 | 
			
		||||
4I5Y7XbC0cCIIER3/QB6Jz80kcJ4y745d9RCbYSqTeUnptrLdcXDNiwbI3bAjyuJ
 | 
			
		||||
tEqg+iPjrz2E6bSlZ4GSxKSTC95Dm80UUU/CG6+H1FesN8JP+ruYey4S5bYASy6o
 | 
			
		||||
z1NtYaPDGqSqDGvLhuWQNKoJAAc4g1R/UcVFbuI2asnCkFGjDF7gcRKkHpw0DNhN
 | 
			
		||||
TMQWMdQ2+I8it5UwNzYpsCZj/le5a54mNZqNYj52nEpURDsdJy4BXJy5dUwADZHz
 | 
			
		||||
ffN+ciWEToQz2hZmnliIG98CAwEAAaOB/zCB/DAOBgNVHQ8BAf8EBAMCBaAwHQYD
 | 
			
		||||
VR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwKQYDVR0O
 | 
			
		||||
BCIEIFRmt7SsPXFStSAcZDS9OCP03JyevPMV6/1R0Utg8UA3MCsGA1UdIwQkMCKA
 | 
			
		||||
IP975meSb3EpXKsmjV4K0GeRTl5WfR72K/cfk267NzMeMGUGA1UdEQReMFyCKmNs
 | 
			
		||||
dXN0ZXIudGVzdHMubm9kZS1ldmVudHN0b3JlLWNsaWVudC5sb2NhbIIobm9kZTEu
 | 
			
		||||
dGVzdHMubm9kZS1ldmVudHN0b3JlLWNsaWVudC5sb2NhbIcEwKghCjANBgkqhkiG
 | 
			
		||||
9w0BAQsFAAOCAQEATHxhyf27pPFJRegPB9ozm4P06MkvZMm4syxmoR1jJohm+7Xp
 | 
			
		||||
7jd9ENATFApZNxV+/MYGgryML9Y+Md/Bd1fttP8j0MUR5euJX8zehrnCufaIw2If
 | 
			
		||||
/a9YalJ2/a+WElAgTHM1sCpdvL+WwsQ6IjWPVfGIu7VIotQXIqllZUjMd3rFI4Ip
 | 
			
		||||
9CkMgXbZzls8OhWH1FnPkFFjolqITwcgSmn3NWbQkl6qFYFjAZ8pFcjhdNay7yZx
 | 
			
		||||
+Pe9gEPbi6iyP50xb0LQtJXQQvFhwmDQbR5v0xiBI6ONK8mha3fQkxmV1wMPJdvQ
 | 
			
		||||
TOva/iFP4qmjyewyzOd752DN6r4qFlpb39Hpmw==
 | 
			
		||||
-----END CERTIFICATE-----
 | 
			
		||||
							
								
								
									
										27
									
								
								certs/node1/node1.key
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								certs/node1/node1.key
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
			
		||||
-----BEGIN RSA PRIVATE KEY-----
 | 
			
		||||
MIIEpAIBAAKCAQEAvcIF40vFkO9QDhYxEAKsz6TG+uUPxqGz0w4V8AkcI0ug1HiZ
 | 
			
		||||
YC+H4FQMewbsTnrgjljtdsLRwIggRHf9AHonPzSRwnjLvjl31EJthKpN5Sem2st1
 | 
			
		||||
xcM2LBsjdsCPK4m0SqD6I+OvPYTptKVngZLEpJML3kObzRRRT8Ibr4fUV6w3wk/6
 | 
			
		||||
u5h7LhLltgBLLqjPU21ho8MapKoMa8uG5ZA0qgkABziDVH9RxUVu4jZqycKQUaMM
 | 
			
		||||
XuBxEqQenDQM2E1MxBYx1Db4jyK3lTA3NimwJmP+V7lrniY1mo1iPnacSlREOx0n
 | 
			
		||||
LgFcnLl1TAANkfN9835yJYROhDPaFmaeWIgb3wIDAQABAoIBAFO5a8eiAwWz0Wql
 | 
			
		||||
t/gMdhsX5QOGVbOaXTFeIafLHTMlh0y3+VRLJHSCIQ+XOmRWKwYjjoK76rg8V6Be
 | 
			
		||||
IK85Nl/Y3gckLSE9UfXBaXkDe2MEX8ZhxxD+1MQZJUicJY9cLsROyo9TQlqubj9a
 | 
			
		||||
S5UMIN9MUgw7YF7X/Bho2LZWBAa6Hz3LSyndwArvqZeUf8ovmJnWEUvJB8amVhwB
 | 
			
		||||
DoYqyNjiqIEJYWRfCeGfLEOmotmwCfYeJFyr84r3wfS6qmaesKM8Nbz8eSSNg7n3
 | 
			
		||||
5LcAL2Bv3hvsMmUEZQl3J41AtBVsU5DgbTf6/seuKvfVOcqVp9AtZp2rg3xY4pNI
 | 
			
		||||
7gN4wiECgYEA1lBh13LdjM0rOg9096ee2hQKjFvwVki0xzZigmf94CXoAJ19qwOe
 | 
			
		||||
J0WXfk1g5GP1bg5pdVhKdS+LEIqet9ipaall5hWotaYJdyOtWiQan9wRRa3sk6pl
 | 
			
		||||
K29LBF+XzZWAKE7C2371rVyMXViHzv056wasw0RSgxd6HBi1mOpcveMCgYEA4qrj
 | 
			
		||||
Ha24Qh+/b883FaMphYrl8H8nMgAdGmi7HiLnJx6jzPzalsBI5+qnDY8/oqeAie66
 | 
			
		||||
k8c6uRKOsEFrsbK/w3+21rGuZb9t9PupDONFOW9D94744HDFu0Clnr5S2ABKM9D6
 | 
			
		||||
hUL2qQedAqZx5CNWbpM/wdV0OBKhveIb9OyjytUCgYA21jCC0ThRK7owy/2w1Kn3
 | 
			
		||||
wQMF8Qxo94eSJZ9FINi7/tcDOUkLdgyEnfDqd2AgcFc/Rt7DEMlUfMrHe8Cq5/xJ
 | 
			
		||||
NfgFzGrzt71aR722f+B0IPomax9KlWH3oC2Au/j6uJMnPSfsw+qW5kRgKiPt2at1
 | 
			
		||||
MKsJ97RpKJutDsGAlA8Q4wKBgQCUyjBD7yEg5s43iwJRxcUf0EmYUR9dhw2TpGQQ
 | 
			
		||||
KEEsQMStbt3eT2KMOlBmaj4Pe3y5DmiTURiPHEtmD8ut3fRbVJ6k2AXu7HY1dm1F
 | 
			
		||||
9HogdZVcEBH24pAplwog5jZja+1Jjkik6YwY8NJ0RuZEJ544/5e+mWus0y4xAxfu
 | 
			
		||||
8teh8QKBgQDQm6vKAsldQStgj9gwRiTAUrMPTriVQTUd4/8lof+RoIJWM7CARLos
 | 
			
		||||
9MYkAefv4MgjvwWNn8RbFjN91NBX4qpCjgm62P25npFSKQAK+JQlvj7MbSw54jyx
 | 
			
		||||
2/uj4JEMM1rOocJr9tvYAeC2nnZMOuhesLVy+SHF9TJ2WtalDOTZ1A==
 | 
			
		||||
-----END RSA PRIVATE KEY-----
 | 
			
		||||
							
								
								
									
										24
									
								
								certs/node2/node2.crt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								certs/node2/node2.crt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
			
		||||
-----BEGIN CERTIFICATE-----
 | 
			
		||||
MIIECDCCAvCgAwIBAgIQdipz5iGZgwtJYjBK4mjFijANBgkqhkiG9w0BAQsFADBi
 | 
			
		||||
MQswCQYDVQQGEwJVSzEYMBYGA1UEChMPRXZlbnQgU3RvcmUgTHRkMTkwNwYDVQQD
 | 
			
		||||
EzBFdmVudFN0b3JlREIgQ0EgOTBmNDczY2NmYzIxM2IyYzZjNDkzMzhmMWUxOTk5
 | 
			
		||||
MWEwHhcNMjMwMTMwMTUyMzQwWhcNMjQwMTMwMTUyMzQwWjAcMRowGAYDVQQDExFl
 | 
			
		||||
dmVudHN0b3JlZGItbm9kZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
 | 
			
		||||
AOJZaF5skFJeNOgkqG8B38lV6lhKwvrmspxZvw7tP8dhzV7R+EUdTXYS86ximW4c
 | 
			
		||||
cdK5zqXRgZG6WaaFFN4BeCLqum+602l9Bw88K5Ww68v5R9VP8sgt7w4UsqvVjTJ4
 | 
			
		||||
60R59PvfrwkIL1DFkKBM4B7CmdLR20VZiJQ9YghR03TBbjjvIhaDyprmxu0vDsF7
 | 
			
		||||
f3zNmcnBF+14Z0b/exevtiVbyvNQ6nQENSo7Whz/kDV1a2i/BsVlsbFc43ywmsHL
 | 
			
		||||
Ks1z2rSctTgfYmK/yUFaR4B1mkzhQf9/CfJxJQLekC9Zv85ah9tMGwl/pbDfZh7q
 | 
			
		||||
NUJQHjJMm4I/HeeTQPd1CXcCAwEAAaOB/zCB/DAOBgNVHQ8BAf8EBAMCBaAwHQYD
 | 
			
		||||
VR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwKQYDVR0O
 | 
			
		||||
BCIEIDlz3IFnAja157ly4cFxgZTfYrwlqAhgtbEu4TVhO/yPMCsGA1UdIwQkMCKA
 | 
			
		||||
IP975meSb3EpXKsmjV4K0GeRTl5WfR72K/cfk267NzMeMGUGA1UdEQReMFyCKmNs
 | 
			
		||||
dXN0ZXIudGVzdHMubm9kZS1ldmVudHN0b3JlLWNsaWVudC5sb2NhbIIobm9kZTIu
 | 
			
		||||
dGVzdHMubm9kZS1ldmVudHN0b3JlLWNsaWVudC5sb2NhbIcEwKghCzANBgkqhkiG
 | 
			
		||||
9w0BAQsFAAOCAQEAvj0ZjZkKdqwVdfXJAhMPGZwMf8gfZRpSCJe95FL0yePUk/jm
 | 
			
		||||
di2qk2sb2+W9prPR1Nbs1hfLnHHBw32yrxekvFSUC6Qc23X8S9QU01FOO7uEVtnM
 | 
			
		||||
fdEzyuZcdPBK2SAL/CxN0WH/yUxNWkWnqQKegZxkvpMVxMAsA0l3twWwfkEQtjhA
 | 
			
		||||
V/dcS5WwZxyyvCQ0qAVZ4+Zd/huvmsNIaXplvCs/P8yU6SR0TUdahJpfxJeKkKIf
 | 
			
		||||
k2h2/G36i26lTTm2TyxO4A2v8PotRO0xhjJkVKVEs4ZuY+lK6JUoTaM9Z8FubDqE
 | 
			
		||||
K2KH+YCBdER5jQK2YbmZDRh58aKMpCXtCx8RqQ==
 | 
			
		||||
-----END CERTIFICATE-----
 | 
			
		||||
							
								
								
									
										27
									
								
								certs/node2/node2.key
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								certs/node2/node2.key
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
			
		||||
-----BEGIN RSA PRIVATE KEY-----
 | 
			
		||||
MIIEpQIBAAKCAQEA4lloXmyQUl406CSobwHfyVXqWErC+uaynFm/Du0/x2HNXtH4
 | 
			
		||||
RR1NdhLzrGKZbhxx0rnOpdGBkbpZpoUU3gF4Iuq6b7rTaX0HDzwrlbDry/lH1U/y
 | 
			
		||||
yC3vDhSyq9WNMnjrRHn0+9+vCQgvUMWQoEzgHsKZ0tHbRVmIlD1iCFHTdMFuOO8i
 | 
			
		||||
FoPKmubG7S8OwXt/fM2ZycEX7XhnRv97F6+2JVvK81DqdAQ1KjtaHP+QNXVraL8G
 | 
			
		||||
xWWxsVzjfLCawcsqzXPatJy1OB9iYr/JQVpHgHWaTOFB/38J8nElAt6QL1m/zlqH
 | 
			
		||||
20wbCX+lsN9mHuo1QlAeMkybgj8d55NA93UJdwIDAQABAoIBAQDR3UvjoIz/kdFE
 | 
			
		||||
HBj/M6GmLz6ktkyqDRQ12xBGarrjxk6AR/YFPvH/M/syLglMCpuOYjCzldiooTtW
 | 
			
		||||
JbX/USVuWmyaA4LZH89X1NYkaHF4IZz0rrfP2qb3S0GOCOZtkaexSdJXZkIIAcq8
 | 
			
		||||
/TDnL9/tJUkyKtk/J5B2waMPS67fZGoZ6wx3sHZ7/CCcvdtHSvCT5+taVoHGUDPi
 | 
			
		||||
kToGcJAIDKAOakZfv1bfzYFyln18NA55V+133tGfZYJrILmEwLcU2Y7BAaoD+yme
 | 
			
		||||
+BWU3eKgYRCsvA+HzdgDetEaqp78Ax/G29OUK9NWdXk2hwhmkpZgSLV3g7OlfNve
 | 
			
		||||
6pmuEpcBAoGBAOPIMM+uYQJmRIapXZADQOc7VkF55sSjh3h25tjS8iHIEGQ9gb8n
 | 
			
		||||
h4iNUDC73NN9Yfw6/vKrwcpIq5nQKRRUQ+NJFxurtN6XBBlYNf336tg6S/65oe3W
 | 
			
		||||
R3m35/w72qcct1aOASDafuxdoEV/kbflpao57PxRZAXGdMPJANDckujXAoGBAP5j
 | 
			
		||||
x4NZvYI73oL2OI/2CJytA5uksfsh0ymusNKRaBhqLwFIE1Ud/CHj5eG1Bo9ox8Yl
 | 
			
		||||
e5AdkMmSSYFIe3B/P1apFI22/GKc1on2mFXKRY8zAMVLGbsLJarQz4xIX36bafUh
 | 
			
		||||
1O9JM1d6PWDITAzoptIJDF7U41jxbbGMic6gIbBhAoGAMOUkNTCFenJhe1aX0vYf
 | 
			
		||||
1IMUPPHh64v+5IkBfMGrYD0F576cP2BI47MR56Qr/uoHQpGXcJgV/UokK9xXNRnx
 | 
			
		||||
iLSD1VjCdpWMN7SLwnyZWNkKvx8x90/r/+DOV4KxqPWtFVNeQqMkY7ClWsXLjeIp
 | 
			
		||||
8aSFjpQaGHNFVVGsbykqD/kCgYEA3BZ/eoidiJs7e5qCfSqjcMnPIU1wHpG5G4rj
 | 
			
		||||
uInMwbK8UCOHdlCm3rtJG+l+b3x7ulabfKfXqE1EAvIuubmdluBZw/HYkYiXpG0Q
 | 
			
		||||
hsilPasms4qyDD0srYhSyE+lLuhO16IZk5yFKt27VIx2H4T5LyZc6X7N4xmdicrJ
 | 
			
		||||
P1cTToECgYEAlW2xWDl90suSAw1Tv23BVEX6ol/UColtGY8VDIHsXPDBYImtGiFt
 | 
			
		||||
MibOuyzWsvPw0HZDzWw9otU0735clhK34v+E1WyPFvOAo18orcCS4A6Fi42tp5oG
 | 
			
		||||
sNVxiYJFFUn+nnHUoGZNuKlB5PZR1Wxus6wXY2rZdoQ6QsBD0XjquCE=
 | 
			
		||||
-----END RSA PRIVATE KEY-----
 | 
			
		||||
							
								
								
									
										24
									
								
								certs/node3/node3.crt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								certs/node3/node3.crt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
			
		||||
-----BEGIN CERTIFICATE-----
 | 
			
		||||
MIIECDCCAvCgAwIBAgIQecOoexYVeIUtLwNQp179vzANBgkqhkiG9w0BAQsFADBi
 | 
			
		||||
MQswCQYDVQQGEwJVSzEYMBYGA1UEChMPRXZlbnQgU3RvcmUgTHRkMTkwNwYDVQQD
 | 
			
		||||
EzBFdmVudFN0b3JlREIgQ0EgOTBmNDczY2NmYzIxM2IyYzZjNDkzMzhmMWUxOTk5
 | 
			
		||||
MWEwHhcNMjMwMTMwMTUyMzQ2WhcNMjQwMTMwMTUyMzQ2WjAcMRowGAYDVQQDExFl
 | 
			
		||||
dmVudHN0b3JlZGItbm9kZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
 | 
			
		||||
AN8iXoWZjjxOqJJLTHmHOy89lbk2pBo/ca7qPZ/WC+I52A4Lgw58/O7tV/RHFyao
 | 
			
		||||
X8lS2hAVMlRfToUqj7ILAVBeF3t827W0qttbv+wdnxvIWqpq1HdtV5xgLIUXbyiQ
 | 
			
		||||
SI97Tgn7zDJOvm41sHV0xsPWKlritliDByXlGMOabzV53yxa1c0cU2bP5n7nc9wW
 | 
			
		||||
KOH03OU64qCj6MJTdi35peKDhaAcRtGmr5ZggUCP4n9GUzJ1FATAkcrLMOjoh1v1
 | 
			
		||||
K6auqOQZ8f+ns+3bQ4G96rZxwwrSzI/leUFY4u/lzjLUlEuLALJquPrB6RiwzTwb
 | 
			
		||||
BOaTYG6mgWORWPBupjpj67cCAwEAAaOB/zCB/DAOBgNVHQ8BAf8EBAMCBaAwHQYD
 | 
			
		||||
VR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwKQYDVR0O
 | 
			
		||||
BCIEIMdKDLFiWvROUmnmDVing8S3lLisBr+vfrrM+A0t3yycMCsGA1UdIwQkMCKA
 | 
			
		||||
IP975meSb3EpXKsmjV4K0GeRTl5WfR72K/cfk267NzMeMGUGA1UdEQReMFyCKmNs
 | 
			
		||||
dXN0ZXIudGVzdHMubm9kZS1ldmVudHN0b3JlLWNsaWVudC5sb2NhbIIobm9kZTMu
 | 
			
		||||
dGVzdHMubm9kZS1ldmVudHN0b3JlLWNsaWVudC5sb2NhbIcEwKghDDANBgkqhkiG
 | 
			
		||||
9w0BAQsFAAOCAQEAEJmQloXSfxqWGIdGFi7UFDNr3oTxuQsEJRztKzA1rRPbvFhp
 | 
			
		||||
jJ1uPZKRv0SBnmaQa6+PW1zphP+kklmMq9XqiFqq7D7FmYgr2err08DbQfMxyEhG
 | 
			
		||||
yHmaBFzEyI/rm8jRn3K5DMV6cDCB3jTn5eud3oVVAZwTsLcR3mB2UpSJ7lAJgRFs
 | 
			
		||||
5pfFFgHKCQ4YQcFIkNtMeda7KpVv4YxoltJMSISDGvo4fcNhCH62H6/PDJFBi/e9
 | 
			
		||||
L4vB7eZHaO//8UQQxV24VSDLDBP1MQ4ucLZEVam9HQj4qK+DiwDlH6WmQs22FqqE
 | 
			
		||||
i7aLjEEu9Ko2zG7hzTp1jxDfyPw5iByax1JdXw==
 | 
			
		||||
-----END CERTIFICATE-----
 | 
			
		||||
							
								
								
									
										27
									
								
								certs/node3/node3.key
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								certs/node3/node3.key
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
			
		||||
-----BEGIN RSA PRIVATE KEY-----
 | 
			
		||||
MIIEpAIBAAKCAQEA3yJehZmOPE6okktMeYc7Lz2VuTakGj9xruo9n9YL4jnYDguD
 | 
			
		||||
Dnz87u1X9EcXJqhfyVLaEBUyVF9OhSqPsgsBUF4Xe3zbtbSq21u/7B2fG8haqmrU
 | 
			
		||||
d21XnGAshRdvKJBIj3tOCfvMMk6+bjWwdXTGw9YqWuK2WIMHJeUYw5pvNXnfLFrV
 | 
			
		||||
zRxTZs/mfudz3BYo4fTc5TrioKPowlN2Lfml4oOFoBxG0aavlmCBQI/if0ZTMnUU
 | 
			
		||||
BMCRyssw6OiHW/Urpq6o5Bnx/6ez7dtDgb3qtnHDCtLMj+V5QVji7+XOMtSUS4sA
 | 
			
		||||
smq4+sHpGLDNPBsE5pNgbqaBY5FY8G6mOmPrtwIDAQABAoIBADk571QEVd5RrhoX
 | 
			
		||||
Bb4FWMB84vFleiDhNJ7PpI5hrxqOC0NO4IXOuG/unygfM2jOtgJEJXkKdqX8635r
 | 
			
		||||
s/7No8Cg4RTiqNapR0iK92XvEudlMxuR2nvmpxmL8N8Ra4jTuEhUL2eQFIaye1R4
 | 
			
		||||
oJD/Khr/yk0U5/87W5H0d61y5iKobF87QbI9xxkBGGQygsvoEni4sHchN1se/Ha8
 | 
			
		||||
y9nb6B/9sYU8lfSSaRhS/sqpH/ppnptWr1hwxj6jxI21uMB+cWN+rs8j1F0Zizex
 | 
			
		||||
+TTDqhyuYoqh1x2J9UFCjipiKVnA1563eFmtQZk2nrNdjvN6K9qWa0iF8IgTGvdh
 | 
			
		||||
m+9NNEECgYEA6sYqugSzeVCqBqHKAQKESsO6XOQjwkDZQhgeDG8Sal5RArlNsup6
 | 
			
		||||
hh/ZONPCL/6zxz5oKEyxzsTg4tJI9F3uqkpF5rcM1UGCc3maywXmLUd70NuTWM2G
 | 
			
		||||
hz+R4IhKyuQsFhWzFRBh10rorSvjIflkKiviZp+lNiDp1UnY0pOhxWUCgYEA807M
 | 
			
		||||
i60fuTTZsvGKhExORHUOnfs3USst1zHODDAaQYyjUYJP7ix/azf1ciHeeNCZ9rzF
 | 
			
		||||
9xBlDKChRSvKPnU0K07C49a+WI4rdgw8zS+8dqKdvaczPas0InPzXs+oW/O6I86I
 | 
			
		||||
ANEanw9fgrAPEL4/8TLMLhjTV3msdrJ04KzVWOsCgYEAtc9Ax01cr1YIVZp1FNMe
 | 
			
		||||
H8fzSnxiNMyDcuu6WWaqnDTuB234/dUXjUacsaVLfF+CWYm6n3rFN5q/jOfMF3Gm
 | 
			
		||||
obli6IhZJ8zTeRlzBkZLOkVhXRytvtdqltJj5b2mLfkFKxUi2e0V1+PqzDBwdJ7t
 | 
			
		||||
MrtJWK/JAWH7s3C8uFYbsQECgYEAsxD2d4H1zA/6fLlKEa47GCTymhCumJ1nwm4U
 | 
			
		||||
UGICoOWJuU5n10mGiXmIufP1UQNtnOs342p8hDugFVFyKl+GAq2Xv6lnM7OGhv3g
 | 
			
		||||
rb6JPOLXpyHsE2HyH70oi0nXhb0t7HZvH/LFXfUpfPxoShFK7BBPt0lsGYAiDsWu
 | 
			
		||||
QUDST/sCgYAVljJlvlEx8C8HmBrSeeh+Zec9t9HDjl04jNAwenY4x5hD1l1u2ij5
 | 
			
		||||
OJqVodZd1s/To7Dm9Xc6w7r6c9x8xsok4Kc3izc/KQXlxPvRnxF76J4KsMw8kEU1
 | 
			
		||||
LnQN+igffijohdln2Q8cQnEZylM1N4e+sNat5ufEzTk7MBn1676aHA==
 | 
			
		||||
-----END RSA PRIVATE KEY-----
 | 
			
		||||
							
								
								
									
										134
									
								
								docker-compose-cluster.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								docker-compose-cluster.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,134 @@
 | 
			
		||||
version: '3.7'
 | 
			
		||||
 | 
			
		||||
services:
 | 
			
		||||
  eventstore1:
 | 
			
		||||
    image: eventstore/eventstore:22.10.0-buster-slim
 | 
			
		||||
    environment:
 | 
			
		||||
      - EVENTSTORE_CLUSTER_SIZE=3
 | 
			
		||||
      - EVENTSTORE_CLUSTER_DNS=cluster.tests.node-eventstore-client.local
 | 
			
		||||
      - EVENTSTORE_ADVERTISE_HOST_TO_CLIENT_AS=node1.tests.node-eventstore-client.local
 | 
			
		||||
      - EVENTSTORE_ADVERTISE_HTTP_PORT_TO_CLIENT_AS=2113
 | 
			
		||||
      - EVENTSTORE_ADVERTISE_TCP_PORT_TO_CLIENT_AS=1113
 | 
			
		||||
#      - EVENTSTORE_DISCOVER_VIA_DNS=False
 | 
			
		||||
#      - EVENTSTORE_GOSSIP_SEED=192.168.33.10:2113,192.168.33.11:2113,192.168.33.12:2113
 | 
			
		||||
      - EVENTSTORE_RUN_PROJECTIONS=All
 | 
			
		||||
      - EVENTSTORE_START_STANDARD_PROJECTIONS=True
 | 
			
		||||
      - EVENTSTORE_ENABLE_EXTERNAL_TCP=true
 | 
			
		||||
      - EVENTSTORE_EXT_TCP_PORT=1113
 | 
			
		||||
      - EVENTSTORE_HTTP_PORT=2113
 | 
			
		||||
      - EVENTSTORE_INT_IP=192.168.33.10
 | 
			
		||||
      - EVENTSTORE_EXT_IP=192.168.33.10
 | 
			
		||||
      - EVENTSTORE_CERTIFICATE_FILE=/etc/eventstore/certs/node1/node1.crt
 | 
			
		||||
      - EVENTSTORE_CERTIFICATE_PRIVATE_KEY_FILE=/etc/eventstore/certs/node1/node1.key
 | 
			
		||||
      - EVENTSTORE_TRUSTED_ROOT_CERTIFICATES_PATH=/etc/eventstore/certs/ca
 | 
			
		||||
    expose:
 | 
			
		||||
      - "1112"
 | 
			
		||||
      - "1113"
 | 
			
		||||
      - "2113"
 | 
			
		||||
    ports:
 | 
			
		||||
      - "1112:1112"
 | 
			
		||||
      - "1113:1113"
 | 
			
		||||
      - "2113:2113"
 | 
			
		||||
    networks:
 | 
			
		||||
      app_net:
 | 
			
		||||
        aliases:
 | 
			
		||||
          - cluster.tests.node-eventstore-client.local
 | 
			
		||||
          - node1.tests.node-eventstore-client.local
 | 
			
		||||
        ipv4_address: 192.168.33.10
 | 
			
		||||
    volumes:
 | 
			
		||||
      - eventstore1-data:/var/lib/eventstore
 | 
			
		||||
      - ./certs:/etc/eventstore/certs:ro
 | 
			
		||||
 | 
			
		||||
  eventstore2:
 | 
			
		||||
    image: eventstore/eventstore:22.10.0-buster-slim
 | 
			
		||||
    environment:
 | 
			
		||||
      - EVENTSTORE_CLUSTER_SIZE=3
 | 
			
		||||
      - EVENTSTORE_CLUSTER_DNS=cluster.tests.node-eventstore-client.local
 | 
			
		||||
      - EVENTSTORE_ADVERTISE_HOST_TO_CLIENT_AS=node2.tests.node-eventstore-client.local
 | 
			
		||||
      - EVENTSTORE_ADVERTISE_HTTP_PORT_TO_CLIENT_AS=2113
 | 
			
		||||
      - EVENTSTORE_ADVERTISE_TCP_PORT_TO_CLIENT_AS=1113
 | 
			
		||||
#      - EVENTSTORE_DISCOVER_VIA_DNS=False
 | 
			
		||||
#      - EVENTSTORE_GOSSIP_SEED=192.168.33.10:2113,192.168.33.11:2113,192.168.33.12:2113
 | 
			
		||||
      - EVENTSTORE_RUN_PROJECTIONS=All
 | 
			
		||||
      - EVENTSTORE_START_STANDARD_PROJECTIONS=True
 | 
			
		||||
      - EVENTSTORE_ENABLE_EXTERNAL_TCP=true
 | 
			
		||||
      - EVENTSTORE_EXT_TCP_PORT=1113
 | 
			
		||||
      - EVENTSTORE_HTTP_PORT=2113
 | 
			
		||||
      - EVENTSTORE_INT_IP=192.168.33.11
 | 
			
		||||
      - EVENTSTORE_EXT_IP=192.168.33.11
 | 
			
		||||
      - EVENTSTORE_CERTIFICATE_FILE=/etc/eventstore/certs/node2/node2.crt
 | 
			
		||||
      - EVENTSTORE_CERTIFICATE_PRIVATE_KEY_FILE=/etc/eventstore/certs/node2/node2.key
 | 
			
		||||
      - EVENTSTORE_TRUSTED_ROOT_CERTIFICATES_PATH=/etc/eventstore/certs/ca
 | 
			
		||||
    expose:
 | 
			
		||||
      - "1113"
 | 
			
		||||
      - "1112"
 | 
			
		||||
      - "2113"
 | 
			
		||||
    networks:
 | 
			
		||||
      app_net:
 | 
			
		||||
        aliases:
 | 
			
		||||
          - cluster.tests.node-eventstore-client.local
 | 
			
		||||
          - node2.tests.node-eventstore-client.local
 | 
			
		||||
        ipv4_address: 192.168.33.11
 | 
			
		||||
    volumes:
 | 
			
		||||
      - eventstore2-data:/var/lib/eventstore
 | 
			
		||||
      - ./certs:/etc/eventstore/certs:ro
 | 
			
		||||
 | 
			
		||||
  eventstore3:
 | 
			
		||||
    image: eventstore/eventstore:22.10.0-buster-slim
 | 
			
		||||
    environment:
 | 
			
		||||
      - EVENTSTORE_CLUSTER_SIZE=3
 | 
			
		||||
      - EVENTSTORE_CLUSTER_DNS=cluster.tests.node-eventstore-client.local
 | 
			
		||||
      - EVENTSTORE_ADVERTISE_HOST_TO_CLIENT_AS=node3.tests.node-eventstore-client.local
 | 
			
		||||
      - EVENTSTORE_ADVERTISE_HTTP_PORT_TO_CLIENT_AS=2113
 | 
			
		||||
      - EVENTSTORE_ADVERTISE_TCP_PORT_TO_CLIENT_AS=1113
 | 
			
		||||
#      - EVENTSTORE_DISCOVER_VIA_DNS=False
 | 
			
		||||
#      - EVENTSTORE_GOSSIP_SEED=192.168.33.10:2113,192.168.33.11:2113,192.168.33.12:2113
 | 
			
		||||
      - EVENTSTORE_RUN_PROJECTIONS=All
 | 
			
		||||
      - EVENTSTORE_START_STANDARD_PROJECTIONS=True
 | 
			
		||||
      - EVENTSTORE_ENABLE_EXTERNAL_TCP=true
 | 
			
		||||
      - EVENTSTORE_EXT_TCP_PORT=1113
 | 
			
		||||
      - EVENTSTORE_HTTP_PORT=2113
 | 
			
		||||
      - EVENTSTORE_INT_IP=192.168.33.12
 | 
			
		||||
      - EVENTSTORE_EXT_IP=192.168.33.12
 | 
			
		||||
      - EVENTSTORE_CERTIFICATE_FILE=/etc/eventstore/certs/node3/node3.crt
 | 
			
		||||
      - EVENTSTORE_CERTIFICATE_PRIVATE_KEY_FILE=/etc/eventstore/certs/node3/node3.key
 | 
			
		||||
      - EVENTSTORE_TRUSTED_ROOT_CERTIFICATES_PATH=/etc/eventstore/certs/ca
 | 
			
		||||
    expose:
 | 
			
		||||
      - "1113"
 | 
			
		||||
      - "1112"
 | 
			
		||||
      - "2113"
 | 
			
		||||
    networks:
 | 
			
		||||
      app_net:
 | 
			
		||||
        aliases:
 | 
			
		||||
          - cluster.tests.node-eventstore-client.local
 | 
			
		||||
          - node3.tests.node-eventstore-client.local
 | 
			
		||||
        ipv4_address: 192.168.33.12
 | 
			
		||||
    volumes:
 | 
			
		||||
      - eventstore3-data:/var/lib/eventstore-data
 | 
			
		||||
      - ./certs:/etc/eventstore/certs:ro
 | 
			
		||||
 | 
			
		||||
  nodejs:
 | 
			
		||||
    image: node:14
 | 
			
		||||
    working_dir: /var/build
 | 
			
		||||
    volumes:
 | 
			
		||||
      - ./:/var/code:ro
 | 
			
		||||
      - ./build-and-test.sh:/var/build/build-and-test.sh:ro
 | 
			
		||||
      - ./certs:/var/certs:ro
 | 
			
		||||
    environment:
 | 
			
		||||
      - NODE_EXTRA_CA_CERTS=/var/certs/ca/ca.crt
 | 
			
		||||
    command: bash -c "tail -f /dev/null"
 | 
			
		||||
    networks:
 | 
			
		||||
      app_net:
 | 
			
		||||
        ipv4_address: 192.168.33.5
 | 
			
		||||
 | 
			
		||||
volumes:
 | 
			
		||||
  eventstore1-data:
 | 
			
		||||
  eventstore2-data:
 | 
			
		||||
  eventstore3-data:
 | 
			
		||||
 | 
			
		||||
networks:
 | 
			
		||||
  app_net:
 | 
			
		||||
    ipam:
 | 
			
		||||
      driver: default
 | 
			
		||||
      config:
 | 
			
		||||
        - subnet: "192.168.33.0/24"
 | 
			
		||||
							
								
								
									
										54
									
								
								docker-compose-single.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								docker-compose-single.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
			
		||||
version: '3.4'
 | 
			
		||||
 | 
			
		||||
services:
 | 
			
		||||
  eventstore:
 | 
			
		||||
    image: eventstore/eventstore:22.10.0-buster-slim
 | 
			
		||||
    environment:
 | 
			
		||||
      - EVENTSTORE_CLUSTER_SIZE=1
 | 
			
		||||
      - EVENTSTORE_RUN_PROJECTIONS=All
 | 
			
		||||
      - EVENTSTORE_START_STANDARD_PROJECTIONS=True
 | 
			
		||||
      - EVENTSTORE_ENABLE_EXTERNAL_TCP=true
 | 
			
		||||
      - EVENTSTORE_EXT_TCP_PORT=1113
 | 
			
		||||
      - EVENTSTORE_HTTP_PORT=2113
 | 
			
		||||
      - EVENTSTORE_INT_IP=192.168.33.10
 | 
			
		||||
      - EVENTSTORE_EXT_IP=192.168.33.10
 | 
			
		||||
      - EVENTSTORE_CERTIFICATE_FILE=/etc/eventstore/certs/node1/node1.crt
 | 
			
		||||
      - EVENTSTORE_CERTIFICATE_PRIVATE_KEY_FILE=/etc/eventstore/certs/node1/node1.key
 | 
			
		||||
      - EVENTSTORE_TRUSTED_ROOT_CERTIFICATES_PATH=/etc/eventstore/certs/ca
 | 
			
		||||
    ports:
 | 
			
		||||
      - "1113:1113"
 | 
			
		||||
      - "2113:2113"
 | 
			
		||||
    tmpfs:
 | 
			
		||||
      - /var/log/eventstore
 | 
			
		||||
    volumes:
 | 
			
		||||
      - eventstore-data:/var/lib/eventstore
 | 
			
		||||
      - ./certs:/etc/eventstore/certs:ro
 | 
			
		||||
    networks:
 | 
			
		||||
      app_net:
 | 
			
		||||
        aliases:
 | 
			
		||||
          - node1.tests.node-eventstore-client.local
 | 
			
		||||
        ipv4_address: 192.168.33.10
 | 
			
		||||
 | 
			
		||||
  nodejs:
 | 
			
		||||
    image: node:14
 | 
			
		||||
    working_dir: /var/build
 | 
			
		||||
    volumes:
 | 
			
		||||
      - ./:/var/code:ro
 | 
			
		||||
      - ./build-and-test.sh:/var/build/build-and-test.sh:ro
 | 
			
		||||
      - ./certs:/var/certs:ro
 | 
			
		||||
    environment:
 | 
			
		||||
      - NODE_EXTRA_CA_CERTS=/var/certs/ca/ca.crt
 | 
			
		||||
    command: bash -c "tail -f /dev/null"
 | 
			
		||||
    networks:
 | 
			
		||||
      app_net:
 | 
			
		||||
        ipv4_address: 192.168.33.5
 | 
			
		||||
 | 
			
		||||
volumes:
 | 
			
		||||
  eventstore-data:
 | 
			
		||||
 | 
			
		||||
networks:
 | 
			
		||||
  app_net:
 | 
			
		||||
    ipam:
 | 
			
		||||
      driver: default
 | 
			
		||||
      config:
 | 
			
		||||
        - subnet: "192.168.33.0/24"
 | 
			
		||||
							
								
								
									
										207
									
								
								index.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										207
									
								
								index.d.ts
									
									
									
									
										vendored
									
									
								
							@@ -1,14 +1,18 @@
 | 
			
		||||
/// <reference types="node" />
 | 
			
		||||
/// <reference types="Long" />
 | 
			
		||||
 | 
			
		||||
import { EventEmitter } from 'events';
 | 
			
		||||
import { StrictEventEmitter } from 'strict-event-emitter-types';
 | 
			
		||||
 | 
			
		||||
// Expose classes
 | 
			
		||||
export class Position {
 | 
			
		||||
    constructor(commitPosition: number|Long, preparePosition: number|Long);
 | 
			
		||||
    readonly commitPosition: Long;
 | 
			
		||||
    readonly preparePosition: Long;
 | 
			
		||||
    static readonly start: number;
 | 
			
		||||
    static readonly end: number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Expose classes
 | 
			
		||||
 | 
			
		||||
export class UserCredentials {
 | 
			
		||||
    constructor(username: string, password: string);
 | 
			
		||||
    readonly username: string;
 | 
			
		||||
@@ -16,7 +20,7 @@ export class UserCredentials {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class PersistentSubscriptionSettings {
 | 
			
		||||
    constructor(resolveLinkTos: boolean, startFrom: number, extraStatistics: boolean, messageTimeout: number,
 | 
			
		||||
    constructor(resolveLinkTos: boolean, startFrom: Long|number, extraStatistics: boolean, messageTimeout: number,
 | 
			
		||||
                maxRetryCount: number, liveBufferSize: number, readBatchSize: number, historyBufferSize: number,
 | 
			
		||||
                checkPointAfter: number, minCheckPointCount: number, maxCheckPointCount: number,
 | 
			
		||||
                maxSubscriberCount: number, namedConsumerStrategy: string)
 | 
			
		||||
@@ -35,13 +39,65 @@ export class GossipSeed {
 | 
			
		||||
    readonly hostHeader: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface ProjectionDetails {
 | 
			
		||||
    readonly coreProcessingTime: number,
 | 
			
		||||
    readonly version: number,
 | 
			
		||||
    readonly epoch: number,
 | 
			
		||||
    readonly effectiveName: string,
 | 
			
		||||
    readonly writesInProgress: number,
 | 
			
		||||
    readonly readsInProgress: number,
 | 
			
		||||
    readonly partitionsCached: number,
 | 
			
		||||
    readonly status: string,
 | 
			
		||||
    readonly stateReason: string,
 | 
			
		||||
    readonly name: string,
 | 
			
		||||
    readonly mode: string,
 | 
			
		||||
    readonly position: string,
 | 
			
		||||
    readonly progress: number,
 | 
			
		||||
    readonly lastCheckpoint: string,
 | 
			
		||||
    readonly eventsProcessedAfterRestart: number,
 | 
			
		||||
    readonly statusUrl: string,
 | 
			
		||||
    readonly stateUrl: string,
 | 
			
		||||
    readonly resultUrl: string,
 | 
			
		||||
    readonly queryUrl: string,
 | 
			
		||||
    readonly enableCommandUrl: string,
 | 
			
		||||
    readonly disableCommandUrl: string,
 | 
			
		||||
    readonly checkpointStatus: string,
 | 
			
		||||
    readonly bufferedEvents: number,
 | 
			
		||||
    readonly writePendingEventsBeforeCheckpoint: number,
 | 
			
		||||
    readonly writePendingEventsAfterCheckpoint: number
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class ProjectionsManager {
 | 
			
		||||
    constructor(log: Logger, httpEndPoint: string, operationTimeout: number);
 | 
			
		||||
    enable(name: string, userCredentials: UserCredentials): Promise<void>;
 | 
			
		||||
    disable(name: string, userCredentials: UserCredentials): Promise<void>;
 | 
			
		||||
    abort(name: string, userCredentials: UserCredentials): Promise<void>;
 | 
			
		||||
    reset(name: string, userCredentials: UserCredentials): Promise<void>;
 | 
			
		||||
    createOneTime(query: string, userCredentials: UserCredentials): Promise<void>;
 | 
			
		||||
    createTransient(name: string, query: string, userCredentials: UserCredentials): Promise<void>;
 | 
			
		||||
    createContinuous(name: string, query: string, trackEmittedStreams: boolean, userCredentials: UserCredentials): Promise<void>;
 | 
			
		||||
    listAll(userCredentials: UserCredentials): Promise<ProjectionDetails[]>;
 | 
			
		||||
    listOneTime(userCredentials: UserCredentials): Promise<ProjectionDetails[]>;
 | 
			
		||||
    listContinuous(userCredentials: UserCredentials): Promise<ProjectionDetails[]>;
 | 
			
		||||
    getStatus(name: string, userCredentials: UserCredentials): Promise<string>;
 | 
			
		||||
    getState(name: string, userCredentials: UserCredentials): Promise<string>;
 | 
			
		||||
    getPartitionState(name: string, partitionId: string, userCredentials: UserCredentials): Promise<string>;
 | 
			
		||||
    getResult(name: string, userCredentials: UserCredentials): Promise<string>;
 | 
			
		||||
    getPartitionResult(name: string, partitionId: string, userCredentials: UserCredentials): Promise<string>;
 | 
			
		||||
    getStatistics(name: string, userCredentials: UserCredentials): Promise<string>;
 | 
			
		||||
    getQuery(name: string, userCredentials: UserCredentials): Promise<string>;
 | 
			
		||||
    getState(name: string, userCredentials: UserCredentials): Promise<string>;
 | 
			
		||||
    updateQuery(name: string, query: string, userCredentials: UserCredentials): Promise<void>;
 | 
			
		||||
    delete(name: string, deleteEmittedStreams: boolean, deleteStateStream: boolean, deleteCheckpointStream: boolean, userCredentials: UserCredentials): Promise<void>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Expose errors
 | 
			
		||||
export class WrongExpectedVersionError {
 | 
			
		||||
    readonly name: string;
 | 
			
		||||
    readonly action: string;
 | 
			
		||||
    readonly message: string;
 | 
			
		||||
    readonly stream?: string;
 | 
			
		||||
    readonly expectedVersion?: number;
 | 
			
		||||
    readonly expectedVersion?: Long;
 | 
			
		||||
    readonly transactionId?: Long;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -59,12 +115,17 @@ export class AccessDeniedError {
 | 
			
		||||
    readonly transactionId?: Long;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Expose enums/constants
 | 
			
		||||
export class ProjectionCommandFailedError {
 | 
			
		||||
    readonly httpStatusCode: number;
 | 
			
		||||
    readonly message: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Expose enums/constants
 | 
			
		||||
export namespace expectedVersion {
 | 
			
		||||
    const any: number;
 | 
			
		||||
    const noStream: number;
 | 
			
		||||
    const emptyStream: number;
 | 
			
		||||
    const streamExists: number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export namespace positions {
 | 
			
		||||
@@ -72,12 +133,17 @@ export namespace positions {
 | 
			
		||||
    const end: Position;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export namespace streamPosition {
 | 
			
		||||
    const start: number;
 | 
			
		||||
    const end: number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//TODO
 | 
			
		||||
// systemMetadata
 | 
			
		||||
// eventReadStatus
 | 
			
		||||
// sliceReadStatus
 | 
			
		||||
 | 
			
		||||
// Expose loggers
 | 
			
		||||
 | 
			
		||||
export interface Logger {
 | 
			
		||||
    debug(fmt: string, ...args: any[]): void;
 | 
			
		||||
    info(fmt: string, ...args: any[]): void;
 | 
			
		||||
@@ -98,18 +164,18 @@ export class FileLogger implements Logger {
 | 
			
		||||
    error(fmt: string, ...args: any[]): void;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
// Expose results
 | 
			
		||||
export interface WriteResult {
 | 
			
		||||
    readonly nextExpectedVersion: number;
 | 
			
		||||
    readonly nextExpectedVersion: Long;
 | 
			
		||||
    readonly logPosition: Position;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface RecordedEvent {
 | 
			
		||||
    readonly eventStreamId: string;
 | 
			
		||||
    readonly eventId: string;
 | 
			
		||||
    readonly eventNumber: number;
 | 
			
		||||
    readonly eventNumber: Long;
 | 
			
		||||
    readonly eventType: string;
 | 
			
		||||
    readonly created: Date;
 | 
			
		||||
    readonly createdEpoch: number;
 | 
			
		||||
    readonly data?: Buffer;
 | 
			
		||||
    readonly metadata?: Buffer;
 | 
			
		||||
@@ -123,17 +189,17 @@ export interface ResolvedEvent {
 | 
			
		||||
    readonly isResolved: boolean;
 | 
			
		||||
    readonly originalPosition?: Position;
 | 
			
		||||
    readonly originalStreamId: string;
 | 
			
		||||
    readonly originalEventNumber: number;
 | 
			
		||||
    readonly originalEventNumber: Long;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface StreamEventsSlice {
 | 
			
		||||
    readonly status: string;        // TODO: enum
 | 
			
		||||
    readonly stream: string;
 | 
			
		||||
    readonly fromEventNumber: number;
 | 
			
		||||
    readonly fromEventNumber: Long;
 | 
			
		||||
    readonly readDirection: string; // TODO: enum
 | 
			
		||||
    readonly events: ResolvedEvent[];
 | 
			
		||||
    readonly nextEventNumber: number;
 | 
			
		||||
    readonly lastEventNumber: number;
 | 
			
		||||
    readonly nextEventNumber: Long;
 | 
			
		||||
    readonly lastEventNumber: Long;
 | 
			
		||||
    readonly isEndOfStream: boolean;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -159,7 +225,7 @@ export interface EventStoreTransaction {
 | 
			
		||||
export interface EventReadResult {
 | 
			
		||||
    readonly status: string;
 | 
			
		||||
    readonly stream: string;
 | 
			
		||||
    readonly eventNumber: number;
 | 
			
		||||
    readonly eventNumber: Long;
 | 
			
		||||
    readonly event: ResolvedEvent | null;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -167,7 +233,7 @@ export interface EventStoreSubscription {
 | 
			
		||||
    readonly isSubscribedToAll: boolean;
 | 
			
		||||
    readonly streamId: string;
 | 
			
		||||
    readonly lastCommitPosition: Position;
 | 
			
		||||
    readonly lastEventNumber: number;
 | 
			
		||||
    readonly lastEventNumber: Long;
 | 
			
		||||
 | 
			
		||||
    close(): void;
 | 
			
		||||
    unsubscribe(): void;
 | 
			
		||||
@@ -194,7 +260,7 @@ export interface EventStorePersistentSubscription {
 | 
			
		||||
export interface RawStreamMetadataResult {
 | 
			
		||||
    readonly stream: string;
 | 
			
		||||
    readonly isStreamDeleted: boolean;
 | 
			
		||||
    readonly metastreamVersion: number;
 | 
			
		||||
    readonly metastreamVersion: Long;
 | 
			
		||||
    readonly streamMetadata: any;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -229,12 +295,12 @@ export interface TcpEndPoint {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface HeartbeatInfo {
 | 
			
		||||
    connectionId: string;
 | 
			
		||||
    remoteEndPoint: TcpEndPoint;
 | 
			
		||||
    requestSentAt: number;
 | 
			
		||||
    requestPkgNumber: number;
 | 
			
		||||
    responseReceivedAt: number;
 | 
			
		||||
    responsePkgNumber: number;
 | 
			
		||||
    readonly connectionId: string;
 | 
			
		||||
    readonly remoteEndPoint: TcpEndPoint;
 | 
			
		||||
    readonly requestSentAt: number;
 | 
			
		||||
    readonly requestPkgNumber: number;
 | 
			
		||||
    readonly responseReceivedAt: number;
 | 
			
		||||
    readonly responsePkgNumber: number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface EventData {
 | 
			
		||||
@@ -245,40 +311,47 @@ export interface EventData {
 | 
			
		||||
    readonly metadata: Buffer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface EventStoreNodeConnection {
 | 
			
		||||
interface EventStoreNodeConnectionEvents {
 | 
			
		||||
    connected: TcpEndPoint;
 | 
			
		||||
    disconnected: TcpEndPoint;
 | 
			
		||||
    reconnecting: void;
 | 
			
		||||
    closed:string;
 | 
			
		||||
    error: Error;
 | 
			
		||||
    heartbeatInfo: HeartbeatInfo;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type EventStoreNodeConnectionEventEmitter = StrictEventEmitter<EventEmitter, EventStoreNodeConnectionEvents>;
 | 
			
		||||
 | 
			
		||||
export class EventStoreNodeConnection extends (EventEmitter as { new(): EventStoreNodeConnectionEventEmitter }) {
 | 
			
		||||
    connect(): Promise<void>;
 | 
			
		||||
    close(): void;
 | 
			
		||||
    // write actions
 | 
			
		||||
    deleteStream(stream: string, expectedVersion: number, hardDelete?: boolean, userCredentials?: UserCredentials): Promise<DeleteResult>;
 | 
			
		||||
    appendToStream(stream: string, expectedVersion: number, eventOrEvents: EventData | EventData[], userCredentials?: UserCredentials): Promise<WriteResult>;
 | 
			
		||||
    startTransaction(stream: string, expectedVersion: number, userCredentials?: UserCredentials): Promise<EventStoreTransaction>;
 | 
			
		||||
    deleteStream(stream: string, expectedVersion: Long|number, hardDelete?: boolean, userCredentials?: UserCredentials): Promise<DeleteResult>;
 | 
			
		||||
    appendToStream(stream: string, expectedVersion: Long|number, eventOrEvents: EventData | EventData[], userCredentials?: UserCredentials): Promise<WriteResult>;
 | 
			
		||||
    startTransaction(stream: string, expectedVersion: Long|number, userCredentials?: UserCredentials): Promise<EventStoreTransaction>;
 | 
			
		||||
    continueTransaction(transactionId: number, userCredentials?: UserCredentials): EventStoreTransaction;
 | 
			
		||||
    // read actions
 | 
			
		||||
    readEvent(stream: string, eventNumber: number, resolveLinkTos?: boolean, userCredentials?: UserCredentials): Promise<EventReadResult>;
 | 
			
		||||
    readStreamEventsForward(stream: string, start: number, count: number, resolveLinkTos?: boolean, userCredentials?: UserCredentials): Promise<StreamEventsSlice>;
 | 
			
		||||
    readStreamEventsBackward(stream: string, start: number, count: number, resolveLinkTos?: boolean, userCredentials?: UserCredentials): Promise<StreamEventsSlice>;
 | 
			
		||||
    readEvent(stream: string, eventNumber: Long|number, resolveLinkTos?: boolean, userCredentials?: UserCredentials): Promise<EventReadResult>;
 | 
			
		||||
    readStreamEventsForward(stream: string, start: Long|number, count: number, resolveLinkTos?: boolean, userCredentials?: UserCredentials): Promise<StreamEventsSlice>;
 | 
			
		||||
    readStreamEventsBackward(stream: string, start: Long|number, count: number, resolveLinkTos?: boolean, userCredentials?: UserCredentials): Promise<StreamEventsSlice>;
 | 
			
		||||
    readAllEventsForward(position: Position, maxCount: number, resolveLinkTos?: boolean, userCredentials?: UserCredentials): Promise<AllEventsSlice>;
 | 
			
		||||
    readAllEventsBackward(position: Position, maxCount: number, resolveLinkTos?: boolean, userCredentials?: UserCredentials): Promise<AllEventsSlice>;
 | 
			
		||||
    // subscription actions
 | 
			
		||||
    subscribeToStream(stream: string, resolveLinkTos: boolean, eventAppeared: EventAppearedCallback<EventStoreSubscription>, subscriptionDropped?: SubscriptionDroppedCallback<EventStoreSubscription>, userCredentials?: UserCredentials): Promise<EventStoreSubscription>;
 | 
			
		||||
    subscribeToStreamFrom(stream: string, lastCheckpoint: number | null, resolveLinkTos: boolean, eventAppeared: EventAppearedCallback<EventStoreCatchUpSubscription>, liveProcessingStarted?: LiveProcessingStartedCallback, subscriptionDropped?: SubscriptionDroppedCallback<EventStoreCatchUpSubscription>, userCredentials?: UserCredentials, readBatchSize?: number): EventStoreCatchUpSubscription;
 | 
			
		||||
    subscribeToStreamFrom(stream: string, lastCheckpoint: Long|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>;
 | 
			
		||||
    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
 | 
			
		||||
    createPersistentSubscription(stream: string, groupName: string, settings: PersistentSubscriptionSettings, userCredentials?: PersistentSubscriptionSettings): Promise<PersistentSubscriptionCreateResult>;
 | 
			
		||||
    updatePersistentSubscription(stream: string, groupName: string, settings: PersistentSubscriptionSettings, userCredentials?: PersistentSubscriptionSettings): Promise<PersistentSubscriptionUpdateResult>;
 | 
			
		||||
    deletePersistentSubscription(stream: string, groupName: string, userCredentials?: PersistentSubscriptionSettings): Promise<PersistentSubscriptionDeleteResult>
 | 
			
		||||
    createPersistentSubscription(stream: string, groupName: string, settings: PersistentSubscriptionSettings, userCredentials?: UserCredentials): Promise<PersistentSubscriptionCreateResult>;
 | 
			
		||||
    updatePersistentSubscription(stream: string, groupName: string, settings: PersistentSubscriptionSettings, userCredentials?: UserCredentials): Promise<PersistentSubscriptionUpdateResult>;
 | 
			
		||||
    deletePersistentSubscription(stream: string, groupName: string, userCredentials?: UserCredentials): Promise<PersistentSubscriptionDeleteResult>
 | 
			
		||||
    connectToPersistentSubscription(stream: string, groupName: string, eventAppeared: EventAppearedCallback<EventStorePersistentSubscription>, subscriptionDropped?: SubscriptionDroppedCallback<EventStorePersistentSubscription>, userCredentials?: UserCredentials, bufferSize?: number, autoAck?: boolean): Promise<EventStorePersistentSubscription>;
 | 
			
		||||
    // metadata actions
 | 
			
		||||
    setStreamMetadataRaw(stream: string, expectedMetastreamVersion: number, metadata: any, userCredentials?: UserCredentials): Promise<WriteResult>;
 | 
			
		||||
    setStreamMetadataRaw(stream: string, expectedMetastreamVersion: Long|number, metadata: any, userCredentials?: UserCredentials): Promise<WriteResult>;
 | 
			
		||||
    getStreamMetadataRaw(stream: string, userCredentials?: UserCredentials): Promise<RawStreamMetadataResult>;
 | 
			
		||||
 | 
			
		||||
    on(event: "connected" | "disconnected" | "reconnecting" | "closed" | "error" | "heartbeatInfo", listener: (arg: Error | string | TcpEndPoint | HeartbeatInfo) => void): this;
 | 
			
		||||
    once(event: "connected" | "disconnected" | "reconnecting" | "closed" | "error" | "heartbeatInfo", listener: (arg: Error | string | TcpEndPoint | HeartbeatInfo) => void): this;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Expose helper functions
 | 
			
		||||
 | 
			
		||||
export interface ConnectionSettings {
 | 
			
		||||
    log?: Logger,
 | 
			
		||||
    verboseLogging?: boolean,
 | 
			
		||||
@@ -307,62 +380,12 @@ export interface ConnectionSettings {
 | 
			
		||||
    // Cluster Settings
 | 
			
		||||
    clusterDns?: string,
 | 
			
		||||
    maxDiscoverAttempts?: number,
 | 
			
		||||
    discoverDelay?: number,
 | 
			
		||||
    externalGossipPort?: number,
 | 
			
		||||
    gossipTimeout?: number
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Expose Helper functions
 | 
			
		||||
export function createConnection(settings: ConnectionSettings, endPointOrGossipSeed: string | TcpEndPoint | GossipSeed[], connectionName?: string): EventStoreNodeConnection;
 | 
			
		||||
export function createJsonEventData(eventId: string, event: any, metadata?: any, type?: string): EventData;
 | 
			
		||||
export function createEventData(eventId: string, type: string, isJson: boolean, data: Buffer, metadata?: Buffer): EventData;
 | 
			
		||||
 | 
			
		||||
// Projections
 | 
			
		||||
export interface ProjectionDetails {
 | 
			
		||||
    coreProcessingTime: number,
 | 
			
		||||
    version: number,
 | 
			
		||||
    epoch: number,
 | 
			
		||||
    effectiveName: string,
 | 
			
		||||
    writesInProgress: number,
 | 
			
		||||
    readsInProgress: number,
 | 
			
		||||
    partitionsCached: number,
 | 
			
		||||
    status: string,
 | 
			
		||||
    stateReason: string,
 | 
			
		||||
    name: string,
 | 
			
		||||
    mode: string,
 | 
			
		||||
    position: string,
 | 
			
		||||
    progress: number,
 | 
			
		||||
    lastCheckpoint: string,
 | 
			
		||||
    eventsProcessedAfterRestart: number,
 | 
			
		||||
    statusUrl: string,
 | 
			
		||||
    stateUrl: string,
 | 
			
		||||
    resultUrl: string,
 | 
			
		||||
    queryUrl: string,
 | 
			
		||||
    enableCommandUrl: string,
 | 
			
		||||
    disableCommandUrl: string,
 | 
			
		||||
    checkpointStatus: string,
 | 
			
		||||
    bufferedEvents: number,
 | 
			
		||||
    writePendingEventsBeforeCheckpoint: number,
 | 
			
		||||
    writePendingEventsAfterCheckpoint: number
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class ProjectionsManager {
 | 
			
		||||
    constructor(log: Logger, httpEndPoint: string, operationTimeout: number);
 | 
			
		||||
    enable(name: string, userCredentials: UserCredentials): Promise<void>;
 | 
			
		||||
    disable(name: string, userCredentials: UserCredentials): Promise<void>;
 | 
			
		||||
    abort(name: string, userCredentials: UserCredentials): Promise<void>;
 | 
			
		||||
    createOneTime(query: string, userCredentials: UserCredentials): Promise<void>;
 | 
			
		||||
    createTransient(name: string, query: string, userCredentials: UserCredentials): Promise<void>;
 | 
			
		||||
    createContinuous(name: string, query: string, trackEmittedStreams: boolean, userCredentials: UserCredentials): Promise<void>;
 | 
			
		||||
    listAll(userCredentials: UserCredentials): Promise<ProjectionDetails[]>;
 | 
			
		||||
    listOneTime(userCredentials: UserCredentials): Promise<ProjectionDetails[]>;
 | 
			
		||||
    listContinuous(userCredentials: UserCredentials): Promise<ProjectionDetails[]>;
 | 
			
		||||
    getStatus(name: string, userCredentials: UserCredentials): Promise<string>;
 | 
			
		||||
    getState(name: string, userCredentials: UserCredentials): Promise<string>;
 | 
			
		||||
    getPartitionState(name: string, partitionId: string, userCredentials: UserCredentials): Promise<string>;
 | 
			
		||||
    getResult(name: string, userCredentials: UserCredentials): Promise<string>;
 | 
			
		||||
    getPartitionResult(name: string, partitionId: string, userCredentials: UserCredentials): Promise<string>;
 | 
			
		||||
    getStatistics(name: string, userCredentials: UserCredentials): Promise<string>;
 | 
			
		||||
    getQuery(name: string, userCredentials: UserCredentials): Promise<string>;
 | 
			
		||||
    getState(name: string, userCredentials: UserCredentials): Promise<string>;
 | 
			
		||||
    updateQuery(name: string, query: string, userCredentials: UserCredentials): Promise<void>;
 | 
			
		||||
    deleteQuery(name: string, deleteEmittedStreams: boolean, userCredentials: UserCredentials): Promise<void>;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										6891
									
								
								package-lock.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										6891
									
								
								package-lock.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										41
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										41
									
								
								package.json
									
									
									
									
									
								
							@@ -1,20 +1,34 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "node-eventstore-client",
 | 
			
		||||
  "version": "0.1.9",
 | 
			
		||||
  "version": "22.10.0",
 | 
			
		||||
  "description": "A port of the EventStore .Net ClientAPI to Node.js",
 | 
			
		||||
  "main": "index.js",
 | 
			
		||||
  "types": "index.d.ts",
 | 
			
		||||
  "engines": {
 | 
			
		||||
    "node": ">=4.0"
 | 
			
		||||
    "node": ">=14",
 | 
			
		||||
    "npm": ">=6"
 | 
			
		||||
  },
 | 
			
		||||
  "engineStrict": true,
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "clean": "rm lib/dist.js",
 | 
			
		||||
    "clean": "rm -f lib/dist.js",
 | 
			
		||||
    "prebuild": "npm run clean",
 | 
			
		||||
    "build": "webpack",
 | 
			
		||||
    "pretest": "npm run build",
 | 
			
		||||
    "test": "nodeunit",
 | 
			
		||||
    "test-debug": "TESTS_VERBOSE_LOGGING=1 nodeunit",
 | 
			
		||||
    "prepublish": "npm run build && npm run gendocs",
 | 
			
		||||
    "test:jest:watch": "jest --watch --coverage",
 | 
			
		||||
    "test:single": "npm run compose:single:start && npm run compose:wait && npm run compose:single:test ; npm run compose:single:stop",
 | 
			
		||||
    "test:gossip": "npm run compose:cluster:start && npm run compose:wait && npm run compose:gossip:test ; npm run compose:cluster:stop",
 | 
			
		||||
    "test:cluster": "npm run compose:cluster:start && npm run compose:wait && npm run compose:cluster:test ; npm run compose:cluster:stop",
 | 
			
		||||
    "compose:single:start": "docker-compose -f docker-compose-single.yaml up --build -d",
 | 
			
		||||
    "compose:cluster:start": "docker-compose -f docker-compose-cluster.yaml up --build -d",
 | 
			
		||||
    "compose:single:stop": "docker-compose -f docker-compose-single.yaml down -v --remove-orphans",
 | 
			
		||||
    "compose:cluster:stop": "docker-compose -f docker-compose-cluster.yaml down -v --remove-orphans",
 | 
			
		||||
    "compose:wait": "while [ \"$(curl -s -o /dev/null -w ''%{http_code}'' -k https://localhost:2113/ping)\" != \"200\" ]; do sleep 5; done",
 | 
			
		||||
    "compose:single:test": "docker-compose -f docker-compose-single.yaml exec nodejs bash -c \"EVENTSTORE_CONNECTION_TYPE=tcp EVENTSTORE_HOST=192.168.33.10 ./build-and-test.sh\"",
 | 
			
		||||
    "compose:gossip:test": "docker-compose -f docker-compose-cluster.yaml exec nodejs bash -c \"EVENTSTORE_CONNECTION_TYPE=gossip EVENTSTORE_HOST=192.168.33.10 EVENTSTORE_HOST_1=192.168.33.10 EVENTSTORE_HOST_2=192.168.33.11 EVENTSTORE_HOST_3=192.168.33.12 ./build-and-test.sh\"",
 | 
			
		||||
    "compose:cluster:test": "docker-compose -f docker-compose-cluster.yaml exec nodejs bash -c \"EVENTSTORE_CONNECTION_TYPE=dns EVENTSTORE_HOST=cluster.tests.node-eventstore-client.local ./build-and-test.sh\"",
 | 
			
		||||
    "prepublishOnly": "npm run build && npm run gendocs",
 | 
			
		||||
    "gendocs": "rm -rf docs && jsdoc src -r -d docs"
 | 
			
		||||
  },
 | 
			
		||||
  "files": [
 | 
			
		||||
@@ -45,15 +59,18 @@
 | 
			
		||||
  },
 | 
			
		||||
  "homepage": "https://github.com/nicdex/node-eventstore-client#readme",
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "@types/long": "^3.0.31",
 | 
			
		||||
    "@types/node": "^6.0.47",
 | 
			
		||||
    "long": "^3.2",
 | 
			
		||||
    "protobufjs": "^6.7.3",
 | 
			
		||||
    "uuid": "^3.0.1"
 | 
			
		||||
    "@types/node": ">=14",
 | 
			
		||||
    "long": "^5.2.0",
 | 
			
		||||
    "strict-event-emitter-types": "^1.2.0",
 | 
			
		||||
    "uuid": "^9.0.0"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "jsdoc": "^3.5.3",
 | 
			
		||||
    "nodeunit": "^0.11.1",
 | 
			
		||||
    "webpack": "^3.3.0"
 | 
			
		||||
    "jest": "^29.4.1",
 | 
			
		||||
    "jsdoc": "^4.0.0",
 | 
			
		||||
    "nodeunit": "^0.11.3",
 | 
			
		||||
    "protobufjs": "^7.2.0",
 | 
			
		||||
    "protobufjs-cli": "^1.1.0",
 | 
			
		||||
    "webpack": "^5.75.0",
 | 
			
		||||
    "webpack-cli": "^3.3.10"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										62
									
								
								samples/issue-60.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								samples/issue-60.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,62 @@
 | 
			
		||||
const client = require('../src/client'); // RWM: Import from npm installed package rather than from src
 | 
			
		||||
//const client = require("node-eventstore-client");
 | 
			
		||||
 | 
			
		||||
const resolveLinkTos = true;
 | 
			
		||||
 | 
			
		||||
function resumeEvent(event) {
 | 
			
		||||
  return [
 | 
			
		||||
    event.originalEvent.eventType,
 | 
			
		||||
    [event.originalEventNumber.toNumber(), event.originalStreamId].join('@'),
 | 
			
		||||
    event.originalPosition
 | 
			
		||||
  ].join(" ")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const eventAppeared = (subscription, event) => console.log("Event received", resumeEvent(event));
 | 
			
		||||
 | 
			
		||||
const subscriptionDropped = (subscription, reason, error) => console.log("Subscription dropped", reason, error);
 | 
			
		||||
 | 
			
		||||
const libeProcessingStarted = () => console.log("Live processing started.");
 | 
			
		||||
 | 
			
		||||
const credentials = new client.UserCredentials("admin", "changeit");
 | 
			
		||||
 | 
			
		||||
const settings = {
 | 
			
		||||
    maxReconnections: 10,
 | 
			
		||||
    reconnectionDelay: 1000, // RWM: slow down the reconnection attempts. 10 seconds to restore connection.
 | 
			
		||||
};
 | 
			
		||||
if (process.env.ENABLE_LOGGING) settings.log = console;
 | 
			
		||||
if (process.env.VERBOSE) settings.verboseLogging = true;
 | 
			
		||||
const endpoint = "tcp://localhost:1113";
 | 
			
		||||
const connection = client.createConnection(settings, endpoint);
 | 
			
		||||
 | 
			
		||||
connection.connect().catch(err => console.log("Connection failed", err));
 | 
			
		||||
 | 
			
		||||
connection.on('heartbeatInfo', heartbeatInfo =>
 | 
			
		||||
  console.log('Heartbeat latency', heartbeatInfo.responseReceivedAt - heartbeatInfo.requestSentAt, 'ms')
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
connection.once("connected", tcpEndPoint => {
 | 
			
		||||
  console.log(`Connected to eventstore at ${tcpEndPoint.host}:${tcpEndPoint.port}`);
 | 
			
		||||
  // RWM: subscribe Stream instead of All
 | 
			
		||||
  connection.subscribeToStreamFrom(
 | 
			
		||||
    "test", // RWM: Stream to subscribe to
 | 
			
		||||
    null,
 | 
			
		||||
    resolveLinkTos,
 | 
			
		||||
    eventAppeared,
 | 
			
		||||
    libeProcessingStarted,
 | 
			
		||||
    subscriptionDropped,
 | 
			
		||||
    credentials
 | 
			
		||||
  );
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
connection.on("error", error =>
 | 
			
		||||
  console.log(`Error occurred on connection: ${error}`)
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
connection.on("closed", reason =>
 | 
			
		||||
  console.log(`Connection closed, reason: ${reason}`)
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// RWM: Handle the reconnecting event, for better awareness of what's happening
 | 
			
		||||
connection.on("reconnecting", msg =>
 | 
			
		||||
  console.log(`Reconnecting, msg: ${JSON.stringify(msg, null, 4)}`)
 | 
			
		||||
)
 | 
			
		||||
							
								
								
									
										50
									
								
								samples/subscribe-all-from-events.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								samples/subscribe-all-from-events.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,50 @@
 | 
			
		||||
const client = require('../src/client');
 | 
			
		||||
//const client = require("node-eventstore-client");
 | 
			
		||||
 | 
			
		||||
const resolveLinkTos = true;
 | 
			
		||||
 | 
			
		||||
function resumeEvent(event) {
 | 
			
		||||
  return [
 | 
			
		||||
    event.originalEvent.eventType,
 | 
			
		||||
    [event.originalEventNumber.toNumber(), event.originalStreamId].join('@'),
 | 
			
		||||
    event.originalPosition
 | 
			
		||||
  ].join(" ")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const eventAppeared = (subscription, event) => console.log("Event received", resumeEvent(event));
 | 
			
		||||
 | 
			
		||||
const subscriptionDropped = (subscription, reason, error) => console.log("Subscription dropped", reason, error);
 | 
			
		||||
 | 
			
		||||
const libeProcessingStarted = () => console.log("Live processing started.");
 | 
			
		||||
 | 
			
		||||
const credentials = new client.UserCredentials("admin", "changeit");
 | 
			
		||||
 | 
			
		||||
const settings = {};
 | 
			
		||||
const endpoint = "tcp://localhost:1113";
 | 
			
		||||
const connection = client.createConnection(settings, endpoint);
 | 
			
		||||
 | 
			
		||||
connection.connect().catch(err => console.log("Connection failed", err));
 | 
			
		||||
 | 
			
		||||
connection.on('heartbeatInfo', heartbeatInfo =>
 | 
			
		||||
  console.log('Heartbeat latency', heartbeatInfo.responseReceivedAt - heartbeatInfo.requestSentAt, 'ms')
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
connection.once("connected", tcpEndPoint => {
 | 
			
		||||
  console.log(`Connected to eventstore at ${tcpEndPoint.host}:${tcpEndPoint.port}`);
 | 
			
		||||
  connection.subscribeToAllFrom(
 | 
			
		||||
    null,
 | 
			
		||||
    resolveLinkTos,
 | 
			
		||||
    eventAppeared,
 | 
			
		||||
    libeProcessingStarted,
 | 
			
		||||
    subscriptionDropped,
 | 
			
		||||
    credentials
 | 
			
		||||
  );
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
connection.on("error", error =>
 | 
			
		||||
  console.log(`Error occurred on connection: ${error}`)
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
connection.on("closed", reason =>
 | 
			
		||||
  console.log(`Connection closed, reason: ${reason}`)
 | 
			
		||||
)
 | 
			
		||||
@@ -4,15 +4,23 @@ var results = require('./results');
 | 
			
		||||
const expectedVersion = {
 | 
			
		||||
  any: -2,
 | 
			
		||||
  noStream: -1,
 | 
			
		||||
  emptyStream: -1
 | 
			
		||||
  emptyStream: -1,
 | 
			
		||||
  streamExists: -4
 | 
			
		||||
};
 | 
			
		||||
Object.freeze(expectedVersion);
 | 
			
		||||
 | 
			
		||||
const positions = {
 | 
			
		||||
  start: new results.Position(0, 0),
 | 
			
		||||
  end: new results.Position(-1, -1)
 | 
			
		||||
};
 | 
			
		||||
Object.freeze(positions);
 | 
			
		||||
 | 
			
		||||
const streamPosition = {
 | 
			
		||||
  start: 0,
 | 
			
		||||
  end: -1
 | 
			
		||||
};
 | 
			
		||||
Object.freeze(streamPosition);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Create an EventData object from JavaScript event/metadata that will be serialized as json
 | 
			
		||||
 * @public
 | 
			
		||||
@@ -25,8 +33,8 @@ Object.freeze(positions);
 | 
			
		||||
function createJsonEventData(eventId, event, metadata, type) {
 | 
			
		||||
  if (!event || typeof event !== 'object') throw new TypeError("data must be an object.");
 | 
			
		||||
 | 
			
		||||
  var eventBuf = new Buffer(JSON.stringify(event));
 | 
			
		||||
  var metaBuf = metadata ? new Buffer(JSON.stringify(metadata)) : null;
 | 
			
		||||
  var eventBuf = Buffer.from(JSON.stringify(event));
 | 
			
		||||
  var metaBuf = metadata ? Buffer.from(JSON.stringify(metadata)) : null;
 | 
			
		||||
  return new EventData(eventId, type || event.constructor.name, true, eventBuf, metaBuf);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -45,28 +53,31 @@ function createEventData(eventId, type, isJson, data, metadata) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Expose classes
 | 
			
		||||
module.exports.Position = results.Position;
 | 
			
		||||
module.exports.UserCredentials = require('./systemData/userCredentials');
 | 
			
		||||
module.exports.PersistentSubscriptionSettings = require('./persistentSubscriptionSettings');
 | 
			
		||||
module.exports.SystemConsumerStrategies = require('./systemConsumerStrategies');
 | 
			
		||||
module.exports.GossipSeed = require('./gossipSeed');
 | 
			
		||||
module.exports.EventStoreConnection = require('./eventStoreConnection');
 | 
			
		||||
module.exports.ProjectionsManager = require('./projections/projectionsManager');
 | 
			
		||||
exports.Position = results.Position;
 | 
			
		||||
exports.UserCredentials = require('./systemData/userCredentials');
 | 
			
		||||
exports.PersistentSubscriptionSettings = require('./persistentSubscriptionSettings');
 | 
			
		||||
exports.SystemConsumerStrategies = require('./systemConsumerStrategies');
 | 
			
		||||
exports.GossipSeed = require('./gossipSeed');
 | 
			
		||||
exports.EventStoreConnection = require('./eventStoreConnection');
 | 
			
		||||
exports.ProjectionsManager = require('./projections/projectionsManager');
 | 
			
		||||
// Expose errors
 | 
			
		||||
module.exports.WrongExpectedVersionError = require('./errors/wrongExpectedVersionError');
 | 
			
		||||
module.exports.StreamDeletedError = require('./errors/streamDeletedError');
 | 
			
		||||
module.exports.AccessDeniedError = require('./errors/accessDeniedError');
 | 
			
		||||
module.exports.ProjectionCommandFailedError = require('./errors/projectionCommandFailedError');
 | 
			
		||||
exports.WrongExpectedVersionError = require('./errors/wrongExpectedVersionError');
 | 
			
		||||
exports.StreamDeletedError = require('./errors/streamDeletedError');
 | 
			
		||||
exports.AccessDeniedError = require('./errors/accessDeniedError');
 | 
			
		||||
exports.ProjectionCommandFailedError = require('./errors/projectionCommandFailedError');
 | 
			
		||||
// Expose enums/constants
 | 
			
		||||
module.exports.expectedVersion = expectedVersion;
 | 
			
		||||
module.exports.positions = positions;
 | 
			
		||||
module.exports.systemMetadata = require('./common/systemMetadata');
 | 
			
		||||
module.exports.eventReadStatus = results.EventReadStatus;
 | 
			
		||||
module.exports.sliceReadStatus = require('./sliceReadStatus');
 | 
			
		||||
exports.expectedVersion = expectedVersion;
 | 
			
		||||
exports.positions = positions;
 | 
			
		||||
exports.streamPosition = streamPosition;
 | 
			
		||||
exports.systemMetadata = require('./common/systemMetadata');
 | 
			
		||||
exports.eventReadStatus = results.EventReadStatus;
 | 
			
		||||
exports.sliceReadStatus = require('./sliceReadStatus');
 | 
			
		||||
exports.persistentSubscriptionNakEventAction =
 | 
			
		||||
exports.PersistentSubscriptionNakEventAction = require('./persistentSubscriptionNakEventAction');
 | 
			
		||||
// Expose loggers
 | 
			
		||||
module.exports.NoopLogger = require('./common/log/noopLogger');
 | 
			
		||||
module.exports.FileLogger = require('./common/log/fileLogger');
 | 
			
		||||
exports.NoopLogger = require('./common/log/noopLogger');
 | 
			
		||||
exports.FileLogger = require('./common/log/fileLogger');
 | 
			
		||||
// Expose Helper functions
 | 
			
		||||
module.exports.createConnection = require('./eventStoreConnection').create;
 | 
			
		||||
module.exports.createJsonEventData = createJsonEventData;
 | 
			
		||||
module.exports.createEventData = createEventData;
 | 
			
		||||
exports.createConnection = require('./eventStoreConnection').create;
 | 
			
		||||
exports.createJsonEventData = createJsonEventData;
 | 
			
		||||
exports.createEventData = createEventData;
 | 
			
		||||
 
 | 
			
		||||
@@ -37,15 +37,14 @@ AppendToStreamOperation.prototype._createRequestDto = function() {
 | 
			
		||||
    eventStreamId: this._stream,
 | 
			
		||||
    expectedVersion: this._expectedVersion,
 | 
			
		||||
    events: dtos,
 | 
			
		||||
    requireMaster: this._requireMaster});
 | 
			
		||||
    requireLeader: this._requireMaster});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
AppendToStreamOperation.prototype._inspectResponse = function(response) {
 | 
			
		||||
  switch (response.result)
 | 
			
		||||
  {
 | 
			
		||||
    case ClientMessage.OperationResult.Success:
 | 
			
		||||
      if (this._wasCommitTimeout)
 | 
			
		||||
        this.log.debug("IDEMPOTENT WRITE SUCCEEDED FOR %s.", this);
 | 
			
		||||
      if (this._wasCommitTimeout) this.log.debug("IDEMPOTENT WRITE SUCCEEDED FOR %s.", this);
 | 
			
		||||
      this._succeed();
 | 
			
		||||
      return new InspectionResult(InspectionDecision.EndOperation, "Success");
 | 
			
		||||
    case ClientMessage.OperationResult.PrepareTimeout:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,4 @@
 | 
			
		||||
var util = require('util');
 | 
			
		||||
var uuid = require('uuid');
 | 
			
		||||
 | 
			
		||||
var TcpCommand = require('../systemData/tcpCommand');
 | 
			
		||||
var InspectionDecision = require('../systemData/inspectionDecision');
 | 
			
		||||
@@ -25,7 +24,7 @@ util.inherits(CommitTransactionOperation, OperationBase);
 | 
			
		||||
CommitTransactionOperation.prototype._createRequestDto = function() {
 | 
			
		||||
  return new ClientMessage.TransactionCommit({
 | 
			
		||||
    transactionId: this._transactionId,
 | 
			
		||||
    requireMaster: this._requireMaster
 | 
			
		||||
    requireLeader: this._requireMaster
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -67,4 +66,4 @@ CommitTransactionOperation.prototype.toString = function() {
 | 
			
		||||
  return util.format("TransactionId: %s", this._transactionId);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports = CommitTransactionOperation;
 | 
			
		||||
module.exports = CommitTransactionOperation;
 | 
			
		||||
 
 | 
			
		||||
@@ -124,4 +124,4 @@ ConnectToPersistentSubscriptionOperation.prototype.notifyEventsFailed = function
 | 
			
		||||
  this._enqueueSend(pkg);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports = ConnectToPersistentSubscriptionOperation;
 | 
			
		||||
module.exports = ConnectToPersistentSubscriptionOperation;
 | 
			
		||||
@@ -1,5 +1,4 @@
 | 
			
		||||
var util = require('util');
 | 
			
		||||
var uuid = require('uuid');
 | 
			
		||||
 | 
			
		||||
var ensure = require('../common/utils/ensure');
 | 
			
		||||
var OperationBase = require('../clientOperations/operationBase');
 | 
			
		||||
@@ -84,4 +83,4 @@ CreatePersistentSubscriptionOperation.prototype.toString = function() {
 | 
			
		||||
  return util.format("Stream: %s, Group Name: %s", this._stream, this._groupName);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports = CreatePersistentSubscriptionOperation;
 | 
			
		||||
module.exports = CreatePersistentSubscriptionOperation;
 | 
			
		||||
@@ -1,7 +1,5 @@
 | 
			
		||||
var util = require('util');
 | 
			
		||||
var uuid = require('uuid');
 | 
			
		||||
 | 
			
		||||
var ensure = require('../common/utils/ensure');
 | 
			
		||||
var OperationBase = require('../clientOperations/operationBase');
 | 
			
		||||
var TcpCommand = require('../systemData/tcpCommand');
 | 
			
		||||
var ClientMessage = require('../messages/clientMessage');
 | 
			
		||||
@@ -55,4 +53,4 @@ DeletePersistentSubscriptionOperation.prototype.toString = function() {
 | 
			
		||||
  return util.format("Stream: %s, Group Name: %s", this._stream, this._groupName);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports = DeletePersistentSubscriptionOperation;
 | 
			
		||||
module.exports = DeletePersistentSubscriptionOperation;
 | 
			
		||||
@@ -1,5 +1,4 @@
 | 
			
		||||
var util = require('util');
 | 
			
		||||
var uuid = require('uuid');
 | 
			
		||||
 | 
			
		||||
var TcpCommand = require('../systemData/tcpCommand');
 | 
			
		||||
var InspectionDecision = require('../systemData/inspectionDecision');
 | 
			
		||||
@@ -28,7 +27,7 @@ DeleteStreamOperation.prototype._createRequestDto = function() {
 | 
			
		||||
  return new ClientMessage.DeleteStream({
 | 
			
		||||
    eventStreamId: this._stream,
 | 
			
		||||
    expectedVersion: this._expectedVersion,
 | 
			
		||||
    requireMaster: this._requireMaster,
 | 
			
		||||
    requireLeader: this._requireMaster,
 | 
			
		||||
    hardDelete: this._hardDelete
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
@@ -70,4 +69,4 @@ DeleteStreamOperation.prototype.toString = function() {
 | 
			
		||||
  return util.format("Stream: %s, ExpectedVersion: %s.", this._stream, this._expectedVersion);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports = DeleteStreamOperation;
 | 
			
		||||
module.exports = DeleteStreamOperation;
 | 
			
		||||
 
 | 
			
		||||
@@ -42,10 +42,11 @@ OperationBase.prototype._succeed = function() {
 | 
			
		||||
  if (!this._completed) {
 | 
			
		||||
    this._completed = true;
 | 
			
		||||
 | 
			
		||||
    if (this._response)
 | 
			
		||||
    if (this._response) {
 | 
			
		||||
      this._cb(null, this._transformResponse(this._response));
 | 
			
		||||
    else
 | 
			
		||||
    } else {
 | 
			
		||||
      this._cb(new Error("No result."))
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -116,9 +117,9 @@ OperationBase.prototype._inspectNotHandled = function(pkg)
 | 
			
		||||
    case ClientMessage.NotHandled.NotHandledReason.TooBusy:
 | 
			
		||||
      return new InspectionResult(InspectionDecision.Retry, "NotHandled - TooBusy");
 | 
			
		||||
 | 
			
		||||
    case ClientMessage.NotHandled.NotHandledReason.NotMaster:
 | 
			
		||||
      var masterInfo = ClientMessage.NotHandled.MasterInfo.decode(message.additionalInfo);
 | 
			
		||||
      return new InspectionResult(InspectionDecision.Reconnect, "NotHandled - NotMaster",
 | 
			
		||||
    case ClientMessage.NotHandled.NotHandledReason.NotLeader:
 | 
			
		||||
      var masterInfo = ClientMessage.NotHandled.LeaderInfo.decode(message.additionalInfo);
 | 
			
		||||
      return new InspectionResult(InspectionDecision.Reconnect, "NotHandled - NotLeader",
 | 
			
		||||
          {host: masterInfo.externalTcpAddress, port: masterInfo.externalTcpPort},
 | 
			
		||||
          {host: masterInfo.externalSecureTcpAddress, port: masterInfo.externalSecureTcpPort});
 | 
			
		||||
 | 
			
		||||
@@ -130,8 +131,7 @@ OperationBase.prototype._inspectNotHandled = function(pkg)
 | 
			
		||||
 | 
			
		||||
OperationBase.prototype._inspectUnexpectedCommand = function(pkg, expectedCommand)
 | 
			
		||||
{
 | 
			
		||||
  if (pkg.command === expectedCommand)
 | 
			
		||||
    throw new Error("Command shouldn't be " + TcpCommand.getName(pkg.command));
 | 
			
		||||
  if (pkg.command === expectedCommand) throw new Error("Command shouldn't be " + TcpCommand.getName(pkg.command));
 | 
			
		||||
 | 
			
		||||
  this.log.error("Unexpected TcpCommand received.\n"
 | 
			
		||||
      + "Expected: %s, Actual: %s, Flags: %s, CorrelationId: %s\n"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,4 @@
 | 
			
		||||
var util = require('util');
 | 
			
		||||
var uuid = require('uuid');
 | 
			
		||||
 | 
			
		||||
var TcpCommand = require('../systemData/tcpCommand');
 | 
			
		||||
var ClientMessage = require('../messages/clientMessage');
 | 
			
		||||
@@ -30,7 +29,7 @@ ReadAllEventsBackwardOperation.prototype._createRequestDto = function() {
 | 
			
		||||
    preparePosition: this._position.preparePosition,
 | 
			
		||||
    maxCount: this._maxCount,
 | 
			
		||||
    resolveLinkTos: this._resolveLinkTos,
 | 
			
		||||
    requireMaster: this._requireMaster
 | 
			
		||||
    requireLeader: this._requireMaster
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,4 @@
 | 
			
		||||
var util = require('util');
 | 
			
		||||
var uuid = require('uuid');
 | 
			
		||||
 | 
			
		||||
var TcpCommand = require('../systemData/tcpCommand');
 | 
			
		||||
var ClientMessage = require('../messages/clientMessage');
 | 
			
		||||
@@ -30,7 +29,7 @@ ReadAllEventsForwardOperation.prototype._createRequestDto = function() {
 | 
			
		||||
      preparePosition: this._position.preparePosition,
 | 
			
		||||
      maxCount: this._maxCount,
 | 
			
		||||
      resolveLinkTos: this._resolveLinkTos,
 | 
			
		||||
      requireMaster: this._requireMaster
 | 
			
		||||
      requireLeader: this._requireMaster
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@ ReadEventOperation.prototype._createRequestDto = function() {
 | 
			
		||||
      eventStreamId: this._stream,
 | 
			
		||||
      eventNumber: this._eventNumber,
 | 
			
		||||
      resolveLinkTos: this._resolveLinkTos,
 | 
			
		||||
      requireMaster: this._requireMaster
 | 
			
		||||
      requireLeader: this._requireMaster
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -59,7 +59,6 @@ ReadEventOperation.prototype._transformResponse = function(response) {
 | 
			
		||||
  return new results.EventReadResult(convert(response.result), this._stream, this._eventNumber, response.event);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function convert(result)
 | 
			
		||||
{
 | 
			
		||||
  switch (result)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,4 @@
 | 
			
		||||
var util = require('util');
 | 
			
		||||
var uuid = require('uuid');
 | 
			
		||||
 | 
			
		||||
var TcpCommand = require('../systemData/tcpCommand');
 | 
			
		||||
var ClientMessage = require('../messages/clientMessage');
 | 
			
		||||
@@ -32,7 +31,7 @@ ReadStreamEventsBackwardOperation.prototype._createRequestDto = function() {
 | 
			
		||||
      fromEventNumber: this._fromEventNumber,
 | 
			
		||||
      maxCount: this._maxCount,
 | 
			
		||||
      resolveLinkTos: this._resolveLinkTos,
 | 
			
		||||
      requireMaster: this._requireMaster
 | 
			
		||||
      requireLeader: this._requireMaster
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,4 @@
 | 
			
		||||
var util = require('util');
 | 
			
		||||
var uuid = require('uuid');
 | 
			
		||||
 | 
			
		||||
var TcpCommand = require('../systemData/tcpCommand');
 | 
			
		||||
var ClientMessage = require('../messages/clientMessage');
 | 
			
		||||
@@ -32,7 +31,7 @@ ReadStreamEventsForwardOperation.prototype._createRequestDto = function() {
 | 
			
		||||
      fromEventNumber: this._fromEventNumber,
 | 
			
		||||
      maxCount: this._maxCount,
 | 
			
		||||
      resolveLinkTos: this._resolveLinkTos,
 | 
			
		||||
      requireMaster: this._requireMaster
 | 
			
		||||
      requireLeader: this._requireMaster
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,12 +1,10 @@
 | 
			
		||||
var util = require('util');
 | 
			
		||||
var uuid = require('uuid');
 | 
			
		||||
 | 
			
		||||
var TcpCommand = require('../systemData/tcpCommand');
 | 
			
		||||
var InspectionDecision = require('../systemData/inspectionDecision');
 | 
			
		||||
var InspectionResult = require('./../systemData/inspectionResult');
 | 
			
		||||
var ClientMessage = require('../messages/clientMessage');
 | 
			
		||||
var EventStoreTransaction = require('../eventStoreTransaction');
 | 
			
		||||
var results = require('../results');
 | 
			
		||||
var AccessDeniedError = require('../errors/accessDeniedError');
 | 
			
		||||
var WrongExpectedVersionError = require('../errors/wrongExpectedVersionError');
 | 
			
		||||
var StreamDeletedError = require('../errors/streamDeletedError');
 | 
			
		||||
@@ -27,7 +25,7 @@ StartTransactionOperation.prototype._createRequestDto = function() {
 | 
			
		||||
  return new ClientMessage.TransactionStart({
 | 
			
		||||
      eventStreamId: this._stream,
 | 
			
		||||
      expectedVersion: this._expectedVersion,
 | 
			
		||||
      requireMaster: this._requireMaster
 | 
			
		||||
      requireLeader: this._requireMaster
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,4 @@
 | 
			
		||||
var util = require('util');
 | 
			
		||||
var uuid = require('uuid');
 | 
			
		||||
 | 
			
		||||
var TcpCommand = require('../systemData/tcpCommand');
 | 
			
		||||
var TcpFlags = require('../systemData/tcpFlags');
 | 
			
		||||
@@ -46,8 +45,7 @@ SubscriptionOperation.prototype._enqueueSend = function(pkg) {
 | 
			
		||||
SubscriptionOperation.prototype.subscribe = function(correlationId, connection) {
 | 
			
		||||
  if (connection === null) throw new TypeError("connection is null.");
 | 
			
		||||
 | 
			
		||||
  if (this._subscription !== null || this._unsubscribed)
 | 
			
		||||
    return false;
 | 
			
		||||
  if (this._subscription !== null || this._unsubscribed) return false;
 | 
			
		||||
 | 
			
		||||
  this._correlationId = correlationId;
 | 
			
		||||
  connection.enqueueSend(this._createSubscriptionPackage());
 | 
			
		||||
@@ -76,9 +74,7 @@ SubscriptionOperation.prototype.inspectPackage = function(pkg) {
 | 
			
		||||
  try
 | 
			
		||||
  {
 | 
			
		||||
    var result = this._inspectPackage(pkg);
 | 
			
		||||
    if (result !== null) {
 | 
			
		||||
      return result;
 | 
			
		||||
    }
 | 
			
		||||
    if (result !== null) return result;
 | 
			
		||||
 | 
			
		||||
    switch (pkg.command)
 | 
			
		||||
    {
 | 
			
		||||
@@ -128,8 +124,9 @@ SubscriptionOperation.prototype.inspectPackage = function(pkg) {
 | 
			
		||||
 | 
			
		||||
      case TcpCommand.NotHandled:
 | 
			
		||||
      {
 | 
			
		||||
        if (this._subscription !== null)
 | 
			
		||||
        if (this._subscription !== null) {
 | 
			
		||||
          throw new Error("NotHandled command appeared while we already subscribed.");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        var message = ClientMessage.NotHandled.decode(pkg.data.toBuffer());
 | 
			
		||||
        switch (message.reason)
 | 
			
		||||
@@ -140,9 +137,9 @@ SubscriptionOperation.prototype.inspectPackage = function(pkg) {
 | 
			
		||||
          case ClientMessage.NotHandled.NotHandledReason.TooBusy:
 | 
			
		||||
            return new InspectionResult(InspectionDecision.Retry, "NotHandled - TooBusy");
 | 
			
		||||
 | 
			
		||||
          case ClientMessage.NotHandled.NotHandledReason.NotMaster:
 | 
			
		||||
            var masterInfo = ClientMessage.NotHandled.MasterInfo.decode(message.additionalInfo);
 | 
			
		||||
            return new InspectionResult(InspectionDecision.Reconnect, "NotHandled - NotMaster",
 | 
			
		||||
          case ClientMessage.NotHandled.NotHandledReason.NotLeader:
 | 
			
		||||
            var masterInfo = ClientMessage.NotHandled.LeaderInfo.decode(message.additionalInfo);
 | 
			
		||||
            return new InspectionResult(InspectionDecision.Reconnect, "NotHandled - NotLeader",
 | 
			
		||||
                {host: masterInfo.externalTcpAddress, port: masterInfo.externalTcpPort},
 | 
			
		||||
                {host: masterInfo.externalSecureTcpAddress, port: masterInfo.externalSecureTcpPort});
 | 
			
		||||
 | 
			
		||||
@@ -172,8 +169,7 @@ SubscriptionOperation.prototype.connectionClosed = function() {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
SubscriptionOperation.prototype.timeOutSubscription = function() {
 | 
			
		||||
  if (this._subscription !== null)
 | 
			
		||||
    return false;
 | 
			
		||||
  if (this._subscription !== null) return false;
 | 
			
		||||
  this.dropSubscription(SubscriptionDropReason.SubscribingError, null);
 | 
			
		||||
  return true;
 | 
			
		||||
};
 | 
			
		||||
@@ -182,9 +178,10 @@ SubscriptionOperation.prototype.dropSubscription = function(reason, err, connect
 | 
			
		||||
  if (!this._unsubscribed)
 | 
			
		||||
  {
 | 
			
		||||
    this._unsubscribed = true;
 | 
			
		||||
    if (this._verboseLogging)
 | 
			
		||||
    if (this._verboseLogging) {
 | 
			
		||||
      this._log.debug("Subscription %s to %s: closing subscription, reason: %s, exception: %s...",
 | 
			
		||||
          this._correlationId, this._streamId || "<all>", reason, err);
 | 
			
		||||
        this._correlationId, this._streamId || "<all>", reason, err);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (reason !== SubscriptionDropReason.UserInitiated && this._subscription === null)
 | 
			
		||||
    {
 | 
			
		||||
@@ -193,24 +190,31 @@ SubscriptionOperation.prototype.dropSubscription = function(reason, err, connect
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (reason === SubscriptionDropReason.UserInitiated && this._subscription !== null && connection !== null)
 | 
			
		||||
    if (reason === SubscriptionDropReason.UserInitiated && this._subscription !== null && connection !== null) {
 | 
			
		||||
      connection.enqueueSend(this._createUnsubscriptionPackage());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var self = this;
 | 
			
		||||
    if (this._subscription !== null)
 | 
			
		||||
      this._executeAction(function() { self._subscriptionDropped(self._subscription, reason, err); });
 | 
			
		||||
    if (this._subscription !== null) {
 | 
			
		||||
      this._executeAction(function () {
 | 
			
		||||
        self._subscriptionDropped(self._subscription, reason, err);
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
SubscriptionOperation.prototype._confirmSubscription = function(lastCommitPosition, lastEventNumber) {
 | 
			
		||||
  if (lastCommitPosition < -1)
 | 
			
		||||
  if (lastCommitPosition < -1) {
 | 
			
		||||
    throw new Error(util.format("Invalid lastCommitPosition %s on subscription confirmation.", lastCommitPosition));
 | 
			
		||||
  if (this._subscription !== null)
 | 
			
		||||
  }
 | 
			
		||||
  if (this._subscription !== null) {
 | 
			
		||||
    throw new Error("Double confirmation of subscription.");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (this._verboseLogging)
 | 
			
		||||
  if (this._verboseLogging) {
 | 
			
		||||
    this._log.debug("Subscription %s to %s: subscribed at CommitPosition: %d, EventNumber: %d.",
 | 
			
		||||
        this._correlationId, this._streamId || "<all>", lastCommitPosition, lastEventNumber);
 | 
			
		||||
      this._correlationId, this._streamId || "<all>", lastCommitPosition, lastEventNumber);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  this._subscription = this._createSubscriptionObject(lastCommitPosition, lastEventNumber);
 | 
			
		||||
  this._cb(null, this._subscription);
 | 
			
		||||
@@ -221,15 +225,15 @@ SubscriptionOperation.prototype._createSubscriptionObject = function(lastCommitP
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
SubscriptionOperation.prototype._onEventAppeared = function(e) {
 | 
			
		||||
  if (this._unsubscribed)
 | 
			
		||||
    return;
 | 
			
		||||
  if (this._unsubscribed) return;
 | 
			
		||||
 | 
			
		||||
  if (this._subscription === null) throw new Error("Subscription not confirmed, but event appeared!");
 | 
			
		||||
 | 
			
		||||
  if (this._verboseLogging)
 | 
			
		||||
  if (this._verboseLogging) {
 | 
			
		||||
    this._log.debug("Subscription %s to %s: event appeared (%s, %d, %s @ %s).",
 | 
			
		||||
        this._correlationId, this._streamId || "<all>",
 | 
			
		||||
        e.originalStreamId, e.originalEventNumber, e.originalEvent.eventType, e.originalPosition);
 | 
			
		||||
      this._correlationId, this._streamId || "<all>",
 | 
			
		||||
      e.originalStreamId, e.originalEventNumber, e.originalEvent.eventType, e.originalPosition);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  var self = this;
 | 
			
		||||
  this._executeAction(function() { return self._eventAppeared(self._subscription, e); });
 | 
			
		||||
@@ -275,4 +279,4 @@ SubscriptionOperation.prototype.toString = function() {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
module.exports = SubscriptionOperation;
 | 
			
		||||
module.exports = SubscriptionOperation;
 | 
			
		||||
 
 | 
			
		||||
@@ -32,7 +32,7 @@ TransactionalWriteOperation.prototype._createRequestDto = function() {
 | 
			
		||||
  return new ClientMessage.TransactionWrite({
 | 
			
		||||
    transactionId: this._transactionId,
 | 
			
		||||
    events: dtos,
 | 
			
		||||
    requireMaster: this._requireMaster
 | 
			
		||||
    requireLeader: this._requireMaster
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -65,4 +65,3 @@ TransactionalWriteOperation.prototype.toString = function() {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports = TransactionalWriteOperation;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,4 @@
 | 
			
		||||
var util = require('util');
 | 
			
		||||
var uuid = require('uuid');
 | 
			
		||||
 | 
			
		||||
var ensure = require('../common/utils/ensure');
 | 
			
		||||
var OperationBase = require('../clientOperations/operationBase');
 | 
			
		||||
@@ -84,4 +83,4 @@ UpdatePersistentSubscriptionOperation.prototype.toString = function() {
 | 
			
		||||
  return util.format("Stream: %s, Group Name: %s", this._stream, this._groupName);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports = UpdatePersistentSubscriptionOperation;
 | 
			
		||||
module.exports = UpdatePersistentSubscriptionOperation;
 | 
			
		||||
@@ -46,7 +46,7 @@ VolatileSubscriptionOperation.prototype._inspectPackage = function(pkg) {
 | 
			
		||||
    }
 | 
			
		||||
    return null;
 | 
			
		||||
  } catch(e) {
 | 
			
		||||
    console.log(e.stack);
 | 
			
		||||
    this._log.warn(e.stack);
 | 
			
		||||
    return null;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
@@ -55,4 +55,4 @@ VolatileSubscriptionOperation.prototype._createSubscriptionObject = function(las
 | 
			
		||||
  return new VolatileEventStoreSubscription(this, this._streamId, lastCommitPosition, lastEventNumber);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports = VolatileSubscriptionOperation;
 | 
			
		||||
module.exports = VolatileSubscriptionOperation;
 | 
			
		||||
 
 | 
			
		||||
@@ -19,8 +19,7 @@ BufferSegment.prototype.toString = function() {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
BufferSegment.prototype.toBuffer = function() {
 | 
			
		||||
  if (this.offset === 0 && this.count === this.buffer.length)
 | 
			
		||||
      return this.buffer;
 | 
			
		||||
  if (this.offset === 0 && this.count === this.buffer.length) return this.buffer;
 | 
			
		||||
  return this.buffer.slice(this.offset, this.offset + this.count);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -14,14 +14,14 @@ function parse(s, buf, offset) {
 | 
			
		||||
  var ii = 0;
 | 
			
		||||
 | 
			
		||||
  if (buf) buf.fill(0, i, i + 16);
 | 
			
		||||
  buf = buf || new Buffer(16);
 | 
			
		||||
  buf = buf || Buffer.alloc(16);
 | 
			
		||||
  s.toLowerCase().replace(/[0-9a-f]{2}/g, function(oct) {
 | 
			
		||||
    if (ii < 16) { // Don't overflow!
 | 
			
		||||
      buf[i + ii++] = _hexToByte[oct];
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  var buf2 = new Buffer(buf.slice(i, i + 16));
 | 
			
		||||
  var buf2 = Buffer.from(buf.slice(i, i + 16));
 | 
			
		||||
  buf[i + 0] = buf2[3];
 | 
			
		||||
  buf[i + 1] = buf2[2];
 | 
			
		||||
  buf[i + 2] = buf2[1];
 | 
			
		||||
@@ -44,4 +44,4 @@ function unparse(buf, offset) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exports.parse = parse;
 | 
			
		||||
exports.unparse = unparse;
 | 
			
		||||
exports.unparse = unparse;
 | 
			
		||||
 
 | 
			
		||||
@@ -39,4 +39,4 @@ Hash.prototype.remove = function(key) {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
module.exports = Hash;
 | 
			
		||||
module.exports = Hash;
 | 
			
		||||
@@ -26,6 +26,11 @@ FileLogger.prototype.info = function() {
 | 
			
		||||
  fs.appendFileSync(this._filePath, line);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
FileLogger.prototype.warn = function() {
 | 
			
		||||
  var line = createLine('WARN', arguments, 0);
 | 
			
		||||
  fs.appendFileSync(this._filePath, line);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
FileLogger.prototype.error = function(e) {
 | 
			
		||||
  var hasError = e instanceof Error;
 | 
			
		||||
  var line = createLine('ERROR', arguments, hasError ? 1 : 0);
 | 
			
		||||
@@ -36,4 +41,4 @@ FileLogger.prototype.error = function(e) {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
module.exports = FileLogger;
 | 
			
		||||
module.exports = FileLogger;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,8 @@
 | 
			
		||||
function NoopLogger() {
 | 
			
		||||
}
 | 
			
		||||
NoopLogger.prototype.error = function() {};
 | 
			
		||||
NoopLogger.prototype.debug = function() {};
 | 
			
		||||
NoopLogger.prototype.info = function() {};
 | 
			
		||||
NoopLogger.prototype.warn = function() {};
 | 
			
		||||
NoopLogger.prototype.error = function() {};
 | 
			
		||||
 | 
			
		||||
module.exports = NoopLogger;
 | 
			
		||||
module.exports = NoopLogger;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
const SystemEventTypes = {
 | 
			
		||||
const SystemEventTypes = Object.freeze({
 | 
			
		||||
  StreamMetadata: '$metadata'
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
module.exports = SystemEventTypes;
 | 
			
		||||
module.exports = SystemEventTypes;
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
const SystemMetadata = {
 | 
			
		||||
const SystemMetadata = Object.freeze({
 | 
			
		||||
  maxAge: '$maxAge',
 | 
			
		||||
  maxCount: '$maxCount',
 | 
			
		||||
  truncateBefore: '$tb',
 | 
			
		||||
@@ -11,7 +11,6 @@ const SystemMetadata = {
 | 
			
		||||
  aclMetaWrite: '$mw',
 | 
			
		||||
  userStreamAcl: '$userStreamAcl',
 | 
			
		||||
  systemStreamAcl: '$systemStreamAcl'
 | 
			
		||||
};
 | 
			
		||||
Object.freeze(SystemMetadata);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
module.exports = SystemMetadata;
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
module.exports.metastreamOf = function(stream) {
 | 
			
		||||
exports.metastreamOf = function(stream) {
 | 
			
		||||
  return '$$' + stream;
 | 
			
		||||
};
 | 
			
		||||
module.exports.isMetastream = function(stream) {
 | 
			
		||||
exports.isMetastream = function(stream) {
 | 
			
		||||
  return stream.indexOf('$$') === 0;
 | 
			
		||||
};
 | 
			
		||||
@@ -1,39 +1,45 @@
 | 
			
		||||
var Long = require('long');
 | 
			
		||||
 | 
			
		||||
module.exports.notNullOrEmpty = function(value, name) {
 | 
			
		||||
  if (value === null)
 | 
			
		||||
    throw new TypeError(name + " should not be null.");
 | 
			
		||||
  if (value === '')
 | 
			
		||||
    throw new Error(name + " should not be empty.");
 | 
			
		||||
  if (value === null) throw new TypeError(name + " should not be null.");
 | 
			
		||||
  if (value === '') throw new Error(name + " should not be empty.");
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports.notNull = function(value, name) {
 | 
			
		||||
  if (value === null)
 | 
			
		||||
    throw new TypeError(name + " should not be null.");
 | 
			
		||||
  if (value === null) throw new TypeError(name + " should not be null.");
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports.isInteger = function(value, name) {
 | 
			
		||||
  if (typeof value !== 'number' || value % 1 !== 0)
 | 
			
		||||
    throw new TypeError(name + " should be an integer.");
 | 
			
		||||
function isInteger(value, name) {
 | 
			
		||||
  if (typeof value !== 'number' || value % 1 !== 0) 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) {
 | 
			
		||||
  if (!Array.isArray(value))
 | 
			
		||||
    throw new TypeError(name + " should be an array.");
 | 
			
		||||
  if (!value.every(function(x) { return x instanceof expectedType; }))
 | 
			
		||||
  if (!Array.isArray(value)) throw new TypeError(name + " should be an array.");
 | 
			
		||||
  if (!value.every(function(x) { return x instanceof expectedType; })) {
 | 
			
		||||
    throw new TypeError([name, " should be an array of ", expectedType.name, "."].join(""));
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports.isTypeOf = function(expectedType, value, name, nullAllowed) {
 | 
			
		||||
  if (nullAllowed && value === null) return;
 | 
			
		||||
  if (!(value instanceof expectedType))
 | 
			
		||||
    throw new TypeError([name, " should be of type '", expectedType.name, "'", nullAllowed ? " or null": "", "."].join(""));
 | 
			
		||||
  if (!(value instanceof expectedType)) {
 | 
			
		||||
    throw new TypeError([name, " should be of type '", expectedType.name, "'", nullAllowed ? " or null" : "", "."].join(""));
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports.positive = function(value, name) {
 | 
			
		||||
  if (value <= 0)
 | 
			
		||||
    throw new Error(name + " should be positive.");
 | 
			
		||||
  if (value <= 0) throw new Error(name + " should be positive.");
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports.nonNegative = function(value, name) {
 | 
			
		||||
  if (value < 0)
 | 
			
		||||
    throw new Error(name + " should be non-negative.");
 | 
			
		||||
  if (value < 0) throw new Error(name + " should be non-negative.");
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										28
									
								
								src/common/utils/shuffle.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/common/utils/shuffle.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
			
		||||
function rndNext(min, max) {
 | 
			
		||||
  min = Math.ceil(min);
 | 
			
		||||
  max = Math.floor(max);
 | 
			
		||||
  return Math.floor(Math.random() * (max - min)) + min;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function shuffle (arr, from, to) {
 | 
			
		||||
  if (arr.length <= 1){
 | 
			
		||||
    return arr;
 | 
			
		||||
  }
 | 
			
		||||
  if (!from) {
 | 
			
		||||
    from = 0;
 | 
			
		||||
  }
 | 
			
		||||
  if (!to) {
 | 
			
		||||
    to = arr.length - 1;
 | 
			
		||||
  }
 | 
			
		||||
  const newArr = [...arr];
 | 
			
		||||
  if (from >= to) return;
 | 
			
		||||
  for (var current = from; current <= to; ++current) {
 | 
			
		||||
    var index = rndNext(current, to + 1);
 | 
			
		||||
    var tmp = newArr[index];
 | 
			
		||||
    newArr[index] = newArr[current];
 | 
			
		||||
    newArr[current] = tmp;
 | 
			
		||||
  }
 | 
			
		||||
  return newArr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports = shuffle;
 | 
			
		||||
							
								
								
									
										165
									
								
								src/core/cluster/clusterDiscoverer.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										165
									
								
								src/core/cluster/clusterDiscoverer.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,165 @@
 | 
			
		||||
const ClusterInfo = require('./clusterInfo');
 | 
			
		||||
const GossipSeed = require('../../gossipSeed');
 | 
			
		||||
const NodeEndPoints = require('./nodeEndpoints');
 | 
			
		||||
const shuffle = require('../../common/utils/shuffle');
 | 
			
		||||
 | 
			
		||||
function wait(ms) {
 | 
			
		||||
  return new Promise(resolve => setTimeout(resolve, ms));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * ClusterDiscoverer
 | 
			
		||||
 * @constructor
 | 
			
		||||
 * @class
 | 
			
		||||
 * @param {Logger} log - Logger instance
 | 
			
		||||
 * @param {Object} settings - Settings object
 | 
			
		||||
 * @param {Object} dnsService - DNS service to perform DNS lookup
 | 
			
		||||
 * @param {Object} httpService - HTTP service to perform http requests
 | 
			
		||||
 */
 | 
			
		||||
function ClusterDiscoverer(log, settings, dnsService, httpService) {
 | 
			
		||||
  if (!settings.clusterDns && (!settings.seeds || settings.seeds.length === 0))
 | 
			
		||||
    throw new Error('Both clusterDns and seeds are null/empty.');
 | 
			
		||||
  this._log = log;
 | 
			
		||||
 | 
			
		||||
  this._settings = settings;
 | 
			
		||||
  this._dnsService = dnsService;
 | 
			
		||||
  this._httpService = httpService;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Discover Cluster endpoints
 | 
			
		||||
 * @param {Object} failedTcpEndPoint - The failed TCP endpoint which were used by the handler
 | 
			
		||||
 * @returns {Promise.<NodeEndPoints>}
 | 
			
		||||
 */
 | 
			
		||||
ClusterDiscoverer.prototype.discover = async function (failedTcpEndPoint) {
 | 
			
		||||
  let attempts = 0;
 | 
			
		||||
  while (attempts++ < this._settings.maxDiscoverAttempts) {
 | 
			
		||||
    try {
 | 
			
		||||
      const candidates = await this._getGossipCandidates(this._settings.managerExternalHttpPort);
 | 
			
		||||
      const gossipSeeds = candidates.filter(
 | 
			
		||||
        (candidate) =>
 | 
			
		||||
          !failedTcpEndPoint ||
 | 
			
		||||
          !(candidate.endPoint.host === failedTcpEndPoint.host && candidate.endPoint.port === failedTcpEndPoint.port)
 | 
			
		||||
      );
 | 
			
		||||
      let gossipSeedsIndex = 0;
 | 
			
		||||
      let clusterInfo;
 | 
			
		||||
      do {
 | 
			
		||||
        try {
 | 
			
		||||
          clusterInfo = await this._clusterInfo(gossipSeeds[gossipSeedsIndex], this._settings.gossipTimeout);
 | 
			
		||||
          if (!clusterInfo.bestNode) {
 | 
			
		||||
            this._log.info(
 | 
			
		||||
              `Discovering attempt ${attempts}/${this._settings.maxDiscoverAttempts} failed: no candidate found.`
 | 
			
		||||
            );
 | 
			
		||||
            continue;
 | 
			
		||||
          }
 | 
			
		||||
        } catch (err) {}
 | 
			
		||||
      } while (++gossipSeedsIndex < gossipSeeds.length);
 | 
			
		||||
      if (clusterInfo) {
 | 
			
		||||
        return NodeEndPoints.createFromGossipMember(clusterInfo.bestNode);
 | 
			
		||||
      }
 | 
			
		||||
    } catch (err) {
 | 
			
		||||
      this._log.info(
 | 
			
		||||
        `Discovering attempt ${attempts}/${this._settings.maxDiscoverAttempts} failed with error: ${err}.\n${err.stack}`
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
    await wait(this._settings.discoverDelay);
 | 
			
		||||
  }
 | 
			
		||||
  throw new Error(`Failed to discover candidate in ${this._settings.maxDiscoverAttempts} attempts.`);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Get gossip candidates either from DNS or from gossipSeeds settings
 | 
			
		||||
 * @private
 | 
			
		||||
 * @param {Number} managerExternalHttpPort - Http port of the manager (or the http port of the node for OSS clusters)
 | 
			
		||||
 * @returns {Promise.<GossipSeed[]>}
 | 
			
		||||
 */
 | 
			
		||||
ClusterDiscoverer.prototype._getGossipCandidates = async function (managerExternalHttpPort) {
 | 
			
		||||
  const gossipSeeds =
 | 
			
		||||
    this._settings.seeds && this._settings.seeds.length > 0
 | 
			
		||||
      ? this._settings.seeds
 | 
			
		||||
      : (await this._resolveDns(this._settings.clusterDns)).map(
 | 
			
		||||
          (address) => new GossipSeed({ host: address, port: managerExternalHttpPort }, address, this._settings.clusterDns)
 | 
			
		||||
        );
 | 
			
		||||
  return shuffle(gossipSeeds);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Resolve the cluster DNS discovery address to retrieve belonging ip addresses
 | 
			
		||||
 * @private
 | 
			
		||||
 * @param {String} clusterDns - Cluster DNS discovery address
 | 
			
		||||
 * @returns {Promise.<String[]>}
 | 
			
		||||
 */
 | 
			
		||||
ClusterDiscoverer.prototype._resolveDns = async function (clusterDns) {
 | 
			
		||||
  const dnsOptions = {
 | 
			
		||||
    family: 4,
 | 
			
		||||
    hints: this._dnsService.ADDRCONFIG | this._dnsService.V4MAPPED,
 | 
			
		||||
    all: true,
 | 
			
		||||
  };
 | 
			
		||||
  const result = await this._dnsService.lookup(clusterDns, dnsOptions);
 | 
			
		||||
  if (!result || result.length === 0) {
 | 
			
		||||
    throw new Error(`No result from dns lookup for ${clusterDns}`);
 | 
			
		||||
  }
 | 
			
		||||
  return result.map((address) => address.address);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Get cluster informations (gossip members)
 | 
			
		||||
 * @param {GossipSeed} candidate - candidate to get informations from
 | 
			
		||||
 * @param {Number} timeout - timeout for the http request
 | 
			
		||||
 * @returns {Promise.<ClusterInfo>}
 | 
			
		||||
 */
 | 
			
		||||
ClusterDiscoverer.prototype._clusterInfo = async function (candidate, timeout) {
 | 
			
		||||
  var self = this;
 | 
			
		||||
  return new Promise((resolve, reject) => {
 | 
			
		||||
    const options = {
 | 
			
		||||
      host: candidate.endPoint.host,
 | 
			
		||||
      port: candidate.endPoint.port,
 | 
			
		||||
      path: '/gossip?format=json',
 | 
			
		||||
      timeout: timeout,
 | 
			
		||||
      rejectUnauthorized: self._settings.rejectUnauthorized
 | 
			
		||||
    };
 | 
			
		||||
    if (candidate.hostHeader) {
 | 
			
		||||
      options.headers = {
 | 
			
		||||
        Host: candidate.hostHeader,
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const request = this._httpService.request(options, (res) => {
 | 
			
		||||
      if (res.statusCode !== 200) {
 | 
			
		||||
        this._log.info('Trying to get gossip from', candidate, 'failed with status code:', res.statusCode);
 | 
			
		||||
        reject(new Error(`Gossip candidate returns a ${res.statusCode} error`));
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      let result = '';
 | 
			
		||||
      res.on('data', (chunk) => {
 | 
			
		||||
        result += chunk.toString();
 | 
			
		||||
      });
 | 
			
		||||
      res.on('end', function () {
 | 
			
		||||
        try {
 | 
			
		||||
          result = JSON.parse(result);
 | 
			
		||||
        } catch (e) {
 | 
			
		||||
          reject(new Error('Unable to parse gossip response'));
 | 
			
		||||
        }
 | 
			
		||||
        resolve(new ClusterInfo(result.members));
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    request.setTimeout(timeout);
 | 
			
		||||
 | 
			
		||||
    request.on('timeout', () => {
 | 
			
		||||
      this._log.info('Trying to get gossip from', candidate, 'timed out.');
 | 
			
		||||
      request.destroy();
 | 
			
		||||
      reject(new Error('Connection to gossip timed out'));
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    request.on('error', (error) => {
 | 
			
		||||
      this._log.info('Trying to get gossip from', candidate, 'errored', error);
 | 
			
		||||
      request.destroy();
 | 
			
		||||
      reject(new Error('Connection to gossip errored'));
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    request.end();
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports = ClusterDiscoverer;
 | 
			
		||||
							
								
								
									
										41
									
								
								src/core/cluster/clusterInfo.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								src/core/cluster/clusterInfo.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
			
		||||
const MemberInfo = require('./memberInfo.js');
 | 
			
		||||
 | 
			
		||||
const VNodeStates = Object.freeze({
 | 
			
		||||
  Initializing: 0,
 | 
			
		||||
  DiscoverLeader: 1,
 | 
			
		||||
  Unknown: 2,
 | 
			
		||||
  PreReplica: 3,
 | 
			
		||||
  CatchingUp: 4,
 | 
			
		||||
  Clone: 5,
 | 
			
		||||
  Follower: 6,
 | 
			
		||||
  PreLeader: 7,
 | 
			
		||||
  Leader: 8,
 | 
			
		||||
  Manager: 9,
 | 
			
		||||
  ShuttingDown: 10,
 | 
			
		||||
  Shutdown: 11,
 | 
			
		||||
  ReadOnlyLeaderless: 12,
 | 
			
		||||
  PreReadOnlyReplica: 13,
 | 
			
		||||
  ReadOnlyReplica: 14,
 | 
			
		||||
  ResigningLeader: 15,
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function ClusterInfo(members) {
 | 
			
		||||
  this._members = members.map(member => new MemberInfo(member));
 | 
			
		||||
 | 
			
		||||
  Object.defineProperty(this, 'bestNode', {
 | 
			
		||||
    enumerable: true,
 | 
			
		||||
    get: function () {
 | 
			
		||||
      return this._getBestNode();
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ClusterInfo.prototype._getBestNode = function () {
 | 
			
		||||
  return this._members
 | 
			
		||||
  .filter(member => member.isAlive && member.isAllowedToConnect)
 | 
			
		||||
  .sort(function (a, b) {
 | 
			
		||||
    return VNodeStates[b.state] - VNodeStates[a.state];
 | 
			
		||||
  })[0];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = ClusterInfo;
 | 
			
		||||
							
								
								
									
										73
									
								
								src/core/cluster/memberInfo.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								src/core/cluster/memberInfo.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,73 @@
 | 
			
		||||
const NOT_ALLOWED_STATES = [
 | 
			
		||||
  'Manager',
 | 
			
		||||
  'ShuttingDown',
 | 
			
		||||
  'Shutdown'
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
function MemberInfo(informations) {
 | 
			
		||||
  this._instanceId = informations.instanceId;
 | 
			
		||||
  this._timeStamp = informations.timeStamp;
 | 
			
		||||
  this._state = informations.state;
 | 
			
		||||
  this._isAlive = informations.isAlive;
 | 
			
		||||
  this._internalTcpIp = informations.internalTcpIp;
 | 
			
		||||
  this._internalTcpPort = informations.internalTcpPort;
 | 
			
		||||
  this._internalSecureTcpPort = informations.internalSecureTcpPort;
 | 
			
		||||
  this._externalTcpIp = informations.externalTcpIp;
 | 
			
		||||
  this._externalTcpPort = informations.externalTcpPort;
 | 
			
		||||
  this._externalSecureTcpPort = informations.externalSecureTcpPort;
 | 
			
		||||
  this._internalHttpIp = informations.internalHttpIp;
 | 
			
		||||
  this._internalHttpPort = informations.internalHttpPort;
 | 
			
		||||
  this._externalHttpIp = informations.externalHttpIp;
 | 
			
		||||
  this._externalHttpPort = informations.externalHttpPort;
 | 
			
		||||
  this._lastCommitPosition = informations.lastCommitPosition;
 | 
			
		||||
  this._writerCheckpoint = informations.writerCheckpoint;
 | 
			
		||||
  this._chaserCheckpoint = informations.chaserCheckpoint;
 | 
			
		||||
  this._epochPosition = informations.epochPosition;
 | 
			
		||||
  this._epochNumber = informations.epochNumber;
 | 
			
		||||
  this._epochId = informations.epochId;
 | 
			
		||||
  this._nodePriority = informations.nodePriority;
 | 
			
		||||
 | 
			
		||||
  Object.defineProperty(this, 'state', {
 | 
			
		||||
    enumerable: true,
 | 
			
		||||
    get: function () {
 | 
			
		||||
      return this._state;
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  Object.defineProperty(this, 'isAllowedToConnect', {
 | 
			
		||||
    enumerable: true,
 | 
			
		||||
    get: function () {
 | 
			
		||||
      return !NOT_ALLOWED_STATES.includes(this._state);
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  Object.defineProperty(this, 'isAlive', {
 | 
			
		||||
    enumerable: true,
 | 
			
		||||
    get: function () {
 | 
			
		||||
      return this._isAlive;
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  Object.defineProperty(this, 'externalTcpIp', {
 | 
			
		||||
    enumerable: true,
 | 
			
		||||
    get: function () {
 | 
			
		||||
      return this._externalTcpIp;
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  Object.defineProperty(this, 'externalTcpPort', {
 | 
			
		||||
    enumerable: true,
 | 
			
		||||
    get: function () {
 | 
			
		||||
      return this._externalTcpPort;
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  Object.defineProperty(this, 'externalSecureTcpPort', {
 | 
			
		||||
    enumerable: true,
 | 
			
		||||
    get: function () {
 | 
			
		||||
      return this._externalSecureTcpPort;
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = MemberInfo;
 | 
			
		||||
							
								
								
									
										23
									
								
								src/core/cluster/nodeEndpoints.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/core/cluster/nodeEndpoints.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
			
		||||
function NodeEndPoints(tcpEndPoint, secureTcpEndPoint) {
 | 
			
		||||
  if (tcpEndPoint === null && secureTcpEndPoint === null) throw new Error('Both endpoints are null.');
 | 
			
		||||
  Object.defineProperties(this, {
 | 
			
		||||
    tcpEndPoint: {
 | 
			
		||||
      enumerable: true,
 | 
			
		||||
      value: tcpEndPoint
 | 
			
		||||
    },
 | 
			
		||||
    secureTcpEndPoint: {
 | 
			
		||||
      enumerable: true,
 | 
			
		||||
      value: secureTcpEndPoint
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NodeEndPoints.createFromGossipMember = function (member) {
 | 
			
		||||
  const normTcp = { host: member.externalTcpIp, port: member.externalTcpPort };
 | 
			
		||||
  const secTcp = member.externalSecureTcpPort > 0
 | 
			
		||||
    ? { host: member.externalTcpIp, port: member.externalSecureTcpPort }
 | 
			
		||||
    : null;
 | 
			
		||||
  return new NodeEndPoints(normTcp, secTcp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = NodeEndPoints
 | 
			
		||||
@@ -1,254 +0,0 @@
 | 
			
		||||
var http = require('http');
 | 
			
		||||
var util = require('util');
 | 
			
		||||
var dns = require('dns');
 | 
			
		||||
var GossipSeed = require('../gossipSeed');
 | 
			
		||||
 | 
			
		||||
function NodeEndPoints(tcpEndPoint, secureTcpEndPoint) {
 | 
			
		||||
  if (tcpEndPoint === null && secureTcpEndPoint === null) throw new Error('Both endpoints are null.');
 | 
			
		||||
  Object.defineProperties(this, {
 | 
			
		||||
    tcpEndPoint: {
 | 
			
		||||
      enumerable: true,
 | 
			
		||||
      value: tcpEndPoint
 | 
			
		||||
    },
 | 
			
		||||
    secureTcpEndPoint: {
 | 
			
		||||
      enumerable: true,
 | 
			
		||||
      value: secureTcpEndPoint
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function ClusterDnsEndPointDiscoverer(log, clusterDns, maxDiscoverAttempts, managerExternalHttpPort, gossipSeeds, gossipTimeout) {
 | 
			
		||||
  if (!clusterDns && (!gossipSeeds || gossipSeeds.length === 0)) throw new Error('Both clusterDns and gossipSeeds are null/empty.');
 | 
			
		||||
  this._log = log;
 | 
			
		||||
  this._clusterDns = clusterDns;
 | 
			
		||||
  this._maxDiscoverAttempts = maxDiscoverAttempts;
 | 
			
		||||
  this._managerExternalHttpPort = managerExternalHttpPort;
 | 
			
		||||
  this._gossipSeeds = gossipSeeds;
 | 
			
		||||
  this._gossipTimeout = gossipTimeout;
 | 
			
		||||
  this._oldGossip = null;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ClusterDnsEndPointDiscoverer.prototype.discover = function(failedTcpEndPoint) {
 | 
			
		||||
  var attempt = 1;
 | 
			
		||||
  var self = this;
 | 
			
		||||
  function discover(resolve, reject) {
 | 
			
		||||
    self._discoverEndPoint(failedTcpEndPoint)
 | 
			
		||||
      .then(function (endPoints) {
 | 
			
		||||
        if (!endPoints)
 | 
			
		||||
          self._log.info(util.format("Discovering attempt %d/%d failed: no candidate found.", attempt, self._maxDiscoverAttempts));
 | 
			
		||||
        return endPoints;
 | 
			
		||||
      })
 | 
			
		||||
      .catch(function (exc) {
 | 
			
		||||
        self._log.info(util.format("Discovering attempt %d/%d failed with error: %s.\n%s", attempt, self._maxDiscoverAttempts, exc, exc.stack));
 | 
			
		||||
      })
 | 
			
		||||
      .then(function (endPoints) {
 | 
			
		||||
        if (endPoints)
 | 
			
		||||
          return resolve(endPoints);
 | 
			
		||||
        if (attempt++ === self._maxDiscoverAttempts)
 | 
			
		||||
          return reject(new Error('Failed to discover candidate in ' + self._maxDiscoverAttempts + ' attempts.'));
 | 
			
		||||
        setTimeout(discover, 500, resolve, reject);
 | 
			
		||||
      });
 | 
			
		||||
  }
 | 
			
		||||
  return new Promise(function (resolve, reject) {
 | 
			
		||||
    discover(resolve, reject);
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Discover Cluster endpoints
 | 
			
		||||
 * @param {Object} failedTcpEndPoint
 | 
			
		||||
 * @returns {Promise.<NodeEndPoints>}
 | 
			
		||||
 * @private
 | 
			
		||||
 */
 | 
			
		||||
ClusterDnsEndPointDiscoverer.prototype._discoverEndPoint = function (failedTcpEndPoint) {
 | 
			
		||||
  try {
 | 
			
		||||
    var mainPromise = this._oldGossip
 | 
			
		||||
      ? Promise.resolve(this._getGossipCandidatesFromOldGossip(this._oldGossip, failedTcpEndPoint))
 | 
			
		||||
      : this._getGossipCandidatesFromDns();
 | 
			
		||||
    var self = this;
 | 
			
		||||
    var j = 0;
 | 
			
		||||
    return mainPromise.then(function (gossipCandidates) {
 | 
			
		||||
      var loopPromise = Promise.resolve();
 | 
			
		||||
      for (var i = 0; i < gossipCandidates.length; i++) {
 | 
			
		||||
        loopPromise = loopPromise.then(function (endPoints) {
 | 
			
		||||
          if (endPoints) return endPoints;
 | 
			
		||||
          return self._tryGetGossipFrom(gossipCandidates[j++])
 | 
			
		||||
            .then(function (gossip) {
 | 
			
		||||
              if (!gossip || !gossip.members || gossip.members.length === 0)
 | 
			
		||||
                return;
 | 
			
		||||
              var bestNode = self._tryDetermineBestNode(gossip.members);
 | 
			
		||||
              if (bestNode) {
 | 
			
		||||
                self._oldGossip = gossip.members;
 | 
			
		||||
                return bestNode;
 | 
			
		||||
              }
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
      return loopPromise;
 | 
			
		||||
    });
 | 
			
		||||
  } catch (e) {
 | 
			
		||||
    return Promise.reject(e);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
ClusterDnsEndPointDiscoverer.prototype._getGossipCandidatesFromOldGossip = function (oldGossip, failedTcpEndPoint) {
 | 
			
		||||
  if (!failedTcpEndPoint) return this._arrangeGossipCandidates(oldGossip);
 | 
			
		||||
  var gossipCandidates = oldGossip.filter(function(x) {
 | 
			
		||||
    return !(x.externalTcpPort === failedTcpEndPoint.port && x.externalTcpIp === failedTcpEndPoint.host);
 | 
			
		||||
  });
 | 
			
		||||
  return this._arrangeGossipCandidates(gossipCandidates);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
ClusterDnsEndPointDiscoverer.prototype._arrangeGossipCandidates = function (members) {
 | 
			
		||||
  var result = new Array(members.length);
 | 
			
		||||
  var i = -1;
 | 
			
		||||
  var j = members.length;
 | 
			
		||||
  for (var k = 0; k < members.length; ++k)
 | 
			
		||||
  {
 | 
			
		||||
    if (members[k].state === 'Manager')
 | 
			
		||||
      result[--j] = new GossipSeed({host: members[k].externalHttpIp, port: members[k].externalHttpPort});
 | 
			
		||||
    else
 | 
			
		||||
      result[++i] = new GossipSeed({host: members[k].externalHttpIp, port: members[k].externalHttpPort});
 | 
			
		||||
  }
 | 
			
		||||
  this._randomShuffle(result, 0, i); // shuffle nodes
 | 
			
		||||
  this._randomShuffle(result, j, members.length - 1); // shuffle managers
 | 
			
		||||
  return result;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
ClusterDnsEndPointDiscoverer.prototype._getGossipCandidatesFromDns = function () {
 | 
			
		||||
  var self = this;
 | 
			
		||||
  return new Promise(function (resolve, reject) {
 | 
			
		||||
    if (self._gossipSeeds && self._gossipSeeds.length > 0) {
 | 
			
		||||
      var endpoints = self._gossipSeeds;
 | 
			
		||||
      self._randomShuffle(endpoints, 0, endpoints.length - 1);
 | 
			
		||||
      resolve(endpoints);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      const dnsOptions = {
 | 
			
		||||
        family: 4,
 | 
			
		||||
        hints: dns.ADDRCONFIG | dns.V4MAPPED,
 | 
			
		||||
        all: true
 | 
			
		||||
      };
 | 
			
		||||
      dns.lookup(self._clusterDns, dnsOptions, function (err, addresses) {
 | 
			
		||||
        if (err) {
 | 
			
		||||
          return reject(err);
 | 
			
		||||
        }
 | 
			
		||||
        if (!addresses || addresses.length === 0) {
 | 
			
		||||
          return reject(new Error('No result from dns lookup for ' + self._clusterDns));
 | 
			
		||||
        }
 | 
			
		||||
        var endpoints = addresses.map(function (x) {
 | 
			
		||||
          return new GossipSeed({host: x.address, port: self._managerExternalHttpPort});
 | 
			
		||||
        });
 | 
			
		||||
        resolve(endpoints);
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
ClusterDnsEndPointDiscoverer.prototype._tryGetGossipFrom = function (endPoint) {
 | 
			
		||||
  var options = {
 | 
			
		||||
    host: endPoint.endPoint.host,
 | 
			
		||||
    port: endPoint.endPoint.port,
 | 
			
		||||
    path: '/gossip?format=json'
 | 
			
		||||
  };
 | 
			
		||||
  if (endPoint.hostHeader) {
 | 
			
		||||
    options.headers = {'Host': endPoint.hostHeader};
 | 
			
		||||
  }
 | 
			
		||||
  this._log.info('Try get gossip from', endPoint);
 | 
			
		||||
  var self = this;
 | 
			
		||||
  return new Promise(function (resolve, reject) {
 | 
			
		||||
    var timedout = false;
 | 
			
		||||
    http.request(options, function (res) {
 | 
			
		||||
          if (timedout) return;
 | 
			
		||||
          var result = '';
 | 
			
		||||
          if (res.statusCode !== 200) {
 | 
			
		||||
            self._log.info('Trying to get gossip from', endPoint, 'failed with status code:', res.statusCode);
 | 
			
		||||
            resolve();
 | 
			
		||||
            return;
 | 
			
		||||
          }
 | 
			
		||||
          res.on('data', function (chunk) {
 | 
			
		||||
            result += chunk.toString();
 | 
			
		||||
          });
 | 
			
		||||
          res.on('end', function () {
 | 
			
		||||
            try {
 | 
			
		||||
              result = JSON.parse(result);
 | 
			
		||||
            } catch (e) {
 | 
			
		||||
              return resolve();
 | 
			
		||||
            }
 | 
			
		||||
            resolve(result);
 | 
			
		||||
          });
 | 
			
		||||
        })
 | 
			
		||||
        .setTimeout(self._gossipTimeout, function () {
 | 
			
		||||
          self._log.info('Trying to get gossip from', endPoint, 'timed out.');
 | 
			
		||||
          timedout = true;
 | 
			
		||||
          resolve();
 | 
			
		||||
        })
 | 
			
		||||
        .on('error', function (e) {
 | 
			
		||||
          if (timedout) return;
 | 
			
		||||
          self._log.info('Trying to get gossip from', endPoint, 'failed with error:', e);
 | 
			
		||||
          resolve();
 | 
			
		||||
        })
 | 
			
		||||
        .end();
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const VNodeStates = {
 | 
			
		||||
  'Initializing': 0,
 | 
			
		||||
  'Unknown': 1,
 | 
			
		||||
  'PreReplica': 2,
 | 
			
		||||
  'CatchingUp': 3,
 | 
			
		||||
  'Clone': 4,
 | 
			
		||||
  'Slave': 5,
 | 
			
		||||
  'PreMaster': 6,
 | 
			
		||||
  'Master': 7,
 | 
			
		||||
  'Manager': 8,
 | 
			
		||||
  'ShuttingDown': 9,
 | 
			
		||||
  'Shutdown': 10
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
ClusterDnsEndPointDiscoverer.prototype._tryDetermineBestNode = function (members) {
 | 
			
		||||
  var notAllowedStates = [
 | 
			
		||||
    'Manager',
 | 
			
		||||
    'ShuttingDown',
 | 
			
		||||
    'Shutdown'
 | 
			
		||||
  ];
 | 
			
		||||
  var node = members
 | 
			
		||||
    .filter(function (x) {
 | 
			
		||||
      return (x.isAlive && notAllowedStates.indexOf(x.state) === -1);
 | 
			
		||||
    })
 | 
			
		||||
    .sort(function (a, b) {
 | 
			
		||||
      return VNodeStates[b.state] - VNodeStates[a.state];
 | 
			
		||||
    })[0];
 | 
			
		||||
  if (!node)
 | 
			
		||||
  {
 | 
			
		||||
    //_log.Info("Unable to locate suitable node. Gossip info:\n{0}.", string.Join("\n", members.Select(x => x.ToString())));
 | 
			
		||||
    return null;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  var normTcp = {host: node.externalTcpIp, port: node.externalTcpPort};
 | 
			
		||||
  var secTcp = node.externalSecureTcpPort > 0
 | 
			
		||||
    ? {host: externalTcpIp, port: node.externalSecureTcpPort}
 | 
			
		||||
    : null;
 | 
			
		||||
  this._log.info(util.format("Discovering: found best choice [%j,%j] (%s).", normTcp, secTcp === null ? "n/a" : secTcp, node.state));
 | 
			
		||||
  return new NodeEndPoints(normTcp, secTcp);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function rndNext(min, max) {
 | 
			
		||||
  min = Math.ceil(min);
 | 
			
		||||
  max = Math.floor(max);
 | 
			
		||||
  return Math.floor(Math.random() * (max - min)) + min;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ClusterDnsEndPointDiscoverer.prototype._randomShuffle = function (arr, i, j) {
 | 
			
		||||
  if (i >= j)
 | 
			
		||||
    return;
 | 
			
		||||
  for (var k = i; k <= j; ++k)
 | 
			
		||||
  {
 | 
			
		||||
    var index = rndNext(k, j + 1);
 | 
			
		||||
    var tmp = arr[index];
 | 
			
		||||
    arr[index] = arr[k];
 | 
			
		||||
    arr[k] = tmp;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports = ClusterDnsEndPointDiscoverer;
 | 
			
		||||
@@ -9,31 +9,35 @@ var SubscriptionsManager = require('./subscriptionsManager');
 | 
			
		||||
var VolatileSubscriptionOperation = require('../clientOperations/volatileSubscriptionOperation');
 | 
			
		||||
var ConnectToPersistentSubscriptionOperation = require('../clientOperations/connectToPersistentSubscriptionOperation');
 | 
			
		||||
var messages = require('./messages');
 | 
			
		||||
var ClientMessage = require('../messages/clientMessage');
 | 
			
		||||
var createBufferSegment = require('../common/bufferSegment');
 | 
			
		||||
 | 
			
		||||
var TcpPackage = require('../systemData/tcpPackage');
 | 
			
		||||
var TcpCommand = require('../systemData/tcpCommand');
 | 
			
		||||
var TcpFlags = require('../systemData/tcpFlags');
 | 
			
		||||
var InspectionDecision = require('../systemData/inspectionDecision');
 | 
			
		||||
 | 
			
		||||
const ConnectionState = {
 | 
			
		||||
const ConnectionState = Object.freeze({
 | 
			
		||||
  Init: 'init',
 | 
			
		||||
  Connecting: 'connecting',
 | 
			
		||||
  Connected: 'connected',
 | 
			
		||||
  Closed: 'closed'
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const ConnectingPhase = {
 | 
			
		||||
const ConnectingPhase = Object.freeze({
 | 
			
		||||
  Invalid: 'invalid',
 | 
			
		||||
  Reconnecting: 'reconnecting',
 | 
			
		||||
  EndPointDiscovery: 'endpointDiscovery',
 | 
			
		||||
  ConnectionEstablishing: 'connectionEstablishing',
 | 
			
		||||
  Authentication: 'authentication',
 | 
			
		||||
  Identification: 'identification',
 | 
			
		||||
  Connected: 'connected'
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const TimerPeriod = 200;
 | 
			
		||||
const TimerTickMessage = new messages.TimerTickMessage();
 | 
			
		||||
const EmptyGuid = '00000000-0000-0000-0000-000000000000';
 | 
			
		||||
const ClientVersion = 1;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @private
 | 
			
		||||
@@ -43,9 +47,10 @@ const EmptyGuid = '00000000-0000-0000-0000-000000000000';
 | 
			
		||||
 * @property {Number} totalOperationCount
 | 
			
		||||
 */
 | 
			
		||||
function EventStoreConnectionLogicHandler(esConnection, settings) {
 | 
			
		||||
  EventEmitter.call(this);
 | 
			
		||||
  this._esConnection = esConnection;
 | 
			
		||||
  this._settings = settings;
 | 
			
		||||
  this._queue = new SimpleQueuedHandler();
 | 
			
		||||
  this._queue = new SimpleQueuedHandler(this._settings.log);
 | 
			
		||||
  this._state = ConnectionState.Init;
 | 
			
		||||
  this._connectingPhase = ConnectingPhase.Invalid;
 | 
			
		||||
  this._endpointDiscoverer = null;
 | 
			
		||||
@@ -182,8 +187,7 @@ EventStoreConnectionLogicHandler.prototype._closeConnection = function(reason, e
 | 
			
		||||
 | 
			
		||||
  this._logInfo("Closed. Reason: %s", reason);
 | 
			
		||||
 | 
			
		||||
  if (error)
 | 
			
		||||
      this.emit('error', error);
 | 
			
		||||
  if (error) this.emit('error', error);
 | 
			
		||||
 | 
			
		||||
  this.emit('closed', reason);
 | 
			
		||||
};
 | 
			
		||||
@@ -200,7 +204,7 @@ EventStoreConnectionLogicHandler.prototype._closeTcpConnection = function(reason
 | 
			
		||||
  this._connection = null;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var _nextSeqNo = -1;
 | 
			
		||||
var _nextSeqNo = 0;
 | 
			
		||||
function createOperationItem(operation, maxRetries, timeout) {
 | 
			
		||||
  var operationItem = {
 | 
			
		||||
    seqNo: _nextSeqNo++,
 | 
			
		||||
@@ -278,10 +282,11 @@ EventStoreConnectionLogicHandler.prototype._startSubscription = function(msg) {
 | 
			
		||||
          this._state === ConnectionState.Connected ? "fire" : "enqueue",
 | 
			
		||||
          operation.constructor.name, operation, msg.maxRetries, msg.timeout);
 | 
			
		||||
      var subscription = createSubscriptionItem(operation, msg.maxRetries, msg.timeout);
 | 
			
		||||
      if (this._state === ConnectionState.Connecting)
 | 
			
		||||
      if (this._state === ConnectionState.Connecting) {
 | 
			
		||||
        this._subscriptions.enqueueSubscription(subscription);
 | 
			
		||||
      else
 | 
			
		||||
      } else {
 | 
			
		||||
        this._subscriptions.startSubscription(subscription, this._connection);
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    case ConnectionState.Closed:
 | 
			
		||||
      msg.cb(new Error("Connection closed. Connection: " + this._esConnection.connectionName));
 | 
			
		||||
@@ -307,10 +312,11 @@ EventStoreConnectionLogicHandler.prototype._startPersistentSubscription = functi
 | 
			
		||||
          this._state === ConnectionState.Connected ? "fire" : "enqueue",
 | 
			
		||||
          operation.constructor.name, operation, msg.maxRetries, msg.timeout);
 | 
			
		||||
      var subscription = createSubscriptionItem(operation, msg.maxRetries, msg.timeout);
 | 
			
		||||
      if (this._state === ConnectionState.Connecting)
 | 
			
		||||
      if (this._state === ConnectionState.Connecting) {
 | 
			
		||||
        this._subscriptions.enqueueSubscription(subscription);
 | 
			
		||||
      else
 | 
			
		||||
      } else {
 | 
			
		||||
        this._subscriptions.startSubscription(subscription, this._connection);
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    case ConnectionState.Closed:
 | 
			
		||||
      msg.cb(new Error("Connection closed. " + this._esConnection.connectionName));
 | 
			
		||||
@@ -391,10 +397,21 @@ EventStoreConnectionLogicHandler.prototype._tcpConnectionEstablished = function(
 | 
			
		||||
  }
 | 
			
		||||
  else
 | 
			
		||||
  {
 | 
			
		||||
    this._goToConnectedState();
 | 
			
		||||
    this._goToIdentifiedState();
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
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() {
 | 
			
		||||
  this._state = ConnectionState.Connected;
 | 
			
		||||
  this._connectingPhase = ConnectingPhase.Connected;
 | 
			
		||||
@@ -498,6 +515,16 @@ EventStoreConnectionLogicHandler.prototype._handleTcpPackage = function(connecti
 | 
			
		||||
      if (pkg.command === TcpCommand.NotAuthenticated)
 | 
			
		||||
        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();
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
@@ -535,8 +562,9 @@ EventStoreConnectionLogicHandler.prototype._handleTcpPackage = function(connecti
 | 
			
		||||
      default:
 | 
			
		||||
        throw new Error("Unknown InspectionDecision: " + result.decision);
 | 
			
		||||
    }
 | 
			
		||||
    if (this._state === ConnectionState.Connected)
 | 
			
		||||
    if (this._state === ConnectionState.Connected) {
 | 
			
		||||
      this._operations.scheduleWaitingOperations(connection);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
@@ -583,8 +611,7 @@ EventStoreConnectionLogicHandler.prototype._reconnectTo = function(endPoints) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (this._state !== ConnectionState.Connected || this._connection.remoteEndPoint === endPoint)
 | 
			
		||||
    return;
 | 
			
		||||
  if (this._state !== ConnectionState.Connected || this._connection.remoteEndPoint === endPoint) return;
 | 
			
		||||
 | 
			
		||||
  var msg = util.format("EventStoreConnection '%s': going to reconnect to [%j]. Current endpoint: [%j, L%j].",
 | 
			
		||||
      this._esConnection.connectionName, endPoint, this._connection.remoteEndPoint, this._connection.localEndPoint);
 | 
			
		||||
@@ -601,26 +628,26 @@ EventStoreConnectionLogicHandler.prototype._timerTick = function() {
 | 
			
		||||
  {
 | 
			
		||||
    case ConnectionState.Init: break;
 | 
			
		||||
    case ConnectionState.Connecting:
 | 
			
		||||
      if (this._connectingPhase === ConnectingPhase.Reconnecting && (Date.now() - this._reconnInfo.timeStamp) >= this._settings.reconnectionDelay)
 | 
			
		||||
      {
 | 
			
		||||
      if (this._connectingPhase === ConnectingPhase.Reconnecting && (Date.now() - this._reconnInfo.timeStamp) >= this._settings.reconnectionDelay) {
 | 
			
		||||
        this._logDebug("TimerTick checking reconnection...");
 | 
			
		||||
 | 
			
		||||
        this._reconnInfo = {reconnectionAttempt: this._reconnInfo.reconnectionAttempt + 1, timeStamp: Date.now()};
 | 
			
		||||
        if (this._settings.maxReconnections >= 0 && this._reconnInfo.reconnectionAttempt > this._settings.maxReconnections)
 | 
			
		||||
        if (this._settings.maxReconnections >= 0 && this._reconnInfo.reconnectionAttempt > this._settings.maxReconnections) {
 | 
			
		||||
          this._closeConnection("Reconnection limit reached.");
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
        } else {
 | 
			
		||||
          this.emit('reconnecting', {});
 | 
			
		||||
          this._discoverEndpoint(null);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      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._goToConnectedState();
 | 
			
		||||
      }
 | 
			
		||||
      else if (this._connectingPhase === ConnectingPhase.Authentication || this._connectingPhase === ConnectingPhase.Connected)
 | 
			
		||||
        if (this._clientVersion === 1) {
 | 
			
		||||
          this._goToIdentifiedState();
 | 
			
		||||
        } else {
 | 
			
		||||
          this._goToConnectedState();
 | 
			
		||||
        }
 | 
			
		||||
      } else if (this._connectingPhase === ConnectingPhase.Authentication || this._connectingPhase === ConnectingPhase.Connected) {
 | 
			
		||||
        this._manageHeartbeats();
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    case ConnectionState.Connected:
 | 
			
		||||
      // operations timeouts are checked only if connection is established and check period time passed
 | 
			
		||||
@@ -647,8 +674,7 @@ EventStoreConnectionLogicHandler.prototype._manageHeartbeats = function() {
 | 
			
		||||
  if (this._connection === null) return;
 | 
			
		||||
 | 
			
		||||
  var timeout = this._heartbeatInfo.isIntervalStage ? this._settings.heartbeatInterval : this._settings.heartbeatTimeout;
 | 
			
		||||
  if ((Date.now() - this._heartbeatInfo.timeStamp) < timeout)
 | 
			
		||||
    return;
 | 
			
		||||
  if ((Date.now() - this._heartbeatInfo.timeStamp) < timeout) return;
 | 
			
		||||
 | 
			
		||||
  var packageNumber = this._packageNumber;
 | 
			
		||||
  if (this._heartbeatInfo.lastPackageNumber !== packageNumber)
 | 
			
		||||
@@ -681,17 +707,19 @@ EventStoreConnectionLogicHandler.prototype._manageHeartbeats = function() {
 | 
			
		||||
EventStoreConnectionLogicHandler.prototype._logDebug = function(message) {
 | 
			
		||||
  if (!this._settings.verboseLogging) return;
 | 
			
		||||
 | 
			
		||||
  if (arguments.length > 1)
 | 
			
		||||
      message = util.format.apply(util, Array.prototype.slice.call(arguments));
 | 
			
		||||
  if (arguments.length > 1) {
 | 
			
		||||
    message = util.format.apply(util, Array.prototype.slice.call(arguments));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  this._settings.log.debug("EventStoreConnection '%s': %s", this._esConnection.connectionName, message);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
EventStoreConnectionLogicHandler.prototype._logInfo = function(message){
 | 
			
		||||
  if (arguments.length > 1)
 | 
			
		||||
  if (arguments.length > 1) {
 | 
			
		||||
    message = util.format.apply(util, Array.prototype.slice.call(arguments));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  this._settings.log.info("EventStoreConnection '%s': %s", this._esConnection.connectionName, message);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports = EventStoreConnectionLogicHandler;
 | 
			
		||||
module.exports = EventStoreConnectionLogicHandler;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,4 @@
 | 
			
		||||
var util = require('util');
 | 
			
		||||
var ensure = require('../common/utils/ensure');
 | 
			
		||||
 | 
			
		||||
function Message() {
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -110,8 +110,7 @@ OperationsManager.prototype.checkTimeoutsAndRetry = function(connection) {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
OperationsManager.prototype.scheduleOperationRetry = function(operation) {
 | 
			
		||||
  if (!this.removeOperation(operation))
 | 
			
		||||
    return;
 | 
			
		||||
  if (!this.removeOperation(operation)) return;
 | 
			
		||||
 | 
			
		||||
  this._logDebug("ScheduleOperationRetry for %s.", operation);
 | 
			
		||||
  if (operation.maxRetries >= 0 && operation.retryCount >= operation.maxRetries)
 | 
			
		||||
@@ -166,10 +165,11 @@ OperationsManager.prototype.scheduleOperation = function(operation, connection)
 | 
			
		||||
OperationsManager.prototype._logDebug = function(message) {
 | 
			
		||||
  if (!this._settings.verboseLogging) return;
 | 
			
		||||
 | 
			
		||||
  if (arguments.length > 1)
 | 
			
		||||
  if (arguments.length > 1) {
 | 
			
		||||
    message = util.format.apply(util, Array.prototype.slice.call(arguments));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  this._settings.log.debug("EventStoreConnection '%s': %s.", this._connectionName, message);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports = OperationsManager;
 | 
			
		||||
module.exports = OperationsManager;
 | 
			
		||||
@@ -1,24 +1,24 @@
 | 
			
		||||
function typeName(t) {
 | 
			
		||||
  if (typeof t === 'function')
 | 
			
		||||
    return t.name;
 | 
			
		||||
  if (typeof t === 'object')
 | 
			
		||||
    return t.constructor.name;
 | 
			
		||||
  if (typeof t === 'function') return t.name;
 | 
			
		||||
  if (typeof t === 'object') return t.constructor.name;
 | 
			
		||||
  throw new TypeError('type must be a function or object, not ' + typeof t);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function SimpleQueuedHandler() {
 | 
			
		||||
function SimpleQueuedHandler(log) {
 | 
			
		||||
  this._handlers = {};
 | 
			
		||||
  this._messages = [];
 | 
			
		||||
  this._isProcessing = false;
 | 
			
		||||
  this._log = log;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SimpleQueuedHandler.prototype.registerHandler = function(type, handler) {
 | 
			
		||||
  var typeId = typeName(type);
 | 
			
		||||
  var log = this._log;
 | 
			
		||||
  this._handlers[typeId] = function (msg) {
 | 
			
		||||
    try {
 | 
			
		||||
      handler(msg);
 | 
			
		||||
    } catch(e) {
 | 
			
		||||
      console.log('ERROR: ', e.stack);
 | 
			
		||||
      log.error('handle for', type, 'failed:', e.stack);
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
@@ -36,12 +36,11 @@ SimpleQueuedHandler.prototype._processQueue = function() {
 | 
			
		||||
  while(message) {
 | 
			
		||||
    var typeId = typeName(message);
 | 
			
		||||
    var handler = this._handlers[typeId];
 | 
			
		||||
    if (!handler)
 | 
			
		||||
        throw new Error("No handler registered for message " + typeId);
 | 
			
		||||
    if (!handler) throw new Error("No handler registered for message " + typeId);
 | 
			
		||||
    setImmediate(handler, message);
 | 
			
		||||
    message = this._messages.shift();
 | 
			
		||||
  }
 | 
			
		||||
  this._isProcessing = false;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports = SimpleQueuedHandler;
 | 
			
		||||
module.exports = SimpleQueuedHandler;
 | 
			
		||||
 
 | 
			
		||||
@@ -7,4 +7,4 @@ function ProjectionCommandFailedError(httpStatusCode, message) {
 | 
			
		||||
}
 | 
			
		||||
util.inherits(ProjectionCommandFailedError, Error);
 | 
			
		||||
 | 
			
		||||
module.exports = ProjectionCommandFailedError;
 | 
			
		||||
module.exports = ProjectionCommandFailedError;
 | 
			
		||||
@@ -1,5 +1,3 @@
 | 
			
		||||
var uuid = require('uuid');
 | 
			
		||||
 | 
			
		||||
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
 | 
			
		||||
function isValidId(id) {
 | 
			
		||||
  if (typeof id !== 'string') return false;
 | 
			
		||||
@@ -26,8 +24,8 @@ function EventData(eventId, type, isJson, data, metadata) {
 | 
			
		||||
  this.eventId = eventId;
 | 
			
		||||
  this.type = type;
 | 
			
		||||
  this.isJson = isJson || false;
 | 
			
		||||
  this.data = data || new Buffer(0);
 | 
			
		||||
  this.metadata = metadata || new Buffer(0);
 | 
			
		||||
  this.data = data || Buffer.alloc(0);
 | 
			
		||||
  this.metadata = metadata || Buffer.alloc(0);
 | 
			
		||||
  Object.freeze(this);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -45,8 +45,7 @@ EventStoreAllCatchUpSubscription.prototype._readEventsTill = function(
 | 
			
		||||
              });
 | 
			
		||||
        })
 | 
			
		||||
        .then(function(done) {
 | 
			
		||||
          if (done || self._shouldStop)
 | 
			
		||||
              return;
 | 
			
		||||
          if (done || self._shouldStop) return;
 | 
			
		||||
          return readNext();
 | 
			
		||||
        });
 | 
			
		||||
  }
 | 
			
		||||
@@ -69,10 +68,11 @@ EventStoreAllCatchUpSubscription.prototype._tryProcess = function(e) {
 | 
			
		||||
    this._lastProcessedPosition = e.originalPosition;
 | 
			
		||||
    processed = true;
 | 
			
		||||
  }
 | 
			
		||||
  if (this._verbose)
 | 
			
		||||
  if (this._verbose) {
 | 
			
		||||
    this._log.debug("Catch-up Subscription to %s: %s event (%s, %d, %s @ %s).",
 | 
			
		||||
        this.streamId || '<all>', processed ? "processed" : "skipping",
 | 
			
		||||
        e.originalEvent.eventStreamId, e.originalEvent.eventNumber, e.originalEvent.eventType, e.originalPosition);
 | 
			
		||||
      this.streamId || '<all>', processed ? "processed" : "skipping",
 | 
			
		||||
      e.originalEvent.eventStreamId, e.originalEvent.eventNumber, e.originalEvent.eventType, e.originalPosition);
 | 
			
		||||
  }
 | 
			
		||||
  return (promise && promise.then) ? promise : Promise.resolve();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,6 @@
 | 
			
		||||
var util = require('util');
 | 
			
		||||
 | 
			
		||||
var SubscriptionDropReason = require('./subscriptionDropReason');
 | 
			
		||||
var results = require('./results');
 | 
			
		||||
 | 
			
		||||
const DefaultReadBatchSize = 500;
 | 
			
		||||
const DefaultMaxPushQueueSize = 10000;
 | 
			
		||||
@@ -68,9 +67,9 @@ function EventStoreCatchUpSubscription(
 | 
			
		||||
 | 
			
		||||
  var self = this;
 | 
			
		||||
  this._onReconnect = function() {
 | 
			
		||||
    if (self._verbose) self._log.debug("Catch-up Subscription to %s: recovering after reconnection.", self._streamId || '<all>');
 | 
			
		||||
    if (self._verbose) self._log.debug("Catch-up Subscription to %s: unhooking from connection.Connected.", self._streamId || '<all>');
 | 
			
		||||
    self._connection.removeListener('connected', self._onReconnect);
 | 
			
		||||
    if (self._verbose) self._log.debug("Catch-up Subscription to %s: recovering after reconnection.", self._streamId || '<all>');
 | 
			
		||||
    self._runSubscription();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -128,15 +127,18 @@ EventStoreCatchUpSubscription.prototype._runSubscription = function() {
 | 
			
		||||
 | 
			
		||||
  var self = this;
 | 
			
		||||
  this._stopped = false;
 | 
			
		||||
  this._isDropped = false;
 | 
			
		||||
  this._dropData = null;
 | 
			
		||||
  if (this._verbose) this._log.debug("Catch-up Subscription to %s: pulling events...", logStreamName);
 | 
			
		||||
  this._readEventsTill(this._connection, this._resolveLinkTos, this._userCredentials, null, null)
 | 
			
		||||
      .then(function() {
 | 
			
		||||
        if (self._shouldStop) return;
 | 
			
		||||
        if (self._verbose) self._log.debug("Catch-up Subscription to %s: subscribing...", logStreamName);
 | 
			
		||||
        if (self._streamId === '')
 | 
			
		||||
        if (self._streamId === '') {
 | 
			
		||||
          return self._connection.subscribeToAll(self._resolveLinkTos, self._enqueuePushedEvent.bind(self), self._serverSubscriptionDropped.bind(self), self._userCredentials);
 | 
			
		||||
        else
 | 
			
		||||
        } else {
 | 
			
		||||
          return self._connection.subscribeToStream(self._streamId, self._resolveLinkTos, self._enqueuePushedEvent.bind(self), self._serverSubscriptionDropped.bind(self), self._userCredentials);
 | 
			
		||||
        }
 | 
			
		||||
      })
 | 
			
		||||
      .then(function(subscription) {
 | 
			
		||||
        if (subscription === undefined) return;
 | 
			
		||||
@@ -155,12 +157,13 @@ EventStoreCatchUpSubscription.prototype._runSubscription = function() {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        if (self._verbose) self._log.debug("Catch-up Subscription to %s: processing live events...", logStreamName);
 | 
			
		||||
        if (self._liveProcessingStarted)
 | 
			
		||||
        if (self._liveProcessingStarted) {
 | 
			
		||||
          try {
 | 
			
		||||
            self._liveProcessingStarted(self);
 | 
			
		||||
          } catch(e) {
 | 
			
		||||
          } catch (e) {
 | 
			
		||||
            self._log.error(e, "Catch-up Subscription to %s: liveProcessingStarted callback failed.", logStreamName);
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        if (self._verbose) self._log.debug("Catch-up Subscription to %s: hooking to connection.Connected", logStreamName);
 | 
			
		||||
        self._connection.on('connected', self._onReconnect);
 | 
			
		||||
        self._allowProcessing = true;
 | 
			
		||||
@@ -169,10 +172,11 @@ EventStoreCatchUpSubscription.prototype._runSubscription = function() {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
EventStoreCatchUpSubscription.prototype._enqueuePushedEvent = function(subscription, e) {
 | 
			
		||||
  if (this._verbose)
 | 
			
		||||
  if (this._verbose) {
 | 
			
		||||
    this._log.debug("Catch-up Subscription to %s: event appeared (%s, %d, %s @ %s).",
 | 
			
		||||
        this._streamId || '<all>',
 | 
			
		||||
        e.originalStreamId, e.originalEventNumber, e.originalEvent.eventType, e.originalPosition);
 | 
			
		||||
      this._streamId || '<all>',
 | 
			
		||||
      e.originalStreamId, e.originalEventNumber, e.originalEvent.eventType, e.originalPosition);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (this._liveQueue.length >= this.maxPushQueueSize)
 | 
			
		||||
  {
 | 
			
		||||
@@ -183,8 +187,7 @@ EventStoreCatchUpSubscription.prototype._enqueuePushedEvent = function(subscript
 | 
			
		||||
 | 
			
		||||
  this._liveQueue.push(e);
 | 
			
		||||
 | 
			
		||||
  if (this._allowProcessing)
 | 
			
		||||
    this._ensureProcessingPushQueue();
 | 
			
		||||
  if (this._allowProcessing) this._ensureProcessingPushQueue();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
EventStoreCatchUpSubscription.prototype._serverSubscriptionDropped = function(subscription, reason, err) {
 | 
			
		||||
@@ -196,8 +199,7 @@ EventStoreCatchUpSubscription.prototype._enqueueSubscriptionDropNotification = f
 | 
			
		||||
  if (this._dropData) return;
 | 
			
		||||
  this._dropData = {reason: reason, error: error};
 | 
			
		||||
  this._liveQueue.push(new DropSubscriptionEvent());
 | 
			
		||||
  if (this._allowProcessing)
 | 
			
		||||
    this._ensureProcessingPushQueue();
 | 
			
		||||
  if (this._allowProcessing) this._ensureProcessingPushQueue();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
EventStoreCatchUpSubscription.prototype._ensureProcessingPushQueue = function() {
 | 
			
		||||
@@ -244,18 +246,19 @@ EventStoreCatchUpSubscription.prototype._dropSubscription = function(reason, err
 | 
			
		||||
  if (this._isDropped) return;
 | 
			
		||||
 | 
			
		||||
  this._isDropped = true;
 | 
			
		||||
  if (this._verbose)
 | 
			
		||||
  if (this._verbose) {
 | 
			
		||||
    this._log.debug("Catch-up Subscription to %s: dropping subscription, reason: %s %s.",
 | 
			
		||||
                    this._streamId || '<all>', reason, error);
 | 
			
		||||
      this._streamId || '<all>', reason, error);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (this._subscription)
 | 
			
		||||
    this._subscription.unsubscribe();
 | 
			
		||||
  if (this._subscriptionDropped)
 | 
			
		||||
  if (this._subscription) this._subscription.unsubscribe();
 | 
			
		||||
  if (this._subscriptionDropped) {
 | 
			
		||||
    try {
 | 
			
		||||
      this._subscriptionDropped(this, reason, error);
 | 
			
		||||
    } catch(e) {
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      this._log.error(e, "Catch-up Subscription to %s: subscriptionDropped callback failed.", this._streamId || '<all>');
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  this._stopped = true;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,21 @@
 | 
			
		||||
var EventStoreNodeConnection = require('./eventStoreNodeConnection');
 | 
			
		||||
var StaticEndpointDiscoverer = require('./core/staticEndpointDiscoverer');
 | 
			
		||||
var ClusterDnsEndPointDiscoverer = require('./core/clusterDnsEndPointDiscoverer');
 | 
			
		||||
var ClusterDiscoverer = require('./core/cluster/clusterDiscoverer');
 | 
			
		||||
var NoopLogger = require('./common/log/noopLogger');
 | 
			
		||||
var ensure = require('./common/utils/ensure');
 | 
			
		||||
 | 
			
		||||
var defaultConnectionSettings = {
 | 
			
		||||
const util = require('util');
 | 
			
		||||
const http = require('http');
 | 
			
		||||
const https = require('https');
 | 
			
		||||
const dns = require('dns');
 | 
			
		||||
 | 
			
		||||
const dnsService = {
 | 
			
		||||
  lookup : util.promisify(dns.lookup),
 | 
			
		||||
  ADDRCONFIG: dns.ADDRCONFIG,
 | 
			
		||||
  V4MAPPED: dns.V4MAPPED
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
var defaultConnectionSettings = Object.freeze({
 | 
			
		||||
  log: new NoopLogger(),
 | 
			
		||||
  verboseLogging: false,
 | 
			
		||||
 | 
			
		||||
@@ -32,9 +43,10 @@ var defaultConnectionSettings = {
 | 
			
		||||
  // Cluster Settings
 | 
			
		||||
  clusterDns: '',
 | 
			
		||||
  maxDiscoverAttempts: 10,
 | 
			
		||||
  discoverDelay: 500,
 | 
			
		||||
  externalGossipPort: 0,
 | 
			
		||||
  gossipTimeout: 1000
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function merge(a,b) {
 | 
			
		||||
@@ -80,17 +92,18 @@ function createFromClusterDns(connectionSettings, clusterDns, externalGossipPort
 | 
			
		||||
  var mergedSettings = merge(defaultConnectionSettings, connectionSettings || {});
 | 
			
		||||
  var clusterSettings = {
 | 
			
		||||
    clusterDns: clusterDns,
 | 
			
		||||
    gossipSeeds: null,
 | 
			
		||||
    externalGossipPort: externalGossipPort,
 | 
			
		||||
    seeds: null,
 | 
			
		||||
    managerExternalHttpPort: externalGossipPort,
 | 
			
		||||
    maxDiscoverAttempts: mergedSettings.maxDiscoverAttempts,
 | 
			
		||||
    gossipTimeout: mergedSettings.gossipTimeout
 | 
			
		||||
    discoverDelay: mergedSettings.discoverDelay,
 | 
			
		||||
    gossipTimeout: mergedSettings.gossipTimeout,
 | 
			
		||||
    rejectUnauthorized: connectionSettings.useSslConnection ? connectionSettings.validateServer : undefined
 | 
			
		||||
  };
 | 
			
		||||
  var endPointDiscoverer = new ClusterDnsEndPointDiscoverer(mergedSettings.log,
 | 
			
		||||
    clusterSettings.clusterDns,
 | 
			
		||||
    clusterSettings.maxDiscoverAttempts,
 | 
			
		||||
    clusterSettings.externalGossipPort,
 | 
			
		||||
    clusterSettings.gossipSeeds,
 | 
			
		||||
    clusterSettings.gossipTimeout
 | 
			
		||||
  var endPointDiscoverer = new ClusterDiscoverer(
 | 
			
		||||
    mergedSettings.log,
 | 
			
		||||
    clusterSettings,
 | 
			
		||||
    dnsService,
 | 
			
		||||
    connectionSettings.useSslConnection ? https : http
 | 
			
		||||
  );
 | 
			
		||||
  return new EventStoreNodeConnection(mergedSettings, clusterSettings, endPointDiscoverer, connectionName);
 | 
			
		||||
}
 | 
			
		||||
@@ -101,17 +114,18 @@ function createFromGossipSeeds(connectionSettings, gossipSeeds, connectionName)
 | 
			
		||||
  var mergedSettings = merge(defaultConnectionSettings, connectionSettings || {});
 | 
			
		||||
  var clusterSettings = {
 | 
			
		||||
    clusterDns: '',
 | 
			
		||||
    gossipSeeds: gossipSeeds,
 | 
			
		||||
    seeds: gossipSeeds,
 | 
			
		||||
    externalGossipPort: 0,
 | 
			
		||||
    maxDiscoverAttempts: mergedSettings.maxDiscoverAttempts,
 | 
			
		||||
    gossipTimeout: mergedSettings.gossipTimeout
 | 
			
		||||
    discoverDelay: mergedSettings.discoverDelay,
 | 
			
		||||
    gossipTimeout: mergedSettings.gossipTimeout,
 | 
			
		||||
    rejectUnauthorized: connectionSettings.useSslConnection ? connectionSettings.validateServer : undefined
 | 
			
		||||
  };
 | 
			
		||||
  var endPointDiscoverer = new ClusterDnsEndPointDiscoverer(mergedSettings.log,
 | 
			
		||||
    clusterSettings.clusterDns,
 | 
			
		||||
    clusterSettings.maxDiscoverAttempts,
 | 
			
		||||
    clusterSettings.externalGossipPort,
 | 
			
		||||
    clusterSettings.gossipSeeds,
 | 
			
		||||
    clusterSettings.gossipTimeout
 | 
			
		||||
  var endPointDiscoverer = new ClusterDiscoverer(
 | 
			
		||||
    mergedSettings.log,
 | 
			
		||||
    clusterSettings,
 | 
			
		||||
    dnsService,
 | 
			
		||||
    connectionSettings.useSslConnection ? https : http
 | 
			
		||||
  );
 | 
			
		||||
  return new EventStoreNodeConnection(mergedSettings, clusterSettings, endPointDiscoverer, connectionName);
 | 
			
		||||
}
 | 
			
		||||
@@ -121,6 +135,27 @@ function createFromGossipSeeds(connectionSettings, gossipSeeds, connectionName)
 | 
			
		||||
 * @public
 | 
			
		||||
 * @alias createConnection
 | 
			
		||||
 * @param {object} settings
 | 
			
		||||
 * @param {boolean} [settings.verboseLogging=false]
 | 
			
		||||
 * @param {number} [settings.maxQueueSize=5000]
 | 
			
		||||
 * @param {number} [settings.maxConcurrentItems=5000]
 | 
			
		||||
 * @param {number} [settings.maxRetries=10]
 | 
			
		||||
 * @param {number} [settings.maxReconnections=10]
 | 
			
		||||
 * @param {boolean} [settings.requireMaster=true]
 | 
			
		||||
 * @param {number} [settings.reconnectionDelay=100]
 | 
			
		||||
 * @param {number} [settings.operationTimeout=7000]
 | 
			
		||||
 * @param {number} [settings.operationTimeoutCheckPeriod=1000]
 | 
			
		||||
 * @param {object} [settings.defaultUserCredentials=null] - The default user credentials to use for requests
 | 
			
		||||
 * @param {boolean} [settings.useSslConnection=false] - Whether to use SSL or not
 | 
			
		||||
 * @param {object} [settings.targetHost=null]
 | 
			
		||||
 * @param {boolean} [settings.validateServer=false]
 | 
			
		||||
 * @param {boolean} [settings.failOnNoServerResponse=false]
 | 
			
		||||
 * @param {number} [settings.heartbeatInterval=750]
 | 
			
		||||
 * @param {number} [settings.heartbeatTimeout=1500]
 | 
			
		||||
 * @param {number} [settings.clientConnectionTimeout=1000]
 | 
			
		||||
 * @param {string} [settings.clusterDns='']
 | 
			
		||||
 * @param {number} [settings.maxDiscoverAttempts=10]
 | 
			
		||||
 * @param {number} [settings.externalGossipPort=0]
 | 
			
		||||
 * @param {number} [settings.gossipTimeout=1000]
 | 
			
		||||
 * @param {string|object|array} endPointOrGossipSeeds
 | 
			
		||||
 * @param {string} [connectionName]
 | 
			
		||||
 * @returns {EventStoreNodeConnection}
 | 
			
		||||
@@ -130,4 +165,4 @@ module.exports.create = function(settings, endPointOrGossipSeeds, connectionName
 | 
			
		||||
  if (typeof endPointOrGossipSeeds === 'object') return createFromTcpEndpoint(settings, endPointOrGossipSeeds, connectionName);
 | 
			
		||||
  if (typeof endPointOrGossipSeeds === 'string') return createFromStringEndpoint(settings, endPointOrGossipSeeds, connectionName);
 | 
			
		||||
  throw new TypeError('endPointOrGossipSeeds must be an object, a string or an array.');
 | 
			
		||||
};
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
var util = require('util');
 | 
			
		||||
var uuid = require('uuid');
 | 
			
		||||
var Long = require('long');
 | 
			
		||||
var EventEmitter = require('events').EventEmitter;
 | 
			
		||||
var ensure = require('./common/utils/ensure');
 | 
			
		||||
 | 
			
		||||
@@ -37,6 +38,7 @@ const MaxReadSize = 4096;
 | 
			
		||||
 * @constructor
 | 
			
		||||
 */
 | 
			
		||||
function EventStoreNodeConnection(settings, clusterSettings, endpointDiscoverer, connectionName) {
 | 
			
		||||
  EventEmitter.call(this);
 | 
			
		||||
  this._connectionName = connectionName || ['ES-', uuid.v4()].join('');
 | 
			
		||||
  this._settings = settings;
 | 
			
		||||
  this._clusterSettings = clusterSettings;
 | 
			
		||||
@@ -100,15 +102,16 @@ EventStoreNodeConnection.prototype.close = function() {
 | 
			
		||||
 * Delete a stream (async)
 | 
			
		||||
 * @public
 | 
			
		||||
 * @param {string} stream
 | 
			
		||||
 * @param {number} expectedVersion
 | 
			
		||||
 * @param {Long|number} expectedVersion
 | 
			
		||||
 * @param {boolean} [hardDelete]
 | 
			
		||||
 * @param {UserCredentials} [userCredentials]
 | 
			
		||||
 * @returns {Promise.<DeleteResult>}
 | 
			
		||||
 */
 | 
			
		||||
EventStoreNodeConnection.prototype.deleteStream = function(stream, expectedVersion, hardDelete, userCredentials) {
 | 
			
		||||
  ensure.notNullOrEmpty(stream, "stream");
 | 
			
		||||
  ensure.isInteger(expectedVersion, "expectedVersion");
 | 
			
		||||
  hardDelete = !!hardDelete;
 | 
			
		||||
  ensure.isLongOrInteger(expectedVersion, "expectedVersion");
 | 
			
		||||
  expectedVersion = Long.fromValue(expectedVersion);
 | 
			
		||||
  hardDelete = Boolean(hardDelete);
 | 
			
		||||
  userCredentials = userCredentials || null;
 | 
			
		||||
 | 
			
		||||
  var self = this;
 | 
			
		||||
@@ -128,16 +131,16 @@ EventStoreNodeConnection.prototype.deleteStream = function(stream, expectedVersi
 | 
			
		||||
 * Append events to a stream (async)
 | 
			
		||||
 * @public
 | 
			
		||||
 * @param {string} stream The name of the stream to which to append.
 | 
			
		||||
 * @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 {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 {EventData[]|EventData} events The event(s) to append.
 | 
			
		||||
 * @param {UserCredentials} [userCredentials] User credentials
 | 
			
		||||
 * @returns {Promise.<WriteResult>}
 | 
			
		||||
 */
 | 
			
		||||
EventStoreNodeConnection.prototype.appendToStream = function(stream, expectedVersion, events, userCredentials) {
 | 
			
		||||
  ensure.notNullOrEmpty(stream, "stream");
 | 
			
		||||
  ensure.isInteger(expectedVersion, "expectedVersion");
 | 
			
		||||
  if (!Array.isArray(events))
 | 
			
		||||
    events = [events];
 | 
			
		||||
  ensure.isLongOrInteger(expectedVersion, "expectedVersion");
 | 
			
		||||
  expectedVersion = Long.fromValue(expectedVersion);
 | 
			
		||||
  if (!Array.isArray(events)) events = [events];
 | 
			
		||||
  ensure.isArrayOf(EventData, events, "events");
 | 
			
		||||
  userCredentials = userCredentials || null;
 | 
			
		||||
 | 
			
		||||
@@ -157,13 +160,14 @@ EventStoreNodeConnection.prototype.appendToStream = function(stream, expectedVer
 | 
			
		||||
 * Start a transaction (async)
 | 
			
		||||
 * @public
 | 
			
		||||
 * @param {string} stream
 | 
			
		||||
 * @param {number} expectedVersion
 | 
			
		||||
 * @param {Long|number} expectedVersion
 | 
			
		||||
 * @param {UserCredentials} [userCredentials]
 | 
			
		||||
 * @returns {Promise.<EventStoreTransaction>}
 | 
			
		||||
 */
 | 
			
		||||
EventStoreNodeConnection.prototype.startTransaction = function(stream, expectedVersion, userCredentials) {
 | 
			
		||||
  ensure.notNullOrEmpty(stream, "stream");
 | 
			
		||||
  ensure.isInteger(expectedVersion, "expectedVersion");
 | 
			
		||||
  ensure.isLongOrInteger(expectedVersion, "expectedVersion");
 | 
			
		||||
  expectedVersion = Long.fromValue(expectedVersion);
 | 
			
		||||
  userCredentials = userCredentials || null;
 | 
			
		||||
 | 
			
		||||
  var self = this;
 | 
			
		||||
@@ -234,21 +238,20 @@ EventStoreNodeConnection.prototype.commitTransaction = function(transaction, use
 | 
			
		||||
 * Read a single event (async)
 | 
			
		||||
 * @public
 | 
			
		||||
 * @param {string} stream
 | 
			
		||||
 * @param {number} eventNumber
 | 
			
		||||
 * @param {Long|number} eventNumber
 | 
			
		||||
 * @param {boolean} [resolveLinkTos]
 | 
			
		||||
 * @param {UserCredentials} [userCredentials]
 | 
			
		||||
 * @returns {Promise.<EventReadResult>}
 | 
			
		||||
 */
 | 
			
		||||
EventStoreNodeConnection.prototype.readEvent = function(stream, eventNumber, resolveLinkTos, userCredentials) {
 | 
			
		||||
  ensure.notNullOrEmpty(stream, "stream");
 | 
			
		||||
  ensure.isInteger(eventNumber, "eventNumber");
 | 
			
		||||
  if (eventNumber < -1) throw new Error("eventNumber out of range.");
 | 
			
		||||
  resolveLinkTos = !!resolveLinkTos;
 | 
			
		||||
  ensure.isLongOrInteger(eventNumber, "eventNumber");
 | 
			
		||||
  eventNumber = Long.fromValue(eventNumber);
 | 
			
		||||
  resolveLinkTos = Boolean(resolveLinkTos);
 | 
			
		||||
  userCredentials = userCredentials || null;
 | 
			
		||||
 | 
			
		||||
  if (typeof stream !== 'string' || stream === '') throw new TypeError("stream must be an non-empty string.");
 | 
			
		||||
  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 (eventNumber.compare(-1) < 0) throw new Error("eventNumber out of range.");
 | 
			
		||||
  if (resolveLinkTos && typeof resolveLinkTos !== 'boolean') throw new TypeError("resolveLinkTos must be a boolean.");
 | 
			
		||||
 | 
			
		||||
  var self = this;
 | 
			
		||||
@@ -267,7 +270,7 @@ EventStoreNodeConnection.prototype.readEvent = function(stream, eventNumber, res
 | 
			
		||||
 * Reading a specific stream forwards (async)
 | 
			
		||||
 * @public
 | 
			
		||||
 * @param {string} stream
 | 
			
		||||
 * @param {number} start
 | 
			
		||||
 * @param {Long|number} start
 | 
			
		||||
 * @param {number} count
 | 
			
		||||
 * @param {boolean} [resolveLinkTos]
 | 
			
		||||
 * @param {UserCredentials} [userCredentials]
 | 
			
		||||
@@ -277,12 +280,13 @@ EventStoreNodeConnection.prototype.readStreamEventsForward = function(
 | 
			
		||||
    stream, start, count, resolveLinkTos, userCredentials
 | 
			
		||||
) {
 | 
			
		||||
  ensure.notNullOrEmpty(stream, "stream");
 | 
			
		||||
  ensure.isInteger(start, "start");
 | 
			
		||||
  ensure.isLongOrInteger(start, "start");
 | 
			
		||||
  start = Long.fromValue(start);
 | 
			
		||||
  ensure.nonNegative(start, "start");
 | 
			
		||||
  ensure.isInteger(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));
 | 
			
		||||
  resolveLinkTos = !!resolveLinkTos;
 | 
			
		||||
  resolveLinkTos = Boolean(resolveLinkTos);
 | 
			
		||||
  userCredentials = userCredentials || null;
 | 
			
		||||
 | 
			
		||||
  var self = this;
 | 
			
		||||
@@ -301,7 +305,7 @@ EventStoreNodeConnection.prototype.readStreamEventsForward = function(
 | 
			
		||||
 * Reading a specific stream backwards (async)
 | 
			
		||||
 * @public
 | 
			
		||||
 * @param {string} stream
 | 
			
		||||
 * @param {number} start
 | 
			
		||||
 * @param {Long|number} start
 | 
			
		||||
 * @param {number} count
 | 
			
		||||
 * @param {boolean} [resolveLinkTos]
 | 
			
		||||
 * @param {UserCredentials} [userCredentials]
 | 
			
		||||
@@ -311,11 +315,12 @@ EventStoreNodeConnection.prototype.readStreamEventsBackward = function(
 | 
			
		||||
    stream, start, count, resolveLinkTos, userCredentials
 | 
			
		||||
) {
 | 
			
		||||
  ensure.notNullOrEmpty(stream, "stream");
 | 
			
		||||
  ensure.isInteger(start, "start");
 | 
			
		||||
  ensure.isLongOrInteger(start, "start");
 | 
			
		||||
  start = Long.fromValue(start);
 | 
			
		||||
  ensure.isInteger(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));
 | 
			
		||||
  resolveLinkTos = !!resolveLinkTos;
 | 
			
		||||
  resolveLinkTos = Boolean(resolveLinkTos);
 | 
			
		||||
  userCredentials = userCredentials || null;
 | 
			
		||||
 | 
			
		||||
  var self = this;
 | 
			
		||||
@@ -346,7 +351,7 @@ EventStoreNodeConnection.prototype.readAllEventsForward = function(
 | 
			
		||||
  ensure.isInteger(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));
 | 
			
		||||
  resolveLinkTos = !!resolveLinkTos;
 | 
			
		||||
  resolveLinkTos = Boolean(resolveLinkTos);
 | 
			
		||||
  userCredentials = userCredentials || null;
 | 
			
		||||
 | 
			
		||||
  var self = this;
 | 
			
		||||
@@ -377,7 +382,7 @@ EventStoreNodeConnection.prototype.readAllEventsBackward = function(
 | 
			
		||||
  ensure.isInteger(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));
 | 
			
		||||
  resolveLinkTos = !!resolveLinkTos;
 | 
			
		||||
  resolveLinkTos = Boolean(resolveLinkTos);
 | 
			
		||||
  userCredentials = userCredentials || null;
 | 
			
		||||
 | 
			
		||||
  var self = this;
 | 
			
		||||
@@ -407,8 +412,7 @@ EventStoreNodeConnection.prototype.subscribeToStream = function(
 | 
			
		||||
) {
 | 
			
		||||
  ensure.notNullOrEmpty(stream, "stream");
 | 
			
		||||
  ensure.isTypeOf(Function, eventAppeared, "eventAppeared");
 | 
			
		||||
  if (subscriptionDropped)
 | 
			
		||||
    ensure.isTypeOf(Function, subscriptionDropped, "subscriptionDropped");
 | 
			
		||||
  if (subscriptionDropped) ensure.isTypeOf(Function, subscriptionDropped, "subscriptionDropped");
 | 
			
		||||
 | 
			
		||||
  var self = this;
 | 
			
		||||
  return new Promise(function(resolve,reject) {
 | 
			
		||||
@@ -427,7 +431,7 @@ EventStoreNodeConnection.prototype.subscribeToStream = function(
 | 
			
		||||
 * Subscribe to a stream from position
 | 
			
		||||
 * @public
 | 
			
		||||
 * @param {!string} stream
 | 
			
		||||
 * @param {?number} lastCheckpoint
 | 
			
		||||
 * @param {?number|Position} lastCheckpoint
 | 
			
		||||
 * @param {!boolean} resolveLinkTos
 | 
			
		||||
 * @param {!function} eventAppeared
 | 
			
		||||
 * @param {function} [liveProcessingStarted]
 | 
			
		||||
@@ -441,7 +445,10 @@ EventStoreNodeConnection.prototype.subscribeToStreamFrom = function(
 | 
			
		||||
    userCredentials, readBatchSize
 | 
			
		||||
) {
 | 
			
		||||
  if (typeof stream !== 'string' || stream === '') throw new TypeError("stream must be a non-empty string.");
 | 
			
		||||
  if (lastCheckpoint !== null && typeof lastCheckpoint !== 'number') throw new TypeError("lastCheckpoint must be a number or null.");
 | 
			
		||||
  if (lastCheckpoint !== null) {
 | 
			
		||||
    ensure.isLongOrInteger(lastCheckpoint);
 | 
			
		||||
    lastCheckpoint = Long.fromValue(lastCheckpoint);
 | 
			
		||||
  }
 | 
			
		||||
  if (typeof eventAppeared !== 'function') throw new TypeError("eventAppeared must be a function.");
 | 
			
		||||
 | 
			
		||||
  var catchUpSubscription =
 | 
			
		||||
@@ -531,7 +538,7 @@ EventStoreNodeConnection.prototype.connectToPersistentSubscription = function(
 | 
			
		||||
  subscriptionDropped = subscriptionDropped || null;
 | 
			
		||||
  userCredentials = userCredentials || null;
 | 
			
		||||
  bufferSize = bufferSize === undefined ? 10 : bufferSize;
 | 
			
		||||
  autoAck = autoAck === undefined ? true : !!autoAck;
 | 
			
		||||
  autoAck = autoAck === undefined ? true : Boolean(autoAck);
 | 
			
		||||
 | 
			
		||||
  var subscription = new EventStorePersistentSubscription(
 | 
			
		||||
      groupName, stream, eventAppeared, subscriptionDropped, userCredentials, this._settings.log,
 | 
			
		||||
@@ -623,7 +630,7 @@ EventStoreNodeConnection.prototype.setStreamMetadata = function() {
 | 
			
		||||
 * Set stream metadata with raw object (async)
 | 
			
		||||
 * @public
 | 
			
		||||
 * @param {string} stream
 | 
			
		||||
 * @param {number} expectedMetastreamVersion
 | 
			
		||||
 * @param {Long|number} expectedMetastreamVersion
 | 
			
		||||
 * @param {object} metadata
 | 
			
		||||
 * @param {UserCredentials} [userCredentials]
 | 
			
		||||
 * @returns {Promise.<WriteResult>}
 | 
			
		||||
@@ -632,15 +639,18 @@ EventStoreNodeConnection.prototype.setStreamMetadataRaw = function(
 | 
			
		||||
    stream, expectedMetastreamVersion, metadata, userCredentials
 | 
			
		||||
) {
 | 
			
		||||
  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));
 | 
			
		||||
  }
 | 
			
		||||
  ensure.isLongOrInteger(expectedMetastreamVersion, "expectedMetastreamVersion");
 | 
			
		||||
  expectedMetastreamVersion = Long.fromValue(expectedMetastreamVersion);
 | 
			
		||||
  var self = this;
 | 
			
		||||
  return new Promise(function(resolve, reject) {
 | 
			
		||||
    function cb(err, result) {
 | 
			
		||||
      if (err) return reject(err);
 | 
			
		||||
      resolve(result);
 | 
			
		||||
    }
 | 
			
		||||
    var data = metadata ? new Buffer(JSON.stringify(metadata)) : null;
 | 
			
		||||
    var data = metadata ? Buffer.from(JSON.stringify(metadata)) : null;
 | 
			
		||||
    var metaevent = new EventData(uuid.v4(), systemEventTypes.StreamMetadata, true, data, null);
 | 
			
		||||
    self._enqueueOperation(
 | 
			
		||||
        new AppendToStreamOperation(self._settings.log, cb, self._settings.requireMaster,
 | 
			
		||||
@@ -676,12 +686,12 @@ EventStoreNodeConnection.prototype.getStreamMetadataRaw = function(stream, userC
 | 
			
		||||
            var evnt = res.event.originalEvent;
 | 
			
		||||
            var version = evnt ? evnt.eventNumber : -1;
 | 
			
		||||
            var data = evnt ? JSON.parse(evnt.data.toString()) : null;
 | 
			
		||||
            return new results.RawStreamMetadataResult(stream, false, version, data);
 | 
			
		||||
            return new results.RawStreamMetadataResult(stream, false, Long.fromValue(version), data);
 | 
			
		||||
          case results.EventReadStatus.NotFound:
 | 
			
		||||
          case results.EventReadStatus.NoStream:
 | 
			
		||||
            return new results.RawStreamMetadataResult(stream, false, -1, null);
 | 
			
		||||
            return new results.RawStreamMetadataResult(stream, false, Long.fromValue(-1), null);
 | 
			
		||||
          case results.EventReadStatus.StreamDeleted:
 | 
			
		||||
            return new results.RawStreamMetadataResult(stream, true, 0x7fffffff, null);
 | 
			
		||||
            return new results.RawStreamMetadataResult(stream, true, Long.fromValue(0x7fffffff), null);
 | 
			
		||||
          default:
 | 
			
		||||
            throw new Error(util.format("Unexpected ReadEventResult: %s.", res.status));
 | 
			
		||||
        }
 | 
			
		||||
@@ -702,7 +712,7 @@ EventStoreNodeConnection.prototype._enqueueOperation = function(operation) {
 | 
			
		||||
  var message = new messages.StartOperationMessage(operation, self._settings.maxRetries, self._settings.operationTimeout);
 | 
			
		||||
  function tryEnqueue() {
 | 
			
		||||
    if (self._handler.totalOperationCount >= self._settings.maxQueueSize) {
 | 
			
		||||
      setImmediate(tryEnqueue);
 | 
			
		||||
      setTimeout(tryEnqueue, 0);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    self._handler.enqueueMessage(message);
 | 
			
		||||
 
 | 
			
		||||
@@ -38,7 +38,7 @@ EventStorePersistentSubscriptionBase.prototype.start = function() {
 | 
			
		||||
  return this._startSubscription(this._subscriptionId, this._streamId, this._bufferSize, this._userCredentials,
 | 
			
		||||
                          this._onEventAppeared.bind(this), this._onSubscriptionDropped.bind(this), this._settings)
 | 
			
		||||
      .then(function(subscription) {
 | 
			
		||||
        console.log('Subscription started.');
 | 
			
		||||
        self._log.debug('Subscription started.');
 | 
			
		||||
        self._subscription = subscription;
 | 
			
		||||
        return self;
 | 
			
		||||
      });
 | 
			
		||||
@@ -56,8 +56,7 @@ EventStorePersistentSubscriptionBase.prototype.acknowledge = function(events) {
 | 
			
		||||
  ensure.notNull(events, "events");
 | 
			
		||||
 | 
			
		||||
  if (this._subscription === null) throw new Error("Invalid operation. Subscription is not active yet.");
 | 
			
		||||
  if (!Array.isArray(events))
 | 
			
		||||
    events = [events];
 | 
			
		||||
  if (!Array.isArray(events)) events = [events];
 | 
			
		||||
  var ids = events.map(function(x) { return x.originalEvent.eventId; });
 | 
			
		||||
  this._subscription.notifyEventsProcessed(ids);
 | 
			
		||||
};
 | 
			
		||||
@@ -73,8 +72,7 @@ EventStorePersistentSubscriptionBase.prototype.fail = function(events, action, r
 | 
			
		||||
  ensure.notNull(reason, "reason");
 | 
			
		||||
 | 
			
		||||
  if (this._subscription === null) throw new Error("Invalid operation. Subscription is not active yet.");
 | 
			
		||||
  if (!Array.isArray(events))
 | 
			
		||||
    events = [events];
 | 
			
		||||
  if (!Array.isArray(events)) events = [events];
 | 
			
		||||
  var ids = events.map(function(x) { return x.originalEvent.eventId; });
 | 
			
		||||
  this._subscription.notifyEventsFailed(ids, action, reason);
 | 
			
		||||
};
 | 
			
		||||
@@ -145,12 +143,12 @@ EventStorePersistentSubscriptionBase.prototype._processQueue = function() {
 | 
			
		||||
    return self._eventAppeared(self, ev);
 | 
			
		||||
  })
 | 
			
		||||
    .then(function() {
 | 
			
		||||
      if(self._autoAck)
 | 
			
		||||
        self._subscription.notifyEventsProcessed([ev.originalEvent.eventId]);
 | 
			
		||||
      if (self._verbose)
 | 
			
		||||
      if(self._autoAck) self._subscription.notifyEventsProcessed([ev.originalEvent.eventId]);
 | 
			
		||||
      if (self._verbose) {
 | 
			
		||||
        self._log.debug("Persistent Subscription to %s: processed event (%s, %d, %s @ %d).",
 | 
			
		||||
          self._streamId, ev.originalEvent.eventStreamId, ev.originalEvent.eventNumber, ev.originalEvent.eventType,
 | 
			
		||||
          ev.originalEventNumber);
 | 
			
		||||
      }
 | 
			
		||||
      return false;
 | 
			
		||||
    }, function(err) {
 | 
			
		||||
      //TODO GFY should we autonak here?
 | 
			
		||||
@@ -168,12 +166,12 @@ EventStorePersistentSubscriptionBase.prototype._dropSubscription = function(reas
 | 
			
		||||
  if (!this._isDropped)
 | 
			
		||||
  {
 | 
			
		||||
    this._isDropped = true;
 | 
			
		||||
    if (this._verbose)
 | 
			
		||||
    if (this._verbose) {
 | 
			
		||||
      this._log.debug("Persistent Subscription to %s: dropping subscription, reason: %s %s.",
 | 
			
		||||
                      this._streamId, reason, error);
 | 
			
		||||
        this._streamId, reason, error);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (this._subscription !== null)
 | 
			
		||||
      this._subscription.unsubscribe();
 | 
			
		||||
    if (this._subscription !== null) this._subscription.unsubscribe();
 | 
			
		||||
    if (this._subscriptionDropped !== null) {
 | 
			
		||||
      try {
 | 
			
		||||
        this._subscriptionDropped(this, reason, error);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
var util = require('util');
 | 
			
		||||
var Long = require('long');
 | 
			
		||||
 | 
			
		||||
var EventStoreCatchUpSubscription = require('./eventStoreCatchUpSubscription');
 | 
			
		||||
var SliceReadStatus = require('./sliceReadStatus');
 | 
			
		||||
@@ -14,8 +15,8 @@ function EventStoreStreamCatchUpSubscription(
 | 
			
		||||
 | 
			
		||||
  //Ensure.NotNullOrEmpty(streamId, "streamId");
 | 
			
		||||
 | 
			
		||||
  this._lastProcessedEventNumber = fromEventNumberExclusive === null ? -1 : fromEventNumberExclusive;
 | 
			
		||||
  this._nextReadEventNumber = fromEventNumberExclusive === null ? 0 : fromEventNumberExclusive + 1;
 | 
			
		||||
  this._lastProcessedEventNumber = fromEventNumberExclusive === null ? Long.fromNumber(-1) : fromEventNumberExclusive;
 | 
			
		||||
  this._nextReadEventNumber = fromEventNumberExclusive === null ? Long.fromNumber(0) : fromEventNumberExclusive.add(1);
 | 
			
		||||
}
 | 
			
		||||
util.inherits(EventStoreStreamCatchUpSubscription, EventStoreCatchUpSubscription);
 | 
			
		||||
 | 
			
		||||
@@ -47,20 +48,19 @@ EventStoreStreamCatchUpSubscription.prototype._readEventsTill = function(
 | 
			
		||||
              return processEvents(slice.events, 0)
 | 
			
		||||
                  .then(function() {
 | 
			
		||||
                    self._nextReadEventNumber = slice.nextEventNumber;
 | 
			
		||||
                    var done = Promise.resolve(lastEventNumber === null ? slice.isEndOfStream : slice.nextEventNumber > lastEventNumber);
 | 
			
		||||
                    if (!done && slice.isEndOfStream)
 | 
			
		||||
                        return delay(100, false);
 | 
			
		||||
                    var done = Promise.resolve(lastEventNumber === null ? slice.isEndOfStream : slice.nextEventNumber.compare(lastEventNumber) > 0);
 | 
			
		||||
                    if (!done && slice.isEndOfStream) return delay(100, false);
 | 
			
		||||
                    return done;
 | 
			
		||||
                  });
 | 
			
		||||
              break;
 | 
			
		||||
            case SliceReadStatus.StreamNotFound:
 | 
			
		||||
              if (lastEventNumber && lastEventNumber !== -1)
 | 
			
		||||
              if (lastEventNumber && lastEventNumber.compare(-1) !== 0) {
 | 
			
		||||
                throw new Error(util.format("Impossible: stream %s disappeared in the middle of catching up subscription.", self.streamId));
 | 
			
		||||
              }
 | 
			
		||||
              return true;
 | 
			
		||||
            case SliceReadStatus.StreamDeleted:
 | 
			
		||||
              throw new Error("Stream deleted: " + self.streamId);
 | 
			
		||||
            default:
 | 
			
		||||
              throw new Error("Unexpected StreamEventsSlice.Status: %s.", slice.status);
 | 
			
		||||
              throw new Error(util.format("Unexpected StreamEventsSlice.Status: %s.", slice.status));
 | 
			
		||||
          }
 | 
			
		||||
        })
 | 
			
		||||
        .then(function(done) {
 | 
			
		||||
@@ -71,26 +71,28 @@ EventStoreStreamCatchUpSubscription.prototype._readEventsTill = function(
 | 
			
		||||
  }
 | 
			
		||||
  return readNext()
 | 
			
		||||
      .then(function() {
 | 
			
		||||
        if (self._verbose)
 | 
			
		||||
        if (self._verbose) {
 | 
			
		||||
          self._log.debug("Catch-up Subscription to %s: finished reading events, nextReadEventNumber = %d.",
 | 
			
		||||
              self.isSubscribedToAll ? '<all>' : self.streamId, self._nextReadEventNumber);
 | 
			
		||||
            self.isSubscribedToAll ? '<all>' : self.streamId, self._nextReadEventNumber);
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
EventStoreStreamCatchUpSubscription.prototype._tryProcess = function(e) {
 | 
			
		||||
  var processed = false;
 | 
			
		||||
  var promise;
 | 
			
		||||
  if (e.originalEventNumber > this._lastProcessedEventNumber) {
 | 
			
		||||
  if (e.originalEventNumber.compare(this._lastProcessedEventNumber) > 0) {
 | 
			
		||||
    promise = this._eventAppeared(this, e);
 | 
			
		||||
    this._lastProcessedEventNumber = e.originalEventNumber;
 | 
			
		||||
    processed = true;
 | 
			
		||||
  }
 | 
			
		||||
  if (this._verbose)
 | 
			
		||||
  if (this._verbose) {
 | 
			
		||||
    this._log.debug("Catch-up Subscription to %s: %s event (%s, %d, %s @ %d).",
 | 
			
		||||
        this.isSubscribedToAll ? '<all>' : this.streamId, processed ? "processed" : "skipping",
 | 
			
		||||
        e.originalEvent.eventStreamId, e.originalEvent.eventNumber, e.originalEvent.eventType, e.originalEventNumber)
 | 
			
		||||
      this.isSubscribedToAll ? '<all>' : this.streamId, processed ? "processed" : "skipping",
 | 
			
		||||
      e.originalEvent.eventStreamId, e.originalEvent.eventNumber, e.originalEvent.eventType, e.originalEventNumber);
 | 
			
		||||
  }
 | 
			
		||||
  return (promise && promise.then) ? promise : Promise.resolve();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
module.exports = EventStoreStreamCatchUpSubscription;
 | 
			
		||||
module.exports = EventStoreStreamCatchUpSubscription;
 | 
			
		||||
@@ -41,4 +41,4 @@ EventStoreSubscription.prototype.unsubscribe = function() {
 | 
			
		||||
  throw new Error("EventStoreSubscription.unsubscribe abstract method called." + this.constructor.name);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports = EventStoreSubscription;
 | 
			
		||||
module.exports = EventStoreSubscription;
 | 
			
		||||
@@ -1,6 +1,9 @@
 | 
			
		||||
module.exports = function GossipSeed(endPoint, hostName) {
 | 
			
		||||
function GossipSeed(endPoint, hostName, hostHeader) {
 | 
			
		||||
  if (typeof endPoint !== 'object' || !endPoint.host || !endPoint.port) throw new TypeError('endPoint must be have host and port properties.');
 | 
			
		||||
  this.endPoint = endPoint;
 | 
			
		||||
  this.hostName = hostName;
 | 
			
		||||
  this.hostHeader = hostHeader;
 | 
			
		||||
  Object.freeze(this);
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = GossipSeed;
 | 
			
		||||
							
								
								
									
										10147
									
								
								src/messages/messages.js
									
									
									
									
									
								
							
							
						
						
									
										10147
									
								
								src/messages/messages.js
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,3 +1,5 @@
 | 
			
		||||
syntax = "proto3";
 | 
			
		||||
 | 
			
		||||
package EventStore.Client.Messages;
 | 
			
		||||
 | 
			
		||||
enum OperationResult
 | 
			
		||||
@@ -13,113 +15,115 @@ enum OperationResult
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message NewEvent {
 | 
			
		||||
	required bytes event_id = 1;
 | 
			
		||||
	required string event_type = 2;
 | 
			
		||||
	required int32 data_content_type = 3;
 | 
			
		||||
	required int32 metadata_content_type = 4;
 | 
			
		||||
	required bytes data = 5;
 | 
			
		||||
	optional bytes metadata = 6;
 | 
			
		||||
	bytes event_id = 1;
 | 
			
		||||
	string event_type = 2;
 | 
			
		||||
	int32 data_content_type = 3;
 | 
			
		||||
	int32 metadata_content_type = 4;
 | 
			
		||||
	bytes data = 5;
 | 
			
		||||
	bytes metadata = 6;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message EventRecord {
 | 
			
		||||
	required string event_stream_id = 1;
 | 
			
		||||
	required int32 event_number = 2;
 | 
			
		||||
	required bytes event_id = 3;
 | 
			
		||||
	required string event_type = 4;
 | 
			
		||||
	required int32 data_content_type = 5;
 | 
			
		||||
	required int32 metadata_content_type = 6;
 | 
			
		||||
	required bytes data = 7;
 | 
			
		||||
	optional bytes metadata = 8;
 | 
			
		||||
	optional int64 created = 9;
 | 
			
		||||
	optional int64 created_epoch = 10;
 | 
			
		||||
	string event_stream_id = 1;
 | 
			
		||||
	int64 event_number = 2;
 | 
			
		||||
	bytes event_id = 3;
 | 
			
		||||
	string event_type = 4;
 | 
			
		||||
	int32 data_content_type = 5;
 | 
			
		||||
	int32 metadata_content_type = 6;
 | 
			
		||||
	bytes data = 7;
 | 
			
		||||
	bytes metadata = 8;
 | 
			
		||||
	int64 created = 9;
 | 
			
		||||
	int64 created_epoch = 10;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message ResolvedIndexedEvent {
 | 
			
		||||
	required EventRecord event = 1;
 | 
			
		||||
	optional EventRecord link = 2;
 | 
			
		||||
	EventRecord event = 1;
 | 
			
		||||
	EventRecord link = 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message ResolvedEvent {
 | 
			
		||||
	required EventRecord event = 1;
 | 
			
		||||
	optional EventRecord link = 2;
 | 
			
		||||
	required int64 commit_position = 3;
 | 
			
		||||
	required int64 prepare_position = 4;
 | 
			
		||||
	EventRecord event = 1;
 | 
			
		||||
	EventRecord link = 2;
 | 
			
		||||
	int64 commit_position = 3;
 | 
			
		||||
	int64 prepare_position = 4;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message WriteEvents {
 | 
			
		||||
	required string event_stream_id = 1;
 | 
			
		||||
	required int32 expected_version = 2;
 | 
			
		||||
	string event_stream_id = 1;
 | 
			
		||||
	int64 expected_version = 2;
 | 
			
		||||
	repeated NewEvent events = 3;
 | 
			
		||||
	required bool require_master = 4;
 | 
			
		||||
	bool require_leader = 4;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message WriteEventsCompleted {
 | 
			
		||||
	required OperationResult result = 1;
 | 
			
		||||
	optional string message = 2;
 | 
			
		||||
	required int32 first_event_number = 3;
 | 
			
		||||
	required int32 last_event_number = 4;
 | 
			
		||||
	optional int64 prepare_position = 5;
 | 
			
		||||
	optional int64 commit_position = 6;
 | 
			
		||||
	OperationResult result = 1;
 | 
			
		||||
	string message = 2;
 | 
			
		||||
	int64 first_event_number = 3;
 | 
			
		||||
	int64 last_event_number = 4;
 | 
			
		||||
	int64 prepare_position = 5;
 | 
			
		||||
	int64 commit_position = 6;
 | 
			
		||||
	int64 current_version  = 7;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message DeleteStream {
 | 
			
		||||
	required string event_stream_id = 1;
 | 
			
		||||
	required int32 expected_version = 2;
 | 
			
		||||
	required bool require_master = 3;
 | 
			
		||||
	optional bool hard_delete = 4;
 | 
			
		||||
	string event_stream_id = 1;
 | 
			
		||||
	int64 expected_version = 2;
 | 
			
		||||
	bool require_leader = 3;
 | 
			
		||||
	bool hard_delete = 4;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message DeleteStreamCompleted {
 | 
			
		||||
	required OperationResult result = 1;
 | 
			
		||||
	optional string message = 2;
 | 
			
		||||
	optional int64 prepare_position = 3;
 | 
			
		||||
	optional int64 commit_position = 4;
 | 
			
		||||
	OperationResult result = 1;
 | 
			
		||||
	string message = 2;
 | 
			
		||||
	int64 prepare_position = 3;
 | 
			
		||||
	int64 commit_position = 4;
 | 
			
		||||
	int64 current_version = 5;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message TransactionStart {
 | 
			
		||||
	required string event_stream_id = 1;
 | 
			
		||||
	required int32 expected_version = 2;
 | 
			
		||||
	required bool require_master = 3;
 | 
			
		||||
	string event_stream_id = 1;
 | 
			
		||||
	int64 expected_version = 2;
 | 
			
		||||
	bool require_leader = 3;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message TransactionStartCompleted {
 | 
			
		||||
	required int64 transaction_id = 1;
 | 
			
		||||
	required OperationResult result = 2;
 | 
			
		||||
	optional string message = 3;
 | 
			
		||||
	int64 transaction_id = 1;
 | 
			
		||||
	OperationResult result = 2;
 | 
			
		||||
	string message = 3;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message TransactionWrite {
 | 
			
		||||
	required int64 transaction_id = 1;
 | 
			
		||||
	int64 transaction_id = 1;
 | 
			
		||||
	repeated NewEvent events = 2;
 | 
			
		||||
	required bool require_master = 3;
 | 
			
		||||
	bool require_leader = 3;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message TransactionWriteCompleted {
 | 
			
		||||
	required int64 transaction_id = 1;
 | 
			
		||||
	required OperationResult result = 2;
 | 
			
		||||
	optional string message = 3;
 | 
			
		||||
	int64 transaction_id = 1;
 | 
			
		||||
	OperationResult result = 2;
 | 
			
		||||
	string message = 3;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message TransactionCommit {
 | 
			
		||||
	required int64 transaction_id = 1;
 | 
			
		||||
	required bool require_master = 2;
 | 
			
		||||
	int64 transaction_id = 1;
 | 
			
		||||
	bool require_leader = 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message TransactionCommitCompleted {
 | 
			
		||||
	required int64 transaction_id = 1;
 | 
			
		||||
	required OperationResult result = 2;
 | 
			
		||||
	optional string message = 3;
 | 
			
		||||
	required int32 first_event_number = 4;
 | 
			
		||||
	required int32 last_event_number = 5;
 | 
			
		||||
	optional int64 prepare_position = 6;
 | 
			
		||||
	optional int64 commit_position = 7;
 | 
			
		||||
	int64 transaction_id = 1;
 | 
			
		||||
	OperationResult result = 2;
 | 
			
		||||
	string message = 3;
 | 
			
		||||
	int64 first_event_number = 4;
 | 
			
		||||
	int64 last_event_number = 5;
 | 
			
		||||
	int64 prepare_position = 6;
 | 
			
		||||
	int64 commit_position = 7;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message ReadEvent {
 | 
			
		||||
	required string event_stream_id = 1;
 | 
			
		||||
	required int32 event_number = 2;
 | 
			
		||||
	required bool resolve_link_tos = 3;
 | 
			
		||||
	required bool require_master = 4;
 | 
			
		||||
	string event_stream_id = 1;
 | 
			
		||||
	int64 event_number = 2;
 | 
			
		||||
	bool resolve_link_tos = 3;
 | 
			
		||||
	bool require_leader = 4;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message ReadEventCompleted {
 | 
			
		||||
@@ -133,18 +137,18 @@ message ReadEventCompleted {
 | 
			
		||||
		AccessDenied = 5;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	required ReadEventResult result = 1;
 | 
			
		||||
	required ResolvedIndexedEvent event = 2;
 | 
			
		||||
	ReadEventResult result = 1;
 | 
			
		||||
	ResolvedIndexedEvent event = 2;
 | 
			
		||||
 | 
			
		||||
	optional string error = 3;
 | 
			
		||||
	string error = 3;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message ReadStreamEvents {
 | 
			
		||||
	required string event_stream_id = 1;
 | 
			
		||||
	required int32 from_event_number = 2;
 | 
			
		||||
	required int32 max_count = 3;
 | 
			
		||||
	required bool resolve_link_tos = 4;
 | 
			
		||||
	required bool require_master = 5;
 | 
			
		||||
	string event_stream_id = 1;
 | 
			
		||||
	int64 from_event_number = 2;
 | 
			
		||||
	int32 max_count = 3;
 | 
			
		||||
	bool resolve_link_tos = 4;
 | 
			
		||||
	bool require_leader = 5;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message ReadStreamEventsCompleted {
 | 
			
		||||
@@ -159,21 +163,21 @@ message ReadStreamEventsCompleted {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	repeated ResolvedIndexedEvent events = 1;
 | 
			
		||||
	required ReadStreamResult result = 2;
 | 
			
		||||
	required int32 next_event_number = 3;
 | 
			
		||||
	required int32 last_event_number = 4;
 | 
			
		||||
	required bool is_end_of_stream = 5;
 | 
			
		||||
	required int64 last_commit_position = 6;
 | 
			
		||||
	ReadStreamResult result = 2;
 | 
			
		||||
	int64 next_event_number = 3;
 | 
			
		||||
	int64 last_event_number = 4;
 | 
			
		||||
	bool is_end_of_stream = 5;
 | 
			
		||||
	int64 last_commit_position = 6;
 | 
			
		||||
 | 
			
		||||
	optional string error = 7;
 | 
			
		||||
	string error = 7;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message ReadAllEvents {
 | 
			
		||||
	required int64 commit_position = 1;
 | 
			
		||||
	required int64 prepare_position = 2;
 | 
			
		||||
	required int32 max_count = 3;
 | 
			
		||||
	required bool resolve_link_tos = 4;
 | 
			
		||||
	required bool require_master = 5;
 | 
			
		||||
	int64 commit_position = 1;
 | 
			
		||||
	int64 prepare_position = 2;
 | 
			
		||||
	int32 max_count = 3;
 | 
			
		||||
	bool resolve_link_tos = 4;
 | 
			
		||||
	bool require_leader = 5;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message ReadAllEventsCompleted {
 | 
			
		||||
@@ -185,57 +189,105 @@ message ReadAllEventsCompleted {
 | 
			
		||||
		AccessDenied = 3;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	required int64 commit_position = 1;
 | 
			
		||||
	required int64 prepare_position = 2;
 | 
			
		||||
	int64 commit_position = 1;
 | 
			
		||||
	int64 prepare_position = 2;
 | 
			
		||||
	repeated ResolvedEvent events = 3;
 | 
			
		||||
	required int64 next_commit_position = 4;
 | 
			
		||||
	required int64 next_prepare_position = 5;
 | 
			
		||||
	int64 next_commit_position = 4;
 | 
			
		||||
	int64 next_prepare_position = 5;
 | 
			
		||||
 | 
			
		||||
	optional ReadAllResult result = 6 [default = Success];
 | 
			
		||||
	optional string error = 7;
 | 
			
		||||
	ReadAllResult result = 6;
 | 
			
		||||
	string error = 7;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message Filter{
 | 
			
		||||
 | 
			
		||||
	enum FilterContext {
 | 
			
		||||
        StreamId = 0;
 | 
			
		||||
		EventType = 1;
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	enum FilterType {
 | 
			
		||||
        Regex = 0;
 | 
			
		||||
		Prefix = 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    FilterContext context = 1;    
 | 
			
		||||
    FilterType type = 2;    
 | 
			
		||||
    repeated string data = 3;    
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message FilteredReadAllEvents {
 | 
			
		||||
    int64 commit_position = 1;
 | 
			
		||||
    int64 prepare_position = 2;
 | 
			
		||||
    int32 max_count = 3;
 | 
			
		||||
    int32 max_search_window = 4;
 | 
			
		||||
    bool resolve_link_tos = 5;
 | 
			
		||||
    bool require_leader = 6;
 | 
			
		||||
    Filter filter = 7;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message FilteredReadAllEventsCompleted {
 | 
			
		||||
 | 
			
		||||
    enum FilteredReadAllResult {
 | 
			
		||||
        Success = 0;
 | 
			
		||||
        NotModified = 1;
 | 
			
		||||
        Error = 2;
 | 
			
		||||
        AccessDenied = 3;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    int64 commit_position = 1;
 | 
			
		||||
    int64 prepare_position = 2;
 | 
			
		||||
    repeated ResolvedEvent events = 3;
 | 
			
		||||
    int64 next_commit_position = 4;
 | 
			
		||||
    int64 next_prepare_position = 5;
 | 
			
		||||
    bool is_end_of_stream = 6;
 | 
			
		||||
 | 
			
		||||
    FilteredReadAllResult result = 7;
 | 
			
		||||
    string error = 8;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message CreatePersistentSubscription {
 | 
			
		||||
	required string subscription_group_name = 1;
 | 
			
		||||
	required string event_stream_id = 2;
 | 
			
		||||
	required bool resolve_link_tos = 3;
 | 
			
		||||
	required int32 start_from = 4;
 | 
			
		||||
	required int32 message_timeout_milliseconds = 5;
 | 
			
		||||
	required bool record_statistics = 6;
 | 
			
		||||
	required int32 live_buffer_size = 7;
 | 
			
		||||
	required int32 read_batch_size = 8;
 | 
			
		||||
	required int32 buffer_size = 9;
 | 
			
		||||
	required int32 max_retry_count = 10;
 | 
			
		||||
	required bool prefer_round_robin = 11;
 | 
			
		||||
	required int32 checkpoint_after_time = 12;
 | 
			
		||||
	required int32 checkpoint_max_count = 13;
 | 
			
		||||
	required int32 checkpoint_min_count = 14;
 | 
			
		||||
	required int32 subscriber_max_count = 15;
 | 
			
		||||
	optional string named_consumer_strategy = 16;
 | 
			
		||||
	string subscription_group_name = 1;
 | 
			
		||||
	string event_stream_id = 2;
 | 
			
		||||
	bool resolve_link_tos = 3;
 | 
			
		||||
	int64 start_from = 4;
 | 
			
		||||
	int32 message_timeout_milliseconds = 5;
 | 
			
		||||
	bool record_statistics = 6;
 | 
			
		||||
	int32 live_buffer_size = 7;
 | 
			
		||||
	int32 read_batch_size = 8;
 | 
			
		||||
	int32 buffer_size = 9;
 | 
			
		||||
	int32 max_retry_count = 10;
 | 
			
		||||
	bool prefer_round_robin = 11;
 | 
			
		||||
	int32 checkpoint_after_time = 12;
 | 
			
		||||
	int32 checkpoint_max_count = 13;
 | 
			
		||||
	int32 checkpoint_min_count = 14;
 | 
			
		||||
	int32 subscriber_max_count = 15;
 | 
			
		||||
	string named_consumer_strategy = 16;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message DeletePersistentSubscription {
 | 
			
		||||
	required string subscription_group_name = 1;
 | 
			
		||||
	required string event_stream_id = 2;
 | 
			
		||||
	string subscription_group_name = 1;
 | 
			
		||||
	string event_stream_id = 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message UpdatePersistentSubscription {
 | 
			
		||||
	required string subscription_group_name = 1;
 | 
			
		||||
	required string event_stream_id = 2;
 | 
			
		||||
	required bool resolve_link_tos = 3;
 | 
			
		||||
	required int32 start_from = 4;
 | 
			
		||||
	required int32 message_timeout_milliseconds = 5;
 | 
			
		||||
	required bool record_statistics = 6;
 | 
			
		||||
	required int32 live_buffer_size = 7;
 | 
			
		||||
	required int32 read_batch_size = 8;
 | 
			
		||||
	required int32 buffer_size = 9;
 | 
			
		||||
	required int32 max_retry_count = 10;
 | 
			
		||||
	required bool prefer_round_robin = 11;
 | 
			
		||||
	required int32 checkpoint_after_time = 12;
 | 
			
		||||
	required int32 checkpoint_max_count = 13;
 | 
			
		||||
	required int32 checkpoint_min_count = 14;
 | 
			
		||||
	required int32 subscriber_max_count = 15;
 | 
			
		||||
	optional string named_consumer_strategy = 16;
 | 
			
		||||
	string subscription_group_name = 1;
 | 
			
		||||
	string event_stream_id = 2;
 | 
			
		||||
	bool resolve_link_tos = 3;
 | 
			
		||||
	int64 start_from = 4;
 | 
			
		||||
	int32 message_timeout_milliseconds = 5;
 | 
			
		||||
	bool record_statistics = 6;
 | 
			
		||||
	int32 live_buffer_size = 7;
 | 
			
		||||
	int32 read_batch_size = 8;
 | 
			
		||||
	int32 buffer_size = 9;
 | 
			
		||||
	int32 max_retry_count = 10;
 | 
			
		||||
	bool prefer_round_robin = 11;
 | 
			
		||||
	int32 checkpoint_after_time = 12;
 | 
			
		||||
	int32 checkpoint_max_count = 13;
 | 
			
		||||
	int32 checkpoint_min_count = 14;
 | 
			
		||||
	int32 subscriber_max_count = 15;
 | 
			
		||||
	string named_consumer_strategy = 16;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message UpdatePersistentSubscriptionCompleted {
 | 
			
		||||
@@ -245,8 +297,8 @@ message UpdatePersistentSubscriptionCompleted {
 | 
			
		||||
		Fail = 2;
 | 
			
		||||
		AccessDenied=3;
 | 
			
		||||
	}
 | 
			
		||||
	required UpdatePersistentSubscriptionResult result = 1 [default = Success];
 | 
			
		||||
	optional string reason = 2;
 | 
			
		||||
	UpdatePersistentSubscriptionResult result = 1;
 | 
			
		||||
	string reason = 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message CreatePersistentSubscriptionCompleted {
 | 
			
		||||
@@ -256,8 +308,8 @@ message CreatePersistentSubscriptionCompleted {
 | 
			
		||||
		Fail = 2;
 | 
			
		||||
		AccessDenied=3;
 | 
			
		||||
	}
 | 
			
		||||
	required CreatePersistentSubscriptionResult result = 1 [default = Success];
 | 
			
		||||
	optional string reason = 2;
 | 
			
		||||
	CreatePersistentSubscriptionResult result = 1;
 | 
			
		||||
	string reason = 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message DeletePersistentSubscriptionCompleted {
 | 
			
		||||
@@ -267,19 +319,19 @@ message DeletePersistentSubscriptionCompleted {
 | 
			
		||||
		Fail = 2;
 | 
			
		||||
		AccessDenied = 3;
 | 
			
		||||
	}
 | 
			
		||||
	required DeletePersistentSubscriptionResult result = 1 [default = Success];
 | 
			
		||||
	optional string reason = 2;
 | 
			
		||||
	DeletePersistentSubscriptionResult result = 1;
 | 
			
		||||
	string reason = 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message ConnectToPersistentSubscription {
 | 
			
		||||
	required string subscription_id = 1;
 | 
			
		||||
	required string event_stream_id = 2;
 | 
			
		||||
	required int32 allowed_in_flight_messages = 3;
 | 
			
		||||
	string subscription_id = 1;
 | 
			
		||||
	string event_stream_id = 2;
 | 
			
		||||
	int32 allowed_in_flight_messages = 3;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message PersistentSubscriptionAckEvents {
 | 
			
		||||
	required string subscription_id = 1;
 | 
			
		||||
	string subscription_id = 1;
 | 
			
		||||
	repeated bytes processed_event_ids = 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -292,34 +344,47 @@ message PersistentSubscriptionNakEvents {
 | 
			
		||||
		Stop = 4;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	required string subscription_id = 1;
 | 
			
		||||
	string subscription_id = 1;
 | 
			
		||||
	repeated bytes processed_event_ids = 2;
 | 
			
		||||
	optional string message = 3;
 | 
			
		||||
	required NakAction action = 4 [default = Unknown];
 | 
			
		||||
	string message = 3;
 | 
			
		||||
	NakAction action = 4;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message PersistentSubscriptionConfirmation {
 | 
			
		||||
	required int64 last_commit_position = 1;
 | 
			
		||||
	required string subscription_id = 2;
 | 
			
		||||
	optional int32 last_event_number = 3;
 | 
			
		||||
	int64 last_commit_position = 1;
 | 
			
		||||
	string subscription_id = 2;
 | 
			
		||||
	int64 last_event_number = 3;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message PersistentSubscriptionStreamEventAppeared {
 | 
			
		||||
	required ResolvedIndexedEvent event = 1;
 | 
			
		||||
	ResolvedIndexedEvent event = 1;
 | 
			
		||||
	int32 retryCount = 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message SubscribeToStream {
 | 
			
		||||
	required string event_stream_id = 1;
 | 
			
		||||
	required bool resolve_link_tos = 2;
 | 
			
		||||
	string event_stream_id = 1;
 | 
			
		||||
	bool resolve_link_tos = 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message FilteredSubscribeToStream {
 | 
			
		||||
	string event_stream_id = 1;
 | 
			
		||||
	bool resolve_link_tos = 2;
 | 
			
		||||
	Filter filter = 3;
 | 
			
		||||
	int32 checkpoint_interval = 4;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message CheckpointReached {
 | 
			
		||||
	int64 commit_position = 1;
 | 
			
		||||
	int64 prepare_position = 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message SubscriptionConfirmation {
 | 
			
		||||
	required int64 last_commit_position = 1;
 | 
			
		||||
	optional int32 last_event_number = 2;
 | 
			
		||||
	int64 last_commit_position = 1;
 | 
			
		||||
	int64 last_event_number = 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message StreamEventAppeared {
 | 
			
		||||
	required ResolvedEvent event = 1;
 | 
			
		||||
	ResolvedEvent event = 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message UnsubscribeFromStream {
 | 
			
		||||
@@ -334,44 +399,52 @@ message SubscriptionDropped {
 | 
			
		||||
		PersistentSubscriptionDeleted=3;
 | 
			
		||||
		SubscriberMaxCountReached=4;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	optional SubscriptionDropReason reason = 1 [default = Unsubscribed];
 | 
			
		||||
	
 | 
			
		||||
	SubscriptionDropReason reason = 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message NotHandled {
 | 
			
		||||
 | 
			
		||||
	
 | 
			
		||||
	enum NotHandledReason {
 | 
			
		||||
		NotReady = 0;
 | 
			
		||||
		TooBusy = 1;
 | 
			
		||||
		NotMaster = 2;
 | 
			
		||||
		NotLeader = 2;
 | 
			
		||||
		IsReadOnly = 3;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	NotHandledReason reason = 1;
 | 
			
		||||
	bytes additional_info = 2;
 | 
			
		||||
 | 
			
		||||
	required NotHandledReason reason = 1;
 | 
			
		||||
	optional bytes additional_info = 2;
 | 
			
		||||
 | 
			
		||||
	message MasterInfo {
 | 
			
		||||
		required string external_tcp_address = 1;
 | 
			
		||||
		required int32 external_tcp_port = 2;
 | 
			
		||||
		required string external_http_address = 3;
 | 
			
		||||
		required int32 external_http_port = 4;
 | 
			
		||||
		optional string external_secure_tcp_address = 5;
 | 
			
		||||
		optional int32 external_secure_tcp_port = 6;
 | 
			
		||||
	message LeaderInfo {
 | 
			
		||||
		string external_tcp_address = 1;
 | 
			
		||||
		int32 external_tcp_port = 2;
 | 
			
		||||
		string http_address = 3;
 | 
			
		||||
		int32 http_port = 4;
 | 
			
		||||
		string external_secure_tcp_address = 5;
 | 
			
		||||
		int32 external_secure_tcp_port = 6;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message ScavengeDatabase {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message ScavengeDatabaseCompleted {
 | 
			
		||||
 | 
			
		||||
message ScavengeDatabaseResponse {
 | 
			
		||||
	
 | 
			
		||||
	enum ScavengeResult {
 | 
			
		||||
		Success = 0;
 | 
			
		||||
		Started = 0;
 | 
			
		||||
		InProgress = 1;
 | 
			
		||||
		Failed = 2;
 | 
			
		||||
		Unauthorized = 2;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	required ScavengeResult result = 1;
 | 
			
		||||
	optional string error = 2;
 | 
			
		||||
	required int32 total_time_ms = 3;
 | 
			
		||||
	required int64 total_space_saved = 4;
 | 
			
		||||
	
 | 
			
		||||
	ScavengeResult result = 1;
 | 
			
		||||
	string scavengeId = 2;
 | 
			
		||||
	
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message IdentifyClient {
 | 
			
		||||
	int32 version = 1;
 | 
			
		||||
	string connection_name = 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
message ClientIdentified {
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -22,4 +22,4 @@ PersistentEventStoreSubscription.prototype.notifyEventsFailed = function(process
 | 
			
		||||
  this._subscriptionOperation.notifyEventsFailed(processedEvents, action, reason);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports = PersistentEventStoreSubscription;
 | 
			
		||||
module.exports = PersistentEventStoreSubscription;
 | 
			
		||||
@@ -1,14 +1,15 @@
 | 
			
		||||
const PersistentSubscriptionNakEventAction = {
 | 
			
		||||
const PersistentSubscriptionNakEventAction = Object.freeze({
 | 
			
		||||
  Unknown: 0,
 | 
			
		||||
  Park: 1,
 | 
			
		||||
  Retry: 2,
 | 
			
		||||
  Skip: 3,
 | 
			
		||||
  Stop: 4
 | 
			
		||||
};
 | 
			
		||||
  Stop: 4,
 | 
			
		||||
  isValid: function(value) {
 | 
			
		||||
    for(var k in PersistentSubscriptionNakEventAction) {
 | 
			
		||||
      if (PersistentSubscriptionNakEventAction[k] === value) return true;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
module.exports = PersistentSubscriptionNakEventAction;
 | 
			
		||||
module.exports.isValid = function(value) {
 | 
			
		||||
  for(var k in PersistentSubscriptionNakEventAction)
 | 
			
		||||
    if (PersistentSubscriptionNakEventAction[k] === value) return true;
 | 
			
		||||
  return false;
 | 
			
		||||
};
 | 
			
		||||
module.exports = PersistentSubscriptionNakEventAction;
 | 
			
		||||
@@ -1,4 +1,6 @@
 | 
			
		||||
var SystemConsumerStrategies = require('./systemConsumerStrategies');
 | 
			
		||||
var ensure = require('./common/utils/ensure');
 | 
			
		||||
var Long = require('long');
 | 
			
		||||
 | 
			
		||||
function PersistentSubscriptionSettings(
 | 
			
		||||
  resolveLinkTos, startFrom, extraStatistics, messageTimeout,
 | 
			
		||||
@@ -6,6 +8,9 @@ function PersistentSubscriptionSettings(
 | 
			
		||||
  checkPointAfter, minCheckPointCount, maxCheckPointCount,
 | 
			
		||||
  maxSubscriberCount, namedConsumerStrategy
 | 
			
		||||
) {
 | 
			
		||||
  ensure.isLongOrInteger(startFrom);
 | 
			
		||||
  startFrom = Long.fromValue(startFrom);
 | 
			
		||||
 | 
			
		||||
  this.resolveLinkTos = resolveLinkTos;
 | 
			
		||||
  this.startFrom = startFrom;
 | 
			
		||||
  this.extraStatistics = extraStatistics;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
const http = require('http');
 | 
			
		||||
const https = require('https');
 | 
			
		||||
const url = require('url');
 | 
			
		||||
const util = require('util');
 | 
			
		||||
const ProjectionCommandFailedError = require('../errors/projectionCommandFailedError');
 | 
			
		||||
@@ -14,9 +15,10 @@ function safeParseJson(json) {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function ProjectionsClient(log, operationTimeout) {
 | 
			
		||||
function ProjectionsClient(log, operationTimeout, rejectUnauthorized) {
 | 
			
		||||
  this._log = log;
 | 
			
		||||
  this._operationTimeout = operationTimeout;
 | 
			
		||||
  this._rejectUnauthorized = typeof rejectUnauthorized === 'undefined' ? true : !!rejectUnauthorized;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ProjectionsClient.prototype.enable = function(httpEndPoint, name, userCredentials) {
 | 
			
		||||
@@ -31,6 +33,10 @@ ProjectionsClient.prototype.abort = function(httpEndPoint, name, userCredentials
 | 
			
		||||
  return this.sendPost(httpEndPoint + '/projection/' + name + '/command/abort', '', userCredentials, HTTP_OK);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
ProjectionsClient.prototype.reset = function(httpEndPoint, name, userCredentials) {
 | 
			
		||||
  return this.sendPost(httpEndPoint + '/projection/' + name + '/command/reset', '', userCredentials, HTTP_OK);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
ProjectionsClient.prototype.createOneTime = function(httpEndPoint, query, userCredentials) {
 | 
			
		||||
  return this.sendPost(httpEndPoint + '/projections/onetime?type=JS', query, userCredentials, HTTP_CREATED);
 | 
			
		||||
};
 | 
			
		||||
@@ -40,7 +46,7 @@ ProjectionsClient.prototype.createTransient = function(httpEndPoint, name, query
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
ProjectionsClient.prototype.createContinuous = function(httpEndPoint, name, query, trackEmittedStreams, userCredentials) {
 | 
			
		||||
  return this.sendPost(httpEndPoint + '/projections/continuous?name=' + name + '&type=JS&emit=1&trackEmittedStreams=' + trackEmittedStreams, query, userCredentials, HTTP_CREATED);
 | 
			
		||||
  return this.sendPost(httpEndPoint + '/projections/continuous?name=' + name + '&type=JS&emit=1&trackemittedstreams=' + trackEmittedStreams, query, userCredentials, HTTP_CREATED);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
ProjectionsClient.prototype.listAll = function(httpEndPoint, userCredentials) {
 | 
			
		||||
@@ -102,22 +108,26 @@ ProjectionsClient.prototype.updateQuery = function(httpEndPoint, name, query, us
 | 
			
		||||
  return this.sendPut(httpEndPoint + '/projection/' + name + '/query?type=JS', query, userCredentials, HTTP_OK);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
ProjectionsClient.prototype.delete = function(httpEndPoint, name, deleteEmittedStreams, userCredentials) {
 | 
			
		||||
  return this.sendDelete(httpEndPoint + '/projection/' + name + '?deleteEmittedStreams=' + deleteEmittedStreams, userCredentials, HTTP_OK);
 | 
			
		||||
ProjectionsClient.prototype.delete = function(httpEndPoint, name, deleteEmittedStreams, deleteStateStream, deleteCheckpointStream, userCredentials) {
 | 
			
		||||
  return this.sendDelete(httpEndPoint + '/projection/' + name + '?deleteStateStream=' + deleteStateStream + '&deleteCheckpointStream=' + deleteCheckpointStream + '&deleteEmittedStreams=' + deleteEmittedStreams, '', userCredentials, HTTP_OK);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
ProjectionsClient.prototype.request = function(method, _url, data, userCredentials, expectedCode) {
 | 
			
		||||
  const options = url.parse(_url);
 | 
			
		||||
  const httplib = options.protocol === 'https:' ? https : http;
 | 
			
		||||
  options.method = method;
 | 
			
		||||
  if (userCredentials) {
 | 
			
		||||
    options.auth = [userCredentials.username, userCredentials.password].join(':');
 | 
			
		||||
  }
 | 
			
		||||
  if (!this._rejectUnauthorized) {
 | 
			
		||||
    options.rejectUnauthorized = false;
 | 
			
		||||
  }
 | 
			
		||||
  var self = this;
 | 
			
		||||
  return new Promise(function (resolve, reject) {
 | 
			
		||||
    const timeout = setTimeout(function () {
 | 
			
		||||
      reject(new Error(util.format('Request timed out for %s on %s', method, _url)))
 | 
			
		||||
    }, self._operationTimeout);
 | 
			
		||||
    const req = http.request(options, function (res) {
 | 
			
		||||
    const req = httplib.request(options, function (res) {
 | 
			
		||||
      const hasExpectedCode = res.statusCode === expectedCode;
 | 
			
		||||
      var result = '';
 | 
			
		||||
      res.setEncoding('utf8');
 | 
			
		||||
@@ -139,6 +149,7 @@ ProjectionsClient.prototype.request = function(method, _url, data, userCredentia
 | 
			
		||||
    });
 | 
			
		||||
    req.on('error', reject);
 | 
			
		||||
    if (data) {
 | 
			
		||||
      req.setHeader('Content-Length', data.length);
 | 
			
		||||
      req.setHeader('Content-Type', 'application/json');
 | 
			
		||||
      req.write(data);
 | 
			
		||||
    }
 | 
			
		||||
@@ -167,4 +178,4 @@ ProjectionsClient.prototype.sendDelete = function(_url, data, userCredentials, e
 | 
			
		||||
    .then(voidResult);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports = ProjectionsClient;
 | 
			
		||||
module.exports = ProjectionsClient;
 | 
			
		||||
 
 | 
			
		||||
@@ -6,12 +6,13 @@ const ProjectionsClient = require('./projectionsClient');
 | 
			
		||||
 * @param {Logger} log              Instance of Logger to use for logging.
 | 
			
		||||
 * @param {string} httpEndPoint     HTTP endpoint of an Event Store server.
 | 
			
		||||
 * @param {number} operationTimeout Operation timeout in milliseconds.
 | 
			
		||||
 * @param {boolean} [rejectUnauthorized] Reject authorized SSL certs (if using SSL) - set to false is using self-signed certs
 | 
			
		||||
 * @constructor
 | 
			
		||||
 */
 | 
			
		||||
function ProjectionsManager(log, httpEndPoint, operationTimeout) {
 | 
			
		||||
function ProjectionsManager(log, httpEndPoint, operationTimeout, rejectUnauthorized) {
 | 
			
		||||
  ensure.notNull(log, "log");
 | 
			
		||||
  ensure.notNull(httpEndPoint, "httpEndPoint");
 | 
			
		||||
  this._client = new ProjectionsClient(log, operationTimeout);
 | 
			
		||||
  this._client = new ProjectionsClient(log, operationTimeout, rejectUnauthorized);
 | 
			
		||||
  this._httpEndPoint = httpEndPoint;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -45,6 +46,16 @@ ProjectionsManager.prototype.abort = function(name, userCredentials) {
 | 
			
		||||
  return this._client.abort(this._httpEndPoint, name, userCredentials);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Reset a projection. (This will re-emit events, streams that are written to from the projection will also be soft deleted)
 | 
			
		||||
 * @param name            The name of the projection.
 | 
			
		||||
 * @param userCredentials Credentials for a user with permission to reset a projection.
 | 
			
		||||
 * @returns {Promise<void>}
 | 
			
		||||
 */
 | 
			
		||||
ProjectionsManager.prototype.reset = function(name, userCredentials) {
 | 
			
		||||
  return this._client.reset(this._httpEndPoint, name, userCredentials);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Creates a one-time query.
 | 
			
		||||
 * @param query           The JavaScript source code for the query.
 | 
			
		||||
@@ -190,13 +201,15 @@ ProjectionsManager.prototype.updateQuery = function(name, query, userCredentials
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Updates the definition of a query.
 | 
			
		||||
 * @param name                  The name of the projection.
 | 
			
		||||
 * @param deleteEmittedStreams  Whether to delete the streams that were emitted by this projection.
 | 
			
		||||
 * @param userCredentials       Credentials for a user with permission to delete a projection.
 | 
			
		||||
 * @param name                    The name of the projection.
 | 
			
		||||
 * @param deleteEmittedStreams    Whether to delete the streams that were emitted by this projection.
 | 
			
		||||
 * @param deleteStateStream       Where to delete the state stream for this projection
 | 
			
		||||
 * @param deleteCheckpointStream  Where to delete the checkpoint stream for this projection
 | 
			
		||||
 * @param userCredentials         Credentials for a user with permission to delete a projection.
 | 
			
		||||
 * @returns {Promise<void>}
 | 
			
		||||
 */
 | 
			
		||||
ProjectionsManager.prototype.delete = function(name, deleteEmittedStreams, userCredentials) {
 | 
			
		||||
  return this._client.delete(this._httpEndPoint, name, deleteEmittedStreams, userCredentials);
 | 
			
		||||
ProjectionsManager.prototype.delete = function(name, deleteEmittedStreams, deleteStateStream, deleteCheckpointStream, userCredentials) {
 | 
			
		||||
  return this._client.delete(this._httpEndPoint, name, deleteEmittedStreams, deleteStateStream, deleteCheckpointStream, userCredentials);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports = ProjectionsManager;
 | 
			
		||||
module.exports = ProjectionsManager;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
const ReadDirection = {
 | 
			
		||||
const ReadDirection = Object.freeze({
 | 
			
		||||
  Forward: 'forward',
 | 
			
		||||
  Backward: 'backward'
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
module.exports = ReadDirection;
 | 
			
		||||
module.exports = ReadDirection;
 | 
			
		||||
@@ -19,10 +19,12 @@ function Position(commitPosition, preparePosition) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Position.prototype.compareTo = function(other) {
 | 
			
		||||
  if (this.commitPosition.lt(other.commitPosition) || (this.commitPosition.eq(other.commitPosition)&& this.preparePosition.lt(other.preparePosition)))
 | 
			
		||||
  if (this.commitPosition.lt(other.commitPosition) || (this.commitPosition.eq(other.commitPosition)&& this.preparePosition.lt(other.preparePosition))) {
 | 
			
		||||
    return -1;
 | 
			
		||||
  if (this.commitPosition.gt(other.commitPosition) || (this.commitPosition.eq(other.commitPosition) && this.preparePosition.gt(other.preparePosition)))
 | 
			
		||||
  }
 | 
			
		||||
  if (this.commitPosition.gt(other.commitPosition) || (this.commitPosition.eq(other.commitPosition) && this.preparePosition.gt(other.preparePosition))) {
 | 
			
		||||
    return 1;
 | 
			
		||||
  }
 | 
			
		||||
  return 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -30,22 +32,24 @@ Position.prototype.toString = function() {
 | 
			
		||||
  return [this.commitPosition.toString(), this.preparePosition.toString()].join("/");
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Position.start = new Position(0,0);
 | 
			
		||||
Position.end = new Position(-1,-1);
 | 
			
		||||
 | 
			
		||||
const EventReadStatus = {
 | 
			
		||||
const EventReadStatus = Object.freeze({
 | 
			
		||||
  Success: 'success',
 | 
			
		||||
  NotFound: 'notFound',
 | 
			
		||||
  NoStream: 'noStream',
 | 
			
		||||
  StreamDeleted: 'streamDeleted'
 | 
			
		||||
};
 | 
			
		||||
Object.freeze(EventReadStatus);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @param {object} ev
 | 
			
		||||
 * @constructor
 | 
			
		||||
 * @property {string} eventStreamId
 | 
			
		||||
 * @property {string} eventId
 | 
			
		||||
 * @property {number} eventNumber
 | 
			
		||||
 * @property {Long} eventNumber
 | 
			
		||||
 * @property {string} eventType
 | 
			
		||||
 * @property {Date} created
 | 
			
		||||
 * @property {number} createdEpoch
 | 
			
		||||
 * @property {?Buffer} data
 | 
			
		||||
 * @property {?Buffer} metadata
 | 
			
		||||
@@ -58,8 +62,8 @@ function RecordedEvent(ev) {
 | 
			
		||||
  this.eventType = ev.eventType;
 | 
			
		||||
  this.created = new Date(ev.createdEpoch ? ev.createdEpoch.toNumber() : 0);
 | 
			
		||||
  this.createdEpoch = ev.createdEpoch ? ev.createdEpoch.toNumber() : 0;
 | 
			
		||||
  this.data = ev.data ? ev.data : new Buffer(0);
 | 
			
		||||
  this.metadata = ev.metadata ? ev.metadata : new Buffer(0);
 | 
			
		||||
  this.data = ev.data ? ev.data : Buffer.alloc(0);
 | 
			
		||||
  this.metadata = ev.metadata ? ev.metadata : Buffer.alloc(0);
 | 
			
		||||
  this.isJson = ev.dataContentType === 1;
 | 
			
		||||
  Object.freeze(this);
 | 
			
		||||
}
 | 
			
		||||
@@ -73,7 +77,7 @@ function RecordedEvent(ev) {
 | 
			
		||||
 * @property {boolean} isResolved
 | 
			
		||||
 * @property {?Position} originalPosition
 | 
			
		||||
 * @property {string} originalStreamId
 | 
			
		||||
 * @property {number} originalEventNumber
 | 
			
		||||
 * @property {Long} originalEventNumber
 | 
			
		||||
 */
 | 
			
		||||
function ResolvedEvent(ev) {
 | 
			
		||||
  this.event = ev.event === null ? null : new RecordedEvent(ev.event);
 | 
			
		||||
@@ -90,12 +94,12 @@ function ResolvedEvent(ev) {
 | 
			
		||||
 *
 | 
			
		||||
 * @param {string} status
 | 
			
		||||
 * @param {string} stream
 | 
			
		||||
 * @param {number} eventNumber
 | 
			
		||||
 * @param {Long} eventNumber
 | 
			
		||||
 * @param {object} event
 | 
			
		||||
 * @constructor
 | 
			
		||||
 * @property {string} status
 | 
			
		||||
 * @property {string} stream
 | 
			
		||||
 * @property {number} eventNumber
 | 
			
		||||
 * @property {Long} eventNumber
 | 
			
		||||
 * @property {ResolvedEvent} event
 | 
			
		||||
 */
 | 
			
		||||
function EventReadResult(status, stream, eventNumber, event) {
 | 
			
		||||
@@ -110,7 +114,7 @@ function EventReadResult(status, stream, eventNumber, event) {
 | 
			
		||||
 * @param {number} nextExpectedVersion
 | 
			
		||||
 * @param {Position} logPosition
 | 
			
		||||
 * @constructor
 | 
			
		||||
 * @property {number} nextExpectedVersion
 | 
			
		||||
 * @property {Long} nextExpectedVersion
 | 
			
		||||
 * @property {Position} logPosition
 | 
			
		||||
 */
 | 
			
		||||
function WriteResult(nextExpectedVersion, logPosition) {
 | 
			
		||||
@@ -122,20 +126,20 @@ function WriteResult(nextExpectedVersion, logPosition) {
 | 
			
		||||
/**
 | 
			
		||||
 * @param {string} status
 | 
			
		||||
 * @param {string} stream
 | 
			
		||||
 * @param {number} fromEventNumber
 | 
			
		||||
 * @param {Long} fromEventNumber
 | 
			
		||||
 * @param {string} readDirection
 | 
			
		||||
 * @param {object[]} events
 | 
			
		||||
 * @param {number} nextEventNumber
 | 
			
		||||
 * @param {number} lastEventNumber
 | 
			
		||||
 * @param {Long} nextEventNumber
 | 
			
		||||
 * @param {Long} lastEventNumber
 | 
			
		||||
 * @param {boolean} isEndOfStream
 | 
			
		||||
 * @constructor
 | 
			
		||||
 * @property {string} status
 | 
			
		||||
 * @property {string} stream
 | 
			
		||||
 * @property {number} fromEventNumber
 | 
			
		||||
 * @property {Long} fromEventNumber
 | 
			
		||||
 * @property {string} readDirection
 | 
			
		||||
 * @property {ResolvedEvent[]} events
 | 
			
		||||
 * @property {number} nextEventNumber
 | 
			
		||||
 * @property {number} lastEventNumber
 | 
			
		||||
 * @property {Long} nextEventNumber
 | 
			
		||||
 * @property {Long} lastEventNumber
 | 
			
		||||
 * @property {boolean} isEndOfStream
 | 
			
		||||
 */
 | 
			
		||||
function StreamEventsSlice(
 | 
			
		||||
@@ -185,12 +189,12 @@ function DeleteResult(logPosition) {
 | 
			
		||||
/**
 | 
			
		||||
 * @param {string} stream
 | 
			
		||||
 * @param {boolean} isStreamDeleted
 | 
			
		||||
 * @param {number} metastreamVersion
 | 
			
		||||
 * @param {Long} metastreamVersion
 | 
			
		||||
 * @param {object} streamMetadata
 | 
			
		||||
 * @constructor
 | 
			
		||||
 * @property {string} stream
 | 
			
		||||
 * @property {boolean} isStreamDeleted
 | 
			
		||||
 * @property {number} metastreamVersion
 | 
			
		||||
 * @property {Long} metastreamVersion
 | 
			
		||||
 * @property {object} streamMetadata
 | 
			
		||||
 */
 | 
			
		||||
function RawStreamMetadataResult(stream, isStreamDeleted, metastreamVersion, streamMetadata) {
 | 
			
		||||
@@ -202,12 +206,11 @@ function RawStreamMetadataResult(stream, isStreamDeleted, metastreamVersion, str
 | 
			
		||||
  Object.freeze(this);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const PersistentSubscriptionCreateStatus = {
 | 
			
		||||
const PersistentSubscriptionCreateStatus = Object.freeze({
 | 
			
		||||
  Success: 'success',
 | 
			
		||||
  NotFound: 'notFound',
 | 
			
		||||
  Failure: 'failure'
 | 
			
		||||
};
 | 
			
		||||
Object.freeze(PersistentSubscriptionCreateStatus);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @param {string} status
 | 
			
		||||
@@ -219,13 +222,12 @@ function PersistentSubscriptionCreateResult(status) {
 | 
			
		||||
  Object.freeze(this);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const PersistentSubscriptionUpdateStatus = {
 | 
			
		||||
const PersistentSubscriptionUpdateStatus = Object.freeze({
 | 
			
		||||
  Success: 'success',
 | 
			
		||||
  NotFound: 'notFound',
 | 
			
		||||
  Failure: 'failure',
 | 
			
		||||
  AccessDenied: 'accessDenied'
 | 
			
		||||
};
 | 
			
		||||
Object.freeze(PersistentSubscriptionUpdateStatus);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @param {string} status
 | 
			
		||||
@@ -237,11 +239,10 @@ function PersistentSubscriptionUpdateResult(status) {
 | 
			
		||||
  Object.freeze(this);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const PersistentSubscriptionDeleteStatus = {
 | 
			
		||||
const PersistentSubscriptionDeleteStatus = Object.freeze({
 | 
			
		||||
  Success: 'success',
 | 
			
		||||
  Failure: 'failure'
 | 
			
		||||
};
 | 
			
		||||
Object.freeze(PersistentSubscriptionDeleteStatus);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @param {string} status
 | 
			
		||||
@@ -254,18 +255,18 @@ function PersistentSubscriptionDeleteResult(status) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Exports Constructors
 | 
			
		||||
module.exports.Position = Position;
 | 
			
		||||
module.exports.ResolvedEvent = ResolvedEvent;
 | 
			
		||||
module.exports.EventReadStatus = EventReadStatus;
 | 
			
		||||
module.exports.EventReadResult = EventReadResult;
 | 
			
		||||
module.exports.WriteResult = WriteResult;
 | 
			
		||||
module.exports.StreamEventsSlice = StreamEventsSlice;
 | 
			
		||||
module.exports.AllEventsSlice = AllEventsSlice;
 | 
			
		||||
module.exports.DeleteResult = DeleteResult;
 | 
			
		||||
module.exports.RawStreamMetadataResult = RawStreamMetadataResult;
 | 
			
		||||
module.exports.PersistentSubscriptionCreateResult = PersistentSubscriptionCreateResult;
 | 
			
		||||
module.exports.PersistentSubscriptionCreateStatus = PersistentSubscriptionCreateStatus;
 | 
			
		||||
module.exports.PersistentSubscriptionUpdateResult = PersistentSubscriptionUpdateResult;
 | 
			
		||||
module.exports.PersistentSubscriptionUpdateStatus = PersistentSubscriptionUpdateStatus;
 | 
			
		||||
module.exports.PersistentSubscriptionDeleteResult = PersistentSubscriptionDeleteResult;
 | 
			
		||||
module.exports.PersistentSubscriptionDeleteStatus = PersistentSubscriptionDeleteStatus;
 | 
			
		||||
exports.Position = Position;
 | 
			
		||||
exports.ResolvedEvent = ResolvedEvent;
 | 
			
		||||
exports.EventReadStatus = EventReadStatus;
 | 
			
		||||
exports.EventReadResult = EventReadResult;
 | 
			
		||||
exports.WriteResult = WriteResult;
 | 
			
		||||
exports.StreamEventsSlice = StreamEventsSlice;
 | 
			
		||||
exports.AllEventsSlice = AllEventsSlice;
 | 
			
		||||
exports.DeleteResult = DeleteResult;
 | 
			
		||||
exports.RawStreamMetadataResult = RawStreamMetadataResult;
 | 
			
		||||
exports.PersistentSubscriptionCreateResult = PersistentSubscriptionCreateResult;
 | 
			
		||||
exports.PersistentSubscriptionCreateStatus = PersistentSubscriptionCreateStatus;
 | 
			
		||||
exports.PersistentSubscriptionUpdateResult = PersistentSubscriptionUpdateResult;
 | 
			
		||||
exports.PersistentSubscriptionUpdateStatus = PersistentSubscriptionUpdateStatus;
 | 
			
		||||
exports.PersistentSubscriptionDeleteResult = PersistentSubscriptionDeleteResult;
 | 
			
		||||
exports.PersistentSubscriptionDeleteStatus = PersistentSubscriptionDeleteStatus;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,7 @@
 | 
			
		||||
const SliceReadStatus = {
 | 
			
		||||
const SliceReadStatus = Object.freeze({
 | 
			
		||||
  Success: 'success',
 | 
			
		||||
  StreamNotFound: 'streamNotFound',
 | 
			
		||||
  StreamDeleted: 'streamDeleted'
 | 
			
		||||
};
 | 
			
		||||
Object.freeze(SliceReadStatus);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
module.exports = SliceReadStatus;
 | 
			
		||||
module.exports = SliceReadStatus;
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
const SubscriptionDropReason = {
 | 
			
		||||
const SubscriptionDropReason = Object.freeze({
 | 
			
		||||
  AccessDenied: 'accessDenied',
 | 
			
		||||
  CatchUpError: 'catchUpError',
 | 
			
		||||
  ConnectionClosed: 'connectionClosed',
 | 
			
		||||
@@ -11,6 +11,6 @@ const SubscriptionDropReason = {
 | 
			
		||||
  SubscribingError: 'subscribingError',
 | 
			
		||||
  UserInitiated: 'userInitiated',
 | 
			
		||||
  Unknown: 'unknown'
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
module.exports = SubscriptionDropReason;
 | 
			
		||||
@@ -1,8 +1,7 @@
 | 
			
		||||
const SystemConsumerStrategies = {
 | 
			
		||||
const SystemConsumerStrategies = Object.freeze({
 | 
			
		||||
  DispatchToSingle: 'DispatchToSingle',
 | 
			
		||||
  RoundRobin: 'RoundRobin',
 | 
			
		||||
  Pinned: 'Pinned'
 | 
			
		||||
};
 | 
			
		||||
Object.freeze(SystemConsumerStrategies);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
module.exports = SystemConsumerStrategies;
 | 
			
		||||
module.exports = SystemConsumerStrategies;
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
var InspectionDecision = {
 | 
			
		||||
var InspectionDecision = Object.freeze({
 | 
			
		||||
  DoNothing: 'doNothing',
 | 
			
		||||
  EndOperation: 'endOperation',
 | 
			
		||||
  Retry: 'retry',
 | 
			
		||||
  Reconnect: 'reconnect',
 | 
			
		||||
  Subscribed: 'subscribed'
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
module.exports = InspectionDecision;
 | 
			
		||||
@@ -5,4 +5,4 @@ function InspectionResult(decision, description, tcpEndPoint, secureTcpEndPoint)
 | 
			
		||||
  this.secureTcpEndPoint = secureTcpEndPoint || null;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = InspectionResult;
 | 
			
		||||
module.exports = InspectionResult;
 | 
			
		||||
@@ -1,9 +1,7 @@
 | 
			
		||||
var ClientMessage = require('../messages/clientMessage');
 | 
			
		||||
var SliceReadStatus = require('../sliceReadStatus');
 | 
			
		||||
 | 
			
		||||
module.exports = {};
 | 
			
		||||
 | 
			
		||||
module.exports.convert = function(code) {
 | 
			
		||||
exports.convert = function(code) {
 | 
			
		||||
  switch(code) {
 | 
			
		||||
    case ClientMessage.ReadStreamEventsCompleted.ReadStreamResult.Success:
 | 
			
		||||
      return SliceReadStatus.Success;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
const TcpCommand = {
 | 
			
		||||
const TcpCommand = Object.freeze({
 | 
			
		||||
  HeartbeatRequestCommand: 0x01,
 | 
			
		||||
  HeartbeatResponseCommand: 0x02,
 | 
			
		||||
 | 
			
		||||
@@ -71,16 +71,20 @@ const TcpCommand = {
 | 
			
		||||
  NotHandled: 0xF1,
 | 
			
		||||
  Authenticate: 0xF2,
 | 
			
		||||
  Authenticated: 0xF3,
 | 
			
		||||
  NotAuthenticated: 0xF4
 | 
			
		||||
};
 | 
			
		||||
  NotAuthenticated: 0xF4,
 | 
			
		||||
  IdentifyClient: 0xF5,
 | 
			
		||||
  ClientIdentified: 0xF6,
 | 
			
		||||
 | 
			
		||||
  getName: function(v) {
 | 
			
		||||
    return _reverseLookup[v];
 | 
			
		||||
  }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
var _reverseLookup = {};
 | 
			
		||||
for(var n in TcpCommand) {
 | 
			
		||||
  if (n === 'getName') continue;
 | 
			
		||||
  var v = TcpCommand[n];
 | 
			
		||||
  _reverseLookup[v] = n;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = TcpCommand;
 | 
			
		||||
module.exports.getName = function(v) {
 | 
			
		||||
  return _reverseLookup[v];
 | 
			
		||||
};
 | 
			
		||||
module.exports = TcpCommand;
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
const TcpFlags = {
 | 
			
		||||
const TcpFlags = Object.freeze({
 | 
			
		||||
  None: 0x0,
 | 
			
		||||
  Authenticated: 0x01
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
module.exports = TcpFlags;
 | 
			
		||||
 
 | 
			
		||||
@@ -19,8 +19,7 @@ function TcpPackage(command, flags, correlationId, login, password, data) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TcpPackage.fromBufferSegment = function(data) {
 | 
			
		||||
  if (data.length < MandatorySize)
 | 
			
		||||
    throw new Error("ArraySegment too short, length: " + data.length);
 | 
			
		||||
  if (data.length < MandatorySize) throw new Error("ArraySegment too short, length: " + data.length);
 | 
			
		||||
 | 
			
		||||
  var command = data.buffer[data.offset + CommandOffset];
 | 
			
		||||
  var flags = data.buffer[data.offset + FlagsOffset];
 | 
			
		||||
@@ -32,13 +31,15 @@ TcpPackage.fromBufferSegment = function(data) {
 | 
			
		||||
  if ((flags & TcpFlags.Authenticated) !== 0)
 | 
			
		||||
  {
 | 
			
		||||
    var loginLen = data.buffer[data.offset + AuthOffset];
 | 
			
		||||
    if (AuthOffset + 1 + loginLen + 1 >= data.count)
 | 
			
		||||
        throw new Error("Login length is too big, it doesn't fit into TcpPackage.");
 | 
			
		||||
    if (AuthOffset + 1 + loginLen + 1 >= data.count) {
 | 
			
		||||
      throw new Error("Login length is too big, it doesn't fit into TcpPackage.");
 | 
			
		||||
    }
 | 
			
		||||
    login = data.buffer.toString('utf8', data.offset + AuthOffset + 1, data.offset + AuthOffset + 1 + loginLen);
 | 
			
		||||
 | 
			
		||||
    var passLen = data.buffer[data.offset + AuthOffset + 1 + loginLen];
 | 
			
		||||
    if (AuthOffset + 1 + loginLen + 1 + passLen > data.count)
 | 
			
		||||
        throw new Error("Password length is too big, it doesn't fit into TcpPackage.");
 | 
			
		||||
    if (AuthOffset + 1 + loginLen + 1 + passLen > data.count) {
 | 
			
		||||
      throw new Error("Password length is too big, it doesn't fit into TcpPackage.");
 | 
			
		||||
    }
 | 
			
		||||
    headerSize += 1 + loginLen + 1 + passLen;
 | 
			
		||||
    pass = data.buffer.toString('utf8', data.offset + AuthOffset + 1 + loginLen + 1, data.offset + headerSize);
 | 
			
		||||
  }
 | 
			
		||||
@@ -49,12 +50,12 @@ TcpPackage.fromBufferSegment = function(data) {
 | 
			
		||||
 | 
			
		||||
TcpPackage.prototype.asBuffer = function() {
 | 
			
		||||
  if ((this.flags & TcpFlags.Authenticated) !== 0) {
 | 
			
		||||
    var loginBytes = new Buffer(this.login);
 | 
			
		||||
    var loginBytes = Buffer.from(this.login);
 | 
			
		||||
    if (loginBytes.length > 255) throw new Error("Login serialized length should be less than 256 bytes.");
 | 
			
		||||
    var passwordBytes = new Buffer(this.password);
 | 
			
		||||
    var passwordBytes = Buffer.from(this.password);
 | 
			
		||||
    if (passwordBytes.length > 255) throw new Error("Password serialized length should be less than 256 bytes.");
 | 
			
		||||
 | 
			
		||||
    var res = new Buffer(MandatorySize + 2 + loginBytes.length + passwordBytes.length + (this.data ? this.data.count : 0));
 | 
			
		||||
    var res = Buffer.alloc(MandatorySize + 2 + loginBytes.length + passwordBytes.length + (this.data ? this.data.count : 0));
 | 
			
		||||
    res[CommandOffset] = this.command;
 | 
			
		||||
    res[FlagsOffset] = this.flags;
 | 
			
		||||
    guidParse.parse(this.correlationId, res, CorrelationOffset);
 | 
			
		||||
@@ -64,17 +65,15 @@ TcpPackage.prototype.asBuffer = function() {
 | 
			
		||||
    res[AuthOffset + 1 + loginBytes.length] = passwordBytes.length;
 | 
			
		||||
    passwordBytes.copy(res, AuthOffset + 2 + loginBytes.length);
 | 
			
		||||
 | 
			
		||||
    if (this.data)
 | 
			
		||||
      this.data.copyTo(res, res.length - this.data.count);
 | 
			
		||||
    if (this.data) this.data.copyTo(res, res.length - this.data.count);
 | 
			
		||||
 | 
			
		||||
    return res;
 | 
			
		||||
  } else {
 | 
			
		||||
    var res = new Buffer(MandatorySize + (this.data ? this.data.count : 0));
 | 
			
		||||
    var res = Buffer.alloc(MandatorySize + (this.data ? this.data.count : 0));
 | 
			
		||||
    res[CommandOffset] = this.command;
 | 
			
		||||
    res[FlagsOffset] = this.flags;
 | 
			
		||||
    guidParse.parse(this.correlationId, res, CorrelationOffset);
 | 
			
		||||
    if (this.data)
 | 
			
		||||
      this.data.copyTo(res, AuthOffset);
 | 
			
		||||
    if (this.data) this.data.copyTo(res, AuthOffset);
 | 
			
		||||
    return res;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
@@ -83,4 +82,4 @@ TcpPackage.prototype.asBufferSegment = function() {
 | 
			
		||||
  return createBufferSegment(this.asBuffer());
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports = TcpPackage;
 | 
			
		||||
module.exports = TcpPackage;
 | 
			
		||||
 
 | 
			
		||||
@@ -31,10 +31,11 @@ LengthPrefixMessageFramer.prototype._parse = function(bytes) {
 | 
			
		||||
      ++this._headerBytes;
 | 
			
		||||
      if (this._headerBytes === HeaderLength)
 | 
			
		||||
      {
 | 
			
		||||
        if (this._packageLength <= 0 || this._packageLength > this._maxPackageSize)
 | 
			
		||||
        if (this._packageLength <= 0 || this._packageLength > this._maxPackageSize) {
 | 
			
		||||
          throw new Error(["Package size is out of bounds: ", this._packageLength, "(max: ", this._maxPackageSize, "."].join(''));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._messageBuffer = new Buffer(this._packageLength);
 | 
			
		||||
        this._messageBuffer = Buffer.alloc(this._packageLength);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
@@ -46,8 +47,9 @@ LengthPrefixMessageFramer.prototype._parse = function(bytes) {
 | 
			
		||||
 | 
			
		||||
      if (this._bufferIndex === this._packageLength)
 | 
			
		||||
      {
 | 
			
		||||
        if (this._receivedHandler !== null)
 | 
			
		||||
        if (this._receivedHandler !== null) {
 | 
			
		||||
          this._receivedHandler(createBufferSegment(this._messageBuffer, 0, this._bufferIndex));
 | 
			
		||||
        }
 | 
			
		||||
        this.reset();
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
@@ -56,7 +58,7 @@ LengthPrefixMessageFramer.prototype._parse = function(bytes) {
 | 
			
		||||
 | 
			
		||||
LengthPrefixMessageFramer.prototype.frameData = function(data) {
 | 
			
		||||
  var length = data.count;
 | 
			
		||||
  var lengthBuffer = new Buffer(HeaderLength);
 | 
			
		||||
  var lengthBuffer = Buffer.alloc(HeaderLength);
 | 
			
		||||
  lengthBuffer.writeInt32LE(length, 0);
 | 
			
		||||
  return [
 | 
			
		||||
    createBufferSegment(lengthBuffer, 0, HeaderLength),
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
var net = require('net');
 | 
			
		||||
var tls = require('tls');
 | 
			
		||||
var createBufferSegment = require('../../common/bufferSegment');
 | 
			
		||||
 | 
			
		||||
const MaxSendPacketSize = 64 * 1024;
 | 
			
		||||
@@ -34,16 +35,15 @@ TcpConnection.prototype._initSocket = function(socket) {
 | 
			
		||||
  this._localEndPoint = {host: socket.localAddress, port: socket.localPort};
 | 
			
		||||
  this._remoteEndPoint.host = socket.remoteAddress;
 | 
			
		||||
 | 
			
		||||
  this._socket.on('drain', this._trySend.bind(this));
 | 
			
		||||
  this._socket.on('error', this._processError.bind(this));
 | 
			
		||||
  this._socket.on('drain', this._trySend.bind(this));
 | 
			
		||||
  this._socket.on('data', this._processReceive.bind(this));
 | 
			
		||||
  this._socket.on('close', this._processClose.bind(this));
 | 
			
		||||
 | 
			
		||||
  this._trySend();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
TcpConnection.prototype.enqueueSend = function(bufSegmentArray) {
 | 
			
		||||
  //console.log(bufSegmentArray);
 | 
			
		||||
 | 
			
		||||
  for(var i = 0; i < bufSegmentArray.length; i++) {
 | 
			
		||||
    var bufSegment = bufSegmentArray[i];
 | 
			
		||||
    this._sendQueue.push(bufSegment.toBuffer());
 | 
			
		||||
@@ -58,17 +58,14 @@ TcpConnection.prototype._trySend = function() {
 | 
			
		||||
  var buffers = [];
 | 
			
		||||
  var bytes = 0;
 | 
			
		||||
  var sendPiece;
 | 
			
		||||
  while(sendPiece = this._sendQueue.shift()) {
 | 
			
		||||
  while((sendPiece = this._sendQueue.shift())) {
 | 
			
		||||
    buffers.push(sendPiece);
 | 
			
		||||
    bytes += sendPiece.length;
 | 
			
		||||
    if (bytes > MaxSendPacketSize)
 | 
			
		||||
        break;
 | 
			
		||||
    if (bytes > MaxSendPacketSize) break;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  var joinedBuffers = Buffer.concat(buffers, bytes);
 | 
			
		||||
  if (!this._socket.write(joinedBuffers)) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  if (!this._socket.write(joinedBuffers)) return;
 | 
			
		||||
 | 
			
		||||
  setImmediate(this._trySend.bind(this));
 | 
			
		||||
};
 | 
			
		||||
@@ -77,6 +74,10 @@ TcpConnection.prototype._processError = function(err) {
 | 
			
		||||
  this._closeInternal(err, "Socket error");
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
TcpConnection.prototype._processClose = function(had_error) {
 | 
			
		||||
  this._closeInternal(had_error, "Socket closed");
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
TcpConnection.prototype._processReceive = function(buf) {
 | 
			
		||||
  if (buf.length === 0) {
 | 
			
		||||
    //NotifyReceiveCompleted(0);
 | 
			
		||||
@@ -96,8 +97,7 @@ TcpConnection.prototype.receive = function(cb) {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
TcpConnection.prototype._tryDequeueReceivedData = function() {
 | 
			
		||||
  if (this._receiveCallback === null || this._receiveQueue.length === 0)
 | 
			
		||||
      return;
 | 
			
		||||
  if (this._receiveCallback === null || this._receiveQueue.length === 0) return;
 | 
			
		||||
 | 
			
		||||
  var res = [];
 | 
			
		||||
  while(this._receiveQueue.length > 0) {
 | 
			
		||||
@@ -111,8 +111,9 @@ TcpConnection.prototype._tryDequeueReceivedData = function() {
 | 
			
		||||
  callback(this, res);
 | 
			
		||||
 | 
			
		||||
  var bytes = 0;
 | 
			
		||||
  for(var i=0;i<res.length;i++)
 | 
			
		||||
  for(var i=0;i<res.length;i++) {
 | 
			
		||||
    bytes += res[i].count;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  //this._pendingReceivedBytes -= bytes;
 | 
			
		||||
};
 | 
			
		||||
@@ -131,28 +132,43 @@ TcpConnection.prototype._closeInternal = function(err, reason) {
 | 
			
		||||
    this._socket = null;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (this._onConnectionClosed !== null)
 | 
			
		||||
      this._onConnectionClosed(this, err);
 | 
			
		||||
  if (this._onConnectionClosed !== null) this._onConnectionClosed(this, err);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
TcpConnection.createConnectingConnection = function(
 | 
			
		||||
    log, connectionId, remoteEndPoint, connectionTimeout,
 | 
			
		||||
    onConnectionEstablished, onConnectionFailed, onConnectionClosed
 | 
			
		||||
    log, connectionId, remoteEndPoint, ssl, targetHost, validateServer,
 | 
			
		||||
    connectionTimeout, onConnectionEstablished, onConnectionFailed, onConnectionClosed
 | 
			
		||||
) {
 | 
			
		||||
  var connection = new TcpConnection(log, connectionId, remoteEndPoint, onConnectionClosed);
 | 
			
		||||
  var socket = net.connect(remoteEndPoint.port, remoteEndPoint.host);
 | 
			
		||||
  function onError(err) {
 | 
			
		||||
    if (onConnectionFailed)
 | 
			
		||||
      onConnectionFailed(connection, err);
 | 
			
		||||
  }
 | 
			
		||||
  socket.once('error', onError);
 | 
			
		||||
  socket.on('connect', function() {
 | 
			
		||||
  var provider = ssl ? tls : net;
 | 
			
		||||
  var options = {
 | 
			
		||||
    servername: targetHost,
 | 
			
		||||
    rejectUnauthorized: validateServer,
 | 
			
		||||
    port: remoteEndPoint.port,
 | 
			
		||||
    host: remoteEndPoint.host,
 | 
			
		||||
    timeout: connectionTimeout
 | 
			
		||||
  };
 | 
			
		||||
  var socket = provider.connect(options, function() {
 | 
			
		||||
    socket.removeListener('error', onError);
 | 
			
		||||
    connection._initSocket(socket);
 | 
			
		||||
    if (onConnectionEstablished)
 | 
			
		||||
      onConnectionEstablished(connection);
 | 
			
		||||
    if (onConnectionEstablished) onConnectionEstablished(connection);
 | 
			
		||||
  });
 | 
			
		||||
  var timer = setTimeout(function(){
 | 
			
		||||
    log.error('TcpConnection: timeout when connecting to %j in %d ms', remoteEndPoint, connectionTimeout);
 | 
			
		||||
    connection.close();
 | 
			
		||||
    if (onConnectionFailed) onConnectionFailed(connection, new Error('Connection failed'));
 | 
			
		||||
  }, connectionTimeout)
 | 
			
		||||
  socket.once('error', onError);
 | 
			
		||||
  function onError(err) {
 | 
			
		||||
    clearTimeout(timer);
 | 
			
		||||
    if (onConnectionFailed) onConnectionFailed(connection, err);
 | 
			
		||||
  }
 | 
			
		||||
  socket.once('connect', onConnect);
 | 
			
		||||
  function onConnect() {
 | 
			
		||||
    log.info('TcpConnection: successfully connected to %j', remoteEndPoint);
 | 
			
		||||
    clearTimeout(timer);
 | 
			
		||||
  }
 | 
			
		||||
  return connection;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports = TcpConnection;
 | 
			
		||||
module.exports = TcpConnection;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,4 @@
 | 
			
		||||
var util = require('util');
 | 
			
		||||
var uuid = require('uuid');
 | 
			
		||||
 | 
			
		||||
var LengthPrefixMessageFramer = require('./lengthPrefixMessageFramer');
 | 
			
		||||
var TcpConnection = require('./tcpConnection');
 | 
			
		||||
@@ -38,15 +37,14 @@ function TcpPackageConnection(
 | 
			
		||||
  this._framer = new LengthPrefixMessageFramer();
 | 
			
		||||
  this._framer.registerMessageArrivedCallback(this._incomingMessageArrived.bind(this));
 | 
			
		||||
 | 
			
		||||
  //TODO ssl
 | 
			
		||||
  var self = this;
 | 
			
		||||
  this._connection = TcpConnection.createConnectingConnection(
 | 
			
		||||
      log,
 | 
			
		||||
      connectionId,
 | 
			
		||||
      remoteEndPoint,
 | 
			
		||||
      //ssl,
 | 
			
		||||
      //targetHost,
 | 
			
		||||
      //validateServer,
 | 
			
		||||
      ssl,
 | 
			
		||||
      targetHost,
 | 
			
		||||
      validateServer,
 | 
			
		||||
      timeout,
 | 
			
		||||
      function(tcpConnection) {
 | 
			
		||||
        log.debug("TcpPackageConnection: connected to [%j, L%j, %s].", tcpConnection.remoteEndPoint, tcpConnection.localEndPoint, connectionId);
 | 
			
		||||
@@ -56,13 +54,11 @@ function TcpPackageConnection(
 | 
			
		||||
        log.debug("TcpPackageConnection: connection to [%j, L%j, %s] failed. Error: %s.", conn.remoteEndPoint, conn.localEndPoint, connectionId, error);
 | 
			
		||||
        connectionClosed(self, error);
 | 
			
		||||
      },
 | 
			
		||||
      function (conn, had_error) {
 | 
			
		||||
        var error;
 | 
			
		||||
        if (had_error)
 | 
			
		||||
            error = new Error('transmission error.');
 | 
			
		||||
      function (conn, error) {
 | 
			
		||||
        if (error === true) error = new Error('transmission error.');
 | 
			
		||||
 | 
			
		||||
        log.debug("TcpPackageConnection: connection [%j, L%j, %s] was closed %s", conn.remoteEndPoint, conn.localEndPoint,
 | 
			
		||||
            connectionId, had_error ? "with error: " + error + "." : "cleanly.");
 | 
			
		||||
            connectionId, error ? "with error: " + error.stack : "cleanly.");
 | 
			
		||||
 | 
			
		||||
        connectionClosed(self, error);
 | 
			
		||||
      });
 | 
			
		||||
@@ -121,27 +117,23 @@ TcpPackageConnection.prototype._incomingMessageArrived = function(data) {
 | 
			
		||||
    var message = util.format("TcpPackageConnection: [%j, L%j, %s] ERROR for %s. Connection will be closed.",
 | 
			
		||||
        this.remoteEndPoint, this.localEndPoint, this._connectionId,
 | 
			
		||||
        valid ? TcpCommand.getName(pkg.command) : "<invalid package>");
 | 
			
		||||
    if (this._onError !== null)
 | 
			
		||||
      this._onError(this, e);
 | 
			
		||||
    if (this._onError !== null) this._onError(this, e);
 | 
			
		||||
    this._log.debug(e, message);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
TcpPackageConnection.prototype.startReceiving = function() {
 | 
			
		||||
  if (this._connection === null)
 | 
			
		||||
    throw new Error("Failed connection.");
 | 
			
		||||
  if (this._connection === null) throw new Error("Failed connection.");
 | 
			
		||||
  this._connection.receive(this._onRawDataReceived.bind(this));
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
TcpPackageConnection.prototype.enqueueSend = function(pkg) {
 | 
			
		||||
  if (this._connection === null)
 | 
			
		||||
    throw new Error("Failed connection.");
 | 
			
		||||
  if (this._connection === null) throw new Error("Failed connection.");
 | 
			
		||||
  this._connection.enqueueSend(this._framer.frameData(pkg.asBufferSegment()));
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
TcpPackageConnection.prototype.close = function(reason) {
 | 
			
		||||
  if (this._connection === null)
 | 
			
		||||
    throw new Error("Failed connection.");
 | 
			
		||||
  if (this._connection === null) throw new Error("Failed connection.");
 | 
			
		||||
  this._connection.close(reason);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -151,4 +143,4 @@ TcpPackageConnection.prototype.equals = function(other) {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
module.exports = TcpPackageConnection;
 | 
			
		||||
module.exports = TcpPackageConnection;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										17
									
								
								src/utils/modules.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								src/utils/modules.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
exports.uncache = function uncache(id) {
 | 
			
		||||
  var mod = require.cache[id];
 | 
			
		||||
  if (!mod) return;
 | 
			
		||||
  delete require.cache[id];
 | 
			
		||||
  if (mod.children)
 | 
			
		||||
    for(var i = 0; i < mod.children.length; i++)
 | 
			
		||||
      uncache(mod.children[i].id);
 | 
			
		||||
  return mod;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
exports.recache = function recache(mod) {
 | 
			
		||||
  if (require.cache[mod.id] === mod) return;
 | 
			
		||||
  require.cache[mod.id] = mod;
 | 
			
		||||
  if (mod.children)
 | 
			
		||||
    for(var i = 0; i < mod.children.length; i++)
 | 
			
		||||
      recache(mod.children[i]);
 | 
			
		||||
};
 | 
			
		||||
@@ -22,4 +22,4 @@ VolatileEventStoreSubscription.prototype.unsubscribe = function() {
 | 
			
		||||
  this._subscriptionOperation.unsubscribe();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports = VolatileEventStoreSubscription;
 | 
			
		||||
module.exports = VolatileEventStoreSubscription;
 | 
			
		||||
@@ -1,13 +1,17 @@
 | 
			
		||||
var uuid = require('uuid');
 | 
			
		||||
var client = require('../src/client');
 | 
			
		||||
var client = require('../lib/dist');
 | 
			
		||||
var Long = require('long');
 | 
			
		||||
 | 
			
		||||
var ANY_VERSION = Long.fromNumber(client.expectedVersion.any);
 | 
			
		||||
var NOSTREAM_VERSION = Long.fromNumber(client.expectedVersion.noStream);
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
  'Append One Event To Stream Happy Path': function(test) {
 | 
			
		||||
    test.expect(2);
 | 
			
		||||
    var event = client.createJsonEventData(uuid.v4(), {a: Math.random(), b: uuid.v4()}, null, 'testEvent');
 | 
			
		||||
    this.conn.appendToStream(this.testStreamName, client.expectedVersion.any, event)
 | 
			
		||||
    this.conn.appendToStream(this.testStreamName, ANY_VERSION, event)
 | 
			
		||||
        .then(function(result) {
 | 
			
		||||
          test.areEqual("nextExpectedVersion", result.nextExpectedVersion, 0);
 | 
			
		||||
          test.areEqual("nextExpectedVersion", result.nextExpectedVersion, Long.fromNumber(0));
 | 
			
		||||
          test.ok(result.logPosition, "No log position in result.");
 | 
			
		||||
          test.done();
 | 
			
		||||
        })
 | 
			
		||||
@@ -25,9 +29,9 @@ module.exports = {
 | 
			
		||||
      else
 | 
			
		||||
        events.push(client.createJsonEventData(uuid.v4(), {b: Math.random(), a: uuid.v4()}, null, 'otherEvent'));
 | 
			
		||||
    }
 | 
			
		||||
    this.conn.appendToStream(this.testStreamName, client.expectedVersion.any, events)
 | 
			
		||||
    this.conn.appendToStream(this.testStreamName, ANY_VERSION, events)
 | 
			
		||||
        .then(function(result) {
 | 
			
		||||
          test.areEqual("result.nextExpectedVersion", result.nextExpectedVersion, expectedVersion);
 | 
			
		||||
          test.areEqual("result.nextExpectedVersion", result.nextExpectedVersion, Long.fromNumber(expectedVersion));
 | 
			
		||||
          test.ok(result.logPosition, "No log position in result.");
 | 
			
		||||
          test.done();
 | 
			
		||||
        })
 | 
			
		||||
@@ -45,9 +49,9 @@ module.exports = {
 | 
			
		||||
      else
 | 
			
		||||
        events.push(client.createJsonEventData(uuid.v4(), {b: Math.random(), a: uuid.v4()}, null, 'otherEvent'));
 | 
			
		||||
    }
 | 
			
		||||
    this.conn.appendToStream(this.testStreamName, client.expectedVersion.any, events)
 | 
			
		||||
    this.conn.appendToStream(this.testStreamName, ANY_VERSION, events)
 | 
			
		||||
        .then(function(result) {
 | 
			
		||||
          test.areEqual("result.nextExpectedVersion", result.nextExpectedVersion, expectedVersion);
 | 
			
		||||
          test.areEqual("result.nextExpectedVersion", result.nextExpectedVersion, Long.fromNumber(expectedVersion));
 | 
			
		||||
          test.ok(result.logPosition, "No log position in result.");
 | 
			
		||||
          test.done();
 | 
			
		||||
        })
 | 
			
		||||
@@ -59,10 +63,10 @@ module.exports = {
 | 
			
		||||
    test.expect(2);
 | 
			
		||||
    const largeData = Buffer.alloc(3 * 1024 *1024, " ");
 | 
			
		||||
    const event = client.createJsonEventData(uuid.v4(), {a: largeData.toString()}, null, 'largePayloadEvent');
 | 
			
		||||
    
 | 
			
		||||
    this.conn.appendToStream(this.testStreamName, client.expectedVersion.any, event)
 | 
			
		||||
 | 
			
		||||
    this.conn.appendToStream(this.testStreamName, ANY_VERSION, event)
 | 
			
		||||
        .then(function(result) {
 | 
			
		||||
          test.areEqual("result.nextExpectedVersion", result.nextExpectedVersion, 0);
 | 
			
		||||
          test.areEqual("result.nextExpectedVersion", result.nextExpectedVersion, Long.fromNumber(0));
 | 
			
		||||
          test.ok(result.logPosition, "No log position in result.");
 | 
			
		||||
          test.done();
 | 
			
		||||
        })
 | 
			
		||||
@@ -73,7 +77,7 @@ module.exports = {
 | 
			
		||||
  'Append To Stream Wrong Expected Version': function(test) {
 | 
			
		||||
    test.expect(1);
 | 
			
		||||
    var event = client.createJsonEventData(uuid.v4(), {a: Math.random(), b: uuid.v4()}, null, 'testEvent');
 | 
			
		||||
    this.conn.appendToStream(this.testStreamName, 10, event)
 | 
			
		||||
    this.conn.appendToStream(this.testStreamName, Long.fromNumber(10), event)
 | 
			
		||||
        .then(function(result) {
 | 
			
		||||
          test.fail("Append succeeded but should have failed.");
 | 
			
		||||
          test.done();
 | 
			
		||||
@@ -88,10 +92,10 @@ module.exports = {
 | 
			
		||||
  'Append To Stream Deleted': function(test) {
 | 
			
		||||
    test.expect(1);
 | 
			
		||||
    var self = this;
 | 
			
		||||
    this.conn.deleteStream(this.testStreamName, client.expectedVersion.noStream, true)
 | 
			
		||||
    this.conn.deleteStream(this.testStreamName, NOSTREAM_VERSION, true)
 | 
			
		||||
        .then(function() {
 | 
			
		||||
          var event = client.createJsonEventData(uuid.v4(), {a: Math.random(), b: uuid.v4()}, null, 'testEvent');
 | 
			
		||||
          return self.conn.appendToStream(self.testStreamName, client.expectedVersion.any, event)
 | 
			
		||||
          return self.conn.appendToStream(self.testStreamName, ANY_VERSION, event)
 | 
			
		||||
        })
 | 
			
		||||
        .then(function(result) {
 | 
			
		||||
          test.fail("Append succeeded but should have failed.");
 | 
			
		||||
@@ -108,10 +112,10 @@ module.exports = {
 | 
			
		||||
    test.expect(1);
 | 
			
		||||
    var self = this;
 | 
			
		||||
    var metadata = {$acl: {$w: "$admins"}};
 | 
			
		||||
    this.conn.setStreamMetadataRaw(this.testStreamName, client.expectedVersion.noStream, metadata)
 | 
			
		||||
    this.conn.setStreamMetadataRaw(this.testStreamName, NOSTREAM_VERSION, metadata)
 | 
			
		||||
        .then(function() {
 | 
			
		||||
          var event = client.createJsonEventData(uuid.v4(), {a: Math.random(), b: uuid.v4()}, null, 'testEvent');
 | 
			
		||||
          return self.conn.appendToStream(self.testStreamName, client.expectedVersion.any, event)
 | 
			
		||||
          return self.conn.appendToStream(self.testStreamName, ANY_VERSION, event)
 | 
			
		||||
        })
 | 
			
		||||
        .then(function(result) {
 | 
			
		||||
          test.fail("Append succeeded but should have failed.");
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
var client = require('../../src/client');
 | 
			
		||||
var client = require('../../lib/dist');
 | 
			
		||||
var uuid = require('uuid');
 | 
			
		||||
 | 
			
		||||
var settings = {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
var client = require('../../src/client');
 | 
			
		||||
var client = require('../../lib/dist');
 | 
			
		||||
var uuid = require('uuid');
 | 
			
		||||
 | 
			
		||||
var settings = {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,42 +1,114 @@
 | 
			
		||||
var util = require('util');
 | 
			
		||||
var uuid = require('uuid');
 | 
			
		||||
var client = require('../../src/client');
 | 
			
		||||
var Long = require('long');
 | 
			
		||||
var client = require('../../lib/dist');
 | 
			
		||||
var FileLogger = require('../../src/common/log/fileLogger');
 | 
			
		||||
var NoopLogger = require('../../src/common/log/noopLogger');
 | 
			
		||||
 | 
			
		||||
// Make sure we mess with protobufjs setup for bug #91
 | 
			
		||||
var protobufJS = require('protobufjs');
 | 
			
		||||
protobufJS.util.Long = undefined;
 | 
			
		||||
protobufJS.configure();
 | 
			
		||||
 | 
			
		||||
var settings = {
 | 
			
		||||
  log: new NoopLogger()
 | 
			
		||||
  log: new NoopLogger(),
 | 
			
		||||
  useSslConnection: true,
 | 
			
		||||
  validateServer: false
 | 
			
		||||
};
 | 
			
		||||
if (process.env.TESTS_VERBOSE_LOGGING === '1') {
 | 
			
		||||
  settings.verboseLogging = true;
 | 
			
		||||
  settings.log = new FileLogger('test-verbose.log');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var tcpEndPoint = {host: 'localhost', port: 1113};
 | 
			
		||||
 | 
			
		||||
function setUp(cb) {
 | 
			
		||||
function setUpWithGossipSeeds(cb) {
 | 
			
		||||
  var gossipSeeds = [
 | 
			
		||||
    new client.GossipSeed({ host: process.env.EVENTSTORE_HOST_1 || '192.168.33.10', port: 2113 }),
 | 
			
		||||
    new client.GossipSeed({ host: process.env.EVENTSTORE_HOST_2 || '192.168.33.11', port: 2113 }),
 | 
			
		||||
    new client.GossipSeed({ host: process.env.EVENTSTORE_HOST_3 || '192.168.33.12', port: 2113 }),
 | 
			
		||||
  ];
 | 
			
		||||
  this.log = settings.log;
 | 
			
		||||
  this.testStreamName = 'test-' + uuid.v4();
 | 
			
		||||
  var connected = false;
 | 
			
		||||
  this.conn = client.EventStoreConnection.create(settings, tcpEndPoint);
 | 
			
		||||
  this.conn.connect()
 | 
			
		||||
      .then(function () {
 | 
			
		||||
        //Doesn't mean anything, connection is just initiated
 | 
			
		||||
        settings.log.debug("Connection to %j initialized.", tcpEndPoint);
 | 
			
		||||
      })
 | 
			
		||||
      .catch(function (err) {
 | 
			
		||||
        settings.log.error(err, "Initializing connection to %j failed.", tcpEndPoint);
 | 
			
		||||
        cb(err);
 | 
			
		||||
      });
 | 
			
		||||
  this.conn = client.createConnection(settings, gossipSeeds);
 | 
			
		||||
  this.conn
 | 
			
		||||
    .connect()
 | 
			
		||||
    .then(function () {
 | 
			
		||||
      //Doesn't mean anything, connection is just initiated
 | 
			
		||||
      settings.log.debug('Connection to %j initialized.', gossipSeeds);
 | 
			
		||||
    })
 | 
			
		||||
    .catch(function (err) {
 | 
			
		||||
      settings.log.error(err, 'Initializing connection to %j failed.', gossipSeeds);
 | 
			
		||||
      cb(err);
 | 
			
		||||
    });
 | 
			
		||||
  this.conn.on('closed', function (reason) {
 | 
			
		||||
    if (connected) return;
 | 
			
		||||
    var error = new Error("Connection failed: " + reason);
 | 
			
		||||
    settings.log.error(error, "Connection to %j failed.", tcpEndPoint);
 | 
			
		||||
    var error = new Error('Connection failed: ' + reason);
 | 
			
		||||
    settings.log.error(error, 'Connection to %j failed.', gossipSeeds);
 | 
			
		||||
    cb(error);
 | 
			
		||||
  });
 | 
			
		||||
  this.conn.on('connected', function (tcpEndPoint) {
 | 
			
		||||
    if (connected) return;
 | 
			
		||||
    settings.log.debug("Connected to %j.", tcpEndPoint);
 | 
			
		||||
    settings.log.debug('Connected to %j.', tcpEndPoint);
 | 
			
		||||
    connected = true;
 | 
			
		||||
    cb();
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function setUpWithDns(cb) {
 | 
			
		||||
  var clusterDns = 'discover://' + process.env.EVENTSTORE_HOST + ':2113';
 | 
			
		||||
  this.log = settings.log;
 | 
			
		||||
  this.testStreamName = 'test-' + uuid.v4();
 | 
			
		||||
  var connected = false;
 | 
			
		||||
  this.conn = client.createConnection(settings, clusterDns);
 | 
			
		||||
  this.conn
 | 
			
		||||
    .connect()
 | 
			
		||||
    .then(function () {
 | 
			
		||||
      //Doesn't mean anything, connection is just initiated
 | 
			
		||||
      settings.log.debug('Connection to %j initialized.', clusterDns);
 | 
			
		||||
    })
 | 
			
		||||
    .catch(function (err) {
 | 
			
		||||
      settings.log.error(err, 'Initializing connection to %j failed.', clusterDns);
 | 
			
		||||
      cb(err);
 | 
			
		||||
    });
 | 
			
		||||
  this.conn.on('closed', function (reason) {
 | 
			
		||||
    if (connected) return;
 | 
			
		||||
    var error = new Error('Connection failed: ' + reason);
 | 
			
		||||
    settings.log.error(error, 'Connection to %j failed.', clusterDns);
 | 
			
		||||
    cb(error);
 | 
			
		||||
  });
 | 
			
		||||
  this.conn.on('connected', function (tcpEndPoint) {
 | 
			
		||||
    if (connected) return;
 | 
			
		||||
    settings.log.debug('Connected to %j.', tcpEndPoint);
 | 
			
		||||
    connected = true;
 | 
			
		||||
    cb();
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function setUpWithTcpEndpoint(cb) {
 | 
			
		||||
  var tcpEndPoint = { host: process.env.EVENTSTORE_HOST || 'localhost', port: 1113 };
 | 
			
		||||
  this.log = settings.log;
 | 
			
		||||
  this.testStreamName = 'test-' + uuid.v4();
 | 
			
		||||
  var connected = false;
 | 
			
		||||
  this.conn = client.EventStoreConnection.create(settings, tcpEndPoint);
 | 
			
		||||
  this.conn
 | 
			
		||||
    .connect()
 | 
			
		||||
    .then(function () {
 | 
			
		||||
      //Doesn't mean anything, connection is just initiated
 | 
			
		||||
      settings.log.debug('Connection to %j initialized.', tcpEndPoint);
 | 
			
		||||
    })
 | 
			
		||||
    .catch(function (err) {
 | 
			
		||||
      settings.log.error(err, 'Initializing connection to %j failed.', tcpEndPoint);
 | 
			
		||||
      cb(err);
 | 
			
		||||
    });
 | 
			
		||||
  this.conn.on('closed', function (reason) {
 | 
			
		||||
    if (connected) return;
 | 
			
		||||
    var error = new Error('Connection failed: ' + reason);
 | 
			
		||||
    settings.log.error(error, 'Connection to %j failed.', tcpEndPoint);
 | 
			
		||||
    cb(error);
 | 
			
		||||
  });
 | 
			
		||||
  this.conn.on('connected', function (tcpEndPoint) {
 | 
			
		||||
    if (connected) return;
 | 
			
		||||
    settings.log.debug('Connected to %j.', tcpEndPoint);
 | 
			
		||||
    connected = true;
 | 
			
		||||
    cb();
 | 
			
		||||
  });
 | 
			
		||||
@@ -44,7 +116,7 @@ function setUp(cb) {
 | 
			
		||||
 | 
			
		||||
function tearDown(cb) {
 | 
			
		||||
  this.conn.close();
 | 
			
		||||
  this.conn.on('closed', function() {
 | 
			
		||||
  this.conn.on('closed', function () {
 | 
			
		||||
    cb();
 | 
			
		||||
  });
 | 
			
		||||
  this.conn = null;
 | 
			
		||||
@@ -52,9 +124,8 @@ function tearDown(cb) {
 | 
			
		||||
 | 
			
		||||
function areEqual(name, actual, expected) {
 | 
			
		||||
  if (typeof expected !== 'object' || expected === null)
 | 
			
		||||
    this.strictEqual(actual, expected, util.format("Failed %s === %s, got %s.", name, expected, actual));
 | 
			
		||||
  else
 | 
			
		||||
    this.deepEqual(actual, expected, util.format("Failed %s deepEqual %j, got %j.", name, expected, actual));
 | 
			
		||||
    this.strictEqual(actual, expected, util.format('Failed %s === %s, got %s.', name, expected, actual));
 | 
			
		||||
  else this.deepEqual(actual, expected, util.format('Failed %s deepEqual %j, got %j.', name, expected, actual));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function fail(reason) {
 | 
			
		||||
@@ -63,49 +134,75 @@ function fail(reason) {
 | 
			
		||||
 | 
			
		||||
function eventEqualEventData(name, resolvedEvent, eventData) {
 | 
			
		||||
  var ev = resolvedEvent.originalEvent;
 | 
			
		||||
  this.ok(ev !== null, util.format("Failed %s !== null.", name + ".originalEvent"));
 | 
			
		||||
  this.ok(ev !== null, util.format('Failed %s !== null.', name + '.originalEvent'));
 | 
			
		||||
  if (ev === null) return;
 | 
			
		||||
  this.areEqual(name + ".originalEvent.eventId", ev.eventId, eventData.eventId);
 | 
			
		||||
  this.areEqual(name + ".originalEvent.eventType", ev.eventType, eventData.type);
 | 
			
		||||
  this.ok(Buffer.compare(ev.data, eventData.data) === 0, name + ".originalEvent.data is not equal to original data.");
 | 
			
		||||
  this.ok(Buffer.compare(ev.metadata, eventData.metadata) === 0, name + ".originalEvent.metadata is not equal to original metadata.");
 | 
			
		||||
  this.areEqual(name + '.originalEvent.eventId', ev.eventId, eventData.eventId);
 | 
			
		||||
  this.areEqual(name + '.originalEvent.eventType', ev.eventType, eventData.type);
 | 
			
		||||
  this.ok(Buffer.compare(ev.data, eventData.data) === 0, name + '.originalEvent.data is not equal to original data.');
 | 
			
		||||
  this.ok(
 | 
			
		||||
    Buffer.compare(ev.metadata, eventData.metadata) === 0,
 | 
			
		||||
    name + '.originalEvent.metadata is not equal to original metadata.'
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function testRecordedEvent(name, event) {
 | 
			
		||||
  this.ok(Long.isLong(event.eventNumber), name + '.eventNumber is not a Long');
 | 
			
		||||
  this.ok(event.created instanceof Date, name + '.created is not a Date');
 | 
			
		||||
  this.ok(typeof event.createdEpoch === 'number', name + '.createdEpoch is not a number');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function testLiveEvent(name, event, evNumber) {
 | 
			
		||||
  this.ok(event.event, name + ".event not defined (or null)");
 | 
			
		||||
  this.ok(event.originalEvent, name + ".originalEvent not defined (or null)");
 | 
			
		||||
  this.ok(event.isResolved === false, name + ".isResolved should be true");
 | 
			
		||||
  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.event, name + '.event not defined (or null)');
 | 
			
		||||
  this.ok(event.originalEvent, name + '.originalEvent not defined (or null)');
 | 
			
		||||
  this.ok(event.isResolved === false, name + '.isResolved should be true');
 | 
			
		||||
  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(Long.isLong(event.originalEventNumber), name + '.originalEventNumber is not a Long');
 | 
			
		||||
  if (typeof evNumber === 'number') {
 | 
			
		||||
    this.ok(event.originalEventNumber === evNumber, name + '.originalEventNumber expected ' + evNumber + ' got ' + event.originalEventNumber);
 | 
			
		||||
  } else {
 | 
			
		||||
    this.ok(typeof event.originalEventNumber === 'number', name + ".originalEventNumber is not a number");
 | 
			
		||||
    this.ok(
 | 
			
		||||
      event.originalEventNumber.toNumber() === evNumber,
 | 
			
		||||
      name + '.originalEventNumber expected ' + evNumber + ' got ' + event.originalEventNumber
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
  testRecordedEvent.call(this, name + '.event', event.event);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function testReadEvent(name, event, evNumber) {
 | 
			
		||||
  this.ok(event.event, name + ".event not defined (or null)");
 | 
			
		||||
  this.ok(event.originalEvent, name + ".originalEvent not defined (or null)");
 | 
			
		||||
  this.ok(event.isResolved === false, name + ".isResolved should be true");
 | 
			
		||||
  this.ok(event.originalPosition === null, name + ".originalPosition is not null");
 | 
			
		||||
  this.ok(event.originalStreamId, name + ".originalStreamId not defined (or null)");
 | 
			
		||||
  this.ok(event.event, name + '.event not defined (or null)');
 | 
			
		||||
  this.ok(event.originalEvent, name + '.originalEvent not defined (or null)');
 | 
			
		||||
  this.ok(event.isResolved === false, name + '.isResolved should be true');
 | 
			
		||||
  this.ok(event.originalPosition === null, name + '.originalPosition is not null');
 | 
			
		||||
  this.ok(event.originalStreamId, name + '.originalStreamId not defined (or null)');
 | 
			
		||||
  this.ok(Long.isLong(event.originalEventNumber), name + '.originalEventNumber is not a Long');
 | 
			
		||||
  if (typeof evNumber === 'number') {
 | 
			
		||||
    this.ok(event.originalEventNumber === evNumber, name + '.originalEventNumber expected ' + evNumber + ' got ' + event.originalEventNumber);
 | 
			
		||||
  } else {
 | 
			
		||||
    this.ok(typeof event.originalEventNumber === 'number', name + ".originalEventNumber is not a number");
 | 
			
		||||
    this.ok(
 | 
			
		||||
      event.originalEventNumber.toNumber() === evNumber,
 | 
			
		||||
      name + '.originalEventNumber expected ' + evNumber + ' got ' + event.originalEventNumber
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
  testRecordedEvent.call(this, name + '.event', event.event);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _ = {
 | 
			
		||||
  'setUp': setUp,
 | 
			
		||||
  'tearDown': tearDown
 | 
			
		||||
  tearDown: tearDown,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
switch (process.env.EVENTSTORE_CONNECTION_TYPE) {
 | 
			
		||||
  case 'gossip':
 | 
			
		||||
    _.setUp = setUpWithGossipSeeds;
 | 
			
		||||
    break;
 | 
			
		||||
  case 'dns':
 | 
			
		||||
    _.setUp = setUpWithDns;
 | 
			
		||||
    break;
 | 
			
		||||
  case 'tcp':
 | 
			
		||||
  default:
 | 
			
		||||
    _.setUp = setUpWithTcpEndpoint;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function wrap(name, testFunc) {
 | 
			
		||||
  var base = _[name];
 | 
			
		||||
  if (base === undefined) {
 | 
			
		||||
    return function(test) {
 | 
			
		||||
    return function (test) {
 | 
			
		||||
      settings.log.debug('--- %s ---', name);
 | 
			
		||||
      test.areEqual = areEqual.bind(test);
 | 
			
		||||
      test.fail = fail.bind(test);
 | 
			
		||||
@@ -113,36 +210,48 @@ function wrap(name, testFunc) {
 | 
			
		||||
      test.testLiveEvent = testLiveEvent.bind(test);
 | 
			
		||||
      test.testReadEvent = testReadEvent.bind(test);
 | 
			
		||||
      return testFunc.call(this, test);
 | 
			
		||||
    }
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
  return function(cb) {
 | 
			
		||||
  return function (cb) {
 | 
			
		||||
    var self = this;
 | 
			
		||||
    base.call(this, function(err) {
 | 
			
		||||
    base.call(this, function (err) {
 | 
			
		||||
      if (err) return cb(err);
 | 
			
		||||
      return testFunc.call(self, cb);
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports.init = function(testSuite, addSetUpTearDownIfNotPresent) {
 | 
			
		||||
module.exports.init = function (testSuite, addSetUpTearDownIfNotPresent) {
 | 
			
		||||
  var thisObj = {};
 | 
			
		||||
  if (addSetUpTearDownIfNotPresent === undefined) addSetUpTearDownIfNotPresent = true;
 | 
			
		||||
  for(var k in testSuite) {
 | 
			
		||||
  for (var k in testSuite) {
 | 
			
		||||
    if (testSuite.hasOwnProperty(k)) {
 | 
			
		||||
      testSuite[k] = wrap(k, testSuite[k]).bind(thisObj);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  if (!addSetUpTearDownIfNotPresent) return;
 | 
			
		||||
  if (!testSuite.hasOwnProperty('setUp')) testSuite['setUp'] = setUp.bind(thisObj);
 | 
			
		||||
  if (!testSuite.hasOwnProperty('setUp')) {
 | 
			
		||||
    switch (process.env.EVENTSTORE_CONNECTION_TYPE) {
 | 
			
		||||
      case 'gossip':
 | 
			
		||||
        testSuite['setUp'] = setUpWithGossipSeeds.bind(thisObj);
 | 
			
		||||
        break;
 | 
			
		||||
      case 'dns':
 | 
			
		||||
        testSuite['setUp'] = setUpWithDns.bind(thisObj);
 | 
			
		||||
        break;
 | 
			
		||||
      case 'tcp':
 | 
			
		||||
      default:
 | 
			
		||||
        testSuite['setUp'] = setUpWithTcpEndpoint.bind(thisObj);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  if (!testSuite.hasOwnProperty('tearDown')) testSuite['tearDown'] = tearDown.bind(thisObj);
 | 
			
		||||
};
 | 
			
		||||
module.exports.settings = function(settingsOverride) {
 | 
			
		||||
module.exports.settings = function (settingsOverride) {
 | 
			
		||||
  var obj = {};
 | 
			
		||||
  for(var prop in settings) {
 | 
			
		||||
  for (var prop in settings) {
 | 
			
		||||
    obj[prop] = settings[prop];
 | 
			
		||||
  }
 | 
			
		||||
  if (!settingsOverride) return obj;
 | 
			
		||||
  for(var prop in settingsOverride) {
 | 
			
		||||
  for (var prop in settingsOverride) {
 | 
			
		||||
    obj[prop] = settingsOverride[prop];
 | 
			
		||||
  }
 | 
			
		||||
  return obj;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,78 +1,176 @@
 | 
			
		||||
var client = require('../src/client.js');
 | 
			
		||||
var client = require('../lib/dist');
 | 
			
		||||
var GossipSeed = require('../src/gossipSeed');
 | 
			
		||||
 | 
			
		||||
var testBase = require('./common/base_test');
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
  'Connect To Endpoint Happy Path': function(test) {
 | 
			
		||||
    test.expect(1);
 | 
			
		||||
    var tcpEndpoint = {host: 'localhost', port: 1113};
 | 
			
		||||
    var conn = client.EventStoreConnection.create(testBase.settings(), tcpEndpoint);
 | 
			
		||||
    conn.connect()
 | 
			
		||||
var withSsl = !!process.env.NODE_ESC_WITH_SSL;
 | 
			
		||||
const evenstStoreType = process.env.EVENTSTORE_CONNECTION_TYPE;
 | 
			
		||||
 | 
			
		||||
module.exports = {}
 | 
			
		||||
 | 
			
		||||
switch(evenstStoreType){
 | 
			
		||||
  case 'gossip':
 | 
			
		||||
    module.exports['Connect to Cluster using gossip seeds'] = function (test) {
 | 
			
		||||
      test.expect(1);
 | 
			
		||||
      var gossipSeeds = [
 | 
			
		||||
        new GossipSeed({host: process.env.EVENTSTORE_HOST_1 || '192.168.33.10', port: 2113}),
 | 
			
		||||
        new GossipSeed({host: process.env.EVENTSTORE_HOST_2 || '192.168.33.11', port: 2113}),
 | 
			
		||||
        new GossipSeed({host: process.env.EVENTSTORE_HOST_3 || '192.168.33.12', port: 2113})
 | 
			
		||||
      ];
 | 
			
		||||
      var conn = client.EventStoreConnection.create(testBase.settings(), gossipSeeds);
 | 
			
		||||
      conn.connect()
 | 
			
		||||
        .catch(function(err) {
 | 
			
		||||
          test.done(err);
 | 
			
		||||
        });
 | 
			
		||||
    conn.on('connected', function(endPoint){
 | 
			
		||||
      test.areEqual("connected endPoint", endPoint, tcpEndpoint);
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
    conn.on('error', done);
 | 
			
		||||
      conn.on('connected', function(endPoint){
 | 
			
		||||
        test.ok(endPoint, 'no endpoint');
 | 
			
		||||
        done();
 | 
			
		||||
      });
 | 
			
		||||
      conn.on('error', done);
 | 
			
		||||
 | 
			
		||||
    function done(err) {
 | 
			
		||||
      conn.close();
 | 
			
		||||
      if (err) return test.done(err);
 | 
			
		||||
      test.done();
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  'Connect To Endpoint That Doesn\'t Exist': function(test) {
 | 
			
		||||
    test.expect(1);
 | 
			
		||||
    var tcpEndpoint = {host: 'localhost', port: 11112};
 | 
			
		||||
    var conn = client.EventStoreConnection.create(testBase.settings({maxReconnections:1}), tcpEndpoint);
 | 
			
		||||
    conn.connect()
 | 
			
		||||
      function done(err) {
 | 
			
		||||
        conn.close();
 | 
			
		||||
        if (err) return test.done(err);
 | 
			
		||||
        test.done();
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    module.exports['Connect To Cluster with bad gossip seeds'] = function (test) {
 | 
			
		||||
      test.expect(3);
 | 
			
		||||
      var gossipSeeds = [
 | 
			
		||||
        new GossipSeed({host: '1.2.3.4', port: 1113}),
 | 
			
		||||
        new GossipSeed({host: '2.3.4.5', port: 2113}),
 | 
			
		||||
        new GossipSeed({host: '3.4.5.6', port: 3113})
 | 
			
		||||
      ];
 | 
			
		||||
      var conn = client.EventStoreConnection.create(testBase.settings({maxDiscoverAttempts: 1}), gossipSeeds);
 | 
			
		||||
      conn.connect()
 | 
			
		||||
        .catch(function (err) {
 | 
			
		||||
          test.ok(err.message.indexOf('Couldn\'t resolve target end point') === 0, 'Wrong expected reason.');
 | 
			
		||||
        });
 | 
			
		||||
      conn.on('connected', function () {
 | 
			
		||||
        test.ok(false, 'Should not be able to connect.');
 | 
			
		||||
      });
 | 
			
		||||
      conn.on('error', function (err) {
 | 
			
		||||
        test.ok(err.message.indexOf('Failed to discover candidate in 1 attempts') === 0, 'Wrong expected reason.');
 | 
			
		||||
      });
 | 
			
		||||
      conn.on('closed', function (reason) {
 | 
			
		||||
        test.ok(reason.indexOf('Failed to resolve TCP end point to which to connect') === 0, 'Wrong expected reason.');
 | 
			
		||||
        test.done();
 | 
			
		||||
      });
 | 
			
		||||
    };
 | 
			
		||||
  break;
 | 
			
		||||
  case 'dns':
 | 
			
		||||
    module.exports['Connect to Cluster using dns discover'] = function (test) {
 | 
			
		||||
      test.expect(1);
 | 
			
		||||
      var clusterDns = 'discover://' + process.env.EVENTSTORE_HOST + ':2113';
 | 
			
		||||
      var conn = client.EventStoreConnection.create(testBase.settings(), clusterDns);
 | 
			
		||||
      conn.connect()
 | 
			
		||||
        .catch(function(err) {
 | 
			
		||||
          test.done(err);
 | 
			
		||||
        });
 | 
			
		||||
      conn.on('connected', function(endPoint){
 | 
			
		||||
        test.ok(endPoint, 'no endpoint');
 | 
			
		||||
        done();
 | 
			
		||||
      });
 | 
			
		||||
      conn.on('error', done);
 | 
			
		||||
 | 
			
		||||
      function done(err) {
 | 
			
		||||
        conn.close();
 | 
			
		||||
        if (err) return test.done(err);
 | 
			
		||||
        test.done();
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    module.exports['Connect To Cluster with bad dns discover'] = function (test) {
 | 
			
		||||
      test.expect(3);
 | 
			
		||||
      var clusterDns = 'discover://abc.def.com:2113';
 | 
			
		||||
      var conn = client.EventStoreConnection.create(testBase.settings({maxDiscoverAttempts: 1}), clusterDns);
 | 
			
		||||
      conn.connect()
 | 
			
		||||
        .catch(function (err) {
 | 
			
		||||
          test.ok(err.message.indexOf('Couldn\'t resolve target end point') === 0, 'Wrong expected reason.');
 | 
			
		||||
        });
 | 
			
		||||
      conn.on('connected', function () {
 | 
			
		||||
        test.ok(false, 'Should not be able to connect.');
 | 
			
		||||
        conn.close();
 | 
			
		||||
      });
 | 
			
		||||
      conn.on('error', function (err) {
 | 
			
		||||
        test.ok(err.message.indexOf('Failed to discover candidate in 1 attempts') === 0, 'Wrong expected reason.');
 | 
			
		||||
      });
 | 
			
		||||
      conn.on('closed', function (reason) {
 | 
			
		||||
        test.ok(reason.indexOf('Failed to resolve TCP end point to which to connect') === 0, 'Wrong expected reason.');
 | 
			
		||||
        test.done();
 | 
			
		||||
      });
 | 
			
		||||
    };
 | 
			
		||||
  break;
 | 
			
		||||
  case 'tcp':
 | 
			
		||||
  default:
 | 
			
		||||
    module.exports['Connect To Endpoint Happy Path'] = function (test) {
 | 
			
		||||
      test.expect(1);
 | 
			
		||||
      var tcpEndpoint = {host: process.env.EVENTSTORE_HOST || 'localhost', port: 1113};
 | 
			
		||||
      var conn = client.EventStoreConnection.create(testBase.settings(), tcpEndpoint);
 | 
			
		||||
      conn.connect()
 | 
			
		||||
        .catch(function (err) {
 | 
			
		||||
          test.done(err);
 | 
			
		||||
        });
 | 
			
		||||
    conn.on('connected', function () {
 | 
			
		||||
      test.ok(false, "Should not be able to connect.");
 | 
			
		||||
      conn.on('connected', function (endPoint) {
 | 
			
		||||
        test.areEqual('connected endPoint', endPoint, tcpEndpoint);
 | 
			
		||||
        done();
 | 
			
		||||
      });
 | 
			
		||||
      conn.on('error', done);
 | 
			
		||||
 | 
			
		||||
      function done(err) {
 | 
			
		||||
        conn.close();
 | 
			
		||||
        if (err) return test.done(err);
 | 
			
		||||
        test.done();
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    module.exports['Connect To Endpoint That Doesn\'t Exist'] = function (test) {
 | 
			
		||||
      test.expect(1);
 | 
			
		||||
      var tcpEndpoint = {host: process.env.EVENTSTORE_HOST || 'localhost', port: 11112};
 | 
			
		||||
      var conn = client.EventStoreConnection.create(testBase.settings({maxReconnections: 1}), tcpEndpoint);
 | 
			
		||||
      conn.connect()
 | 
			
		||||
        .catch(function (err) {
 | 
			
		||||
          test.done(err);
 | 
			
		||||
        });
 | 
			
		||||
      conn.on('connected', function () {
 | 
			
		||||
        test.ok(false, 'Should not be able to connect.');
 | 
			
		||||
        test.done();
 | 
			
		||||
      });
 | 
			
		||||
      conn.on('error', function (err) {
 | 
			
		||||
        test.done(err);
 | 
			
		||||
      });
 | 
			
		||||
      conn.on('closed', function (reason) {
 | 
			
		||||
        test.ok(reason.indexOf('Reconnection limit reached') === 0, 'Wrong expected reason.');
 | 
			
		||||
        test.done();
 | 
			
		||||
      });
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    module.exports['Create a connection with tcp://host:port string'] = function (test) {
 | 
			
		||||
      var conn = client.createConnection({}, `tcp://${process.env.EVENTSTORE_HOST || 'localhost'}:1113`);
 | 
			
		||||
      conn.close();
 | 
			
		||||
      test.done();
 | 
			
		||||
    });
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
if (withSsl) {
 | 
			
		||||
  module.exports['Connect to secure tcp endpoint'] = function(test) {
 | 
			
		||||
    var conn = client.createConnection({
 | 
			
		||||
      useSslConnection: true,
 | 
			
		||||
      targetHost: process.env.EVENTSTORE_HOST || 'localhost',
 | 
			
		||||
      validateServer: false
 | 
			
		||||
    }, `tcp://${process.env.EVENTSTORE_HOST || 'localhost'}:1115`);
 | 
			
		||||
    conn.on('error', function (err) {
 | 
			
		||||
      test.done(err);
 | 
			
		||||
    });
 | 
			
		||||
    conn.on('closed', function(reason) {
 | 
			
		||||
      test.ok(reason.indexOf("Reconnection limit reached") === 0, "Wrong expected reason.");
 | 
			
		||||
      test.done();
 | 
			
		||||
    });
 | 
			
		||||
  },
 | 
			
		||||
  'Create a connection with tcp://host:port string': function(test) {
 | 
			
		||||
    var conn = client.createConnection({}, 'tcp://localhost:1113');
 | 
			
		||||
    conn.close();
 | 
			
		||||
    test.done();
 | 
			
		||||
  }/*,
 | 
			
		||||
  'Connect to Cluster using gossip seeds': function (test) {
 | 
			
		||||
    test.expect(1);
 | 
			
		||||
    var gossipSeeds = [
 | 
			
		||||
      new GossipSeed({host: 'localhost', port: 1113}),
 | 
			
		||||
      new GossipSeed({host: 'localhost', port: 2113}),
 | 
			
		||||
      new GossipSeed({host: 'localhost', port: 3113})
 | 
			
		||||
    ];
 | 
			
		||||
    var conn = client.EventStoreConnection.create(testBase.settings(), gossipSeeds);
 | 
			
		||||
    conn.connect()
 | 
			
		||||
      .catch(function(err) {
 | 
			
		||||
      .catch(function (err) {
 | 
			
		||||
        test.done(err);
 | 
			
		||||
      });
 | 
			
		||||
    conn.on('connected', function(endPoint){
 | 
			
		||||
      test.ok(endPoint, "no endpoint");
 | 
			
		||||
      done();
 | 
			
		||||
    });
 | 
			
		||||
    conn.on('error', done);
 | 
			
		||||
 | 
			
		||||
    function done(err) {
 | 
			
		||||
      conn.close();
 | 
			
		||||
      if (err) return test.done(err);
 | 
			
		||||
    conn.on('connected', function () {
 | 
			
		||||
      test.done();
 | 
			
		||||
    }
 | 
			
		||||
  }*/
 | 
			
		||||
};
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
testBase.init(module.exports, false);
 | 
			
		||||
testBase.init(module.exports, false);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
var uuid = require('uuid');
 | 
			
		||||
var client = require('../src/client');
 | 
			
		||||
var client = require('../lib/dist');
 | 
			
		||||
var Long = require('long');
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
  setUp: function(cb) {
 | 
			
		||||
@@ -16,7 +17,7 @@ module.exports = {
 | 
			
		||||
  'Test Delete Stream Soft Happy Path': function(test) {
 | 
			
		||||
    test.expect(4);
 | 
			
		||||
    var self = this;
 | 
			
		||||
    this.conn.deleteStream(this.testStreamName, 1, false)
 | 
			
		||||
    this.conn.deleteStream(this.testStreamName, Long.fromNumber(1), false)
 | 
			
		||||
        .then(function(result) {
 | 
			
		||||
          test.ok(result.logPosition, "No log position in result.");
 | 
			
		||||
          return self.conn.getStreamMetadataRaw(self.testStreamName);
 | 
			
		||||
@@ -34,7 +35,7 @@ module.exports = {
 | 
			
		||||
  'Test Delete Stream Hard Happy Path': function(test) {
 | 
			
		||||
    test.expect(4);
 | 
			
		||||
    var self = this;
 | 
			
		||||
    this.conn.deleteStream(this.testStreamName, 1, true)
 | 
			
		||||
    this.conn.deleteStream(this.testStreamName, Long.fromNumber(1), true)
 | 
			
		||||
        .then(function(result) {
 | 
			
		||||
          test.ok(result.logPosition, "No log position in result.");
 | 
			
		||||
          return self.conn.getStreamMetadataRaw(self.testStreamName);
 | 
			
		||||
@@ -51,7 +52,7 @@ module.exports = {
 | 
			
		||||
  },
 | 
			
		||||
  'Test Delete Stream With Wrong Expected Version': function(test) {
 | 
			
		||||
    test.expect(1);
 | 
			
		||||
    this.conn.deleteStream(this.testStreamName, 10)
 | 
			
		||||
    this.conn.deleteStream(this.testStreamName, Long.fromNumber(10))
 | 
			
		||||
        .then(function(result) {
 | 
			
		||||
          test.fail("Delete succeeded but should have failed.");
 | 
			
		||||
          test.done();
 | 
			
		||||
@@ -68,7 +69,7 @@ module.exports = {
 | 
			
		||||
    var self = this;
 | 
			
		||||
    this.conn.setStreamMetadataRaw(this.testStreamName, client.expectedVersion.any, {$acl: {$d: "$admins"}})
 | 
			
		||||
        .then(function() {
 | 
			
		||||
          return self.conn.deleteStream(self.testStreamName, 10);
 | 
			
		||||
          return self.conn.deleteStream(self.testStreamName, Long.fromNumber(10));
 | 
			
		||||
        })
 | 
			
		||||
        .then(function(result) {
 | 
			
		||||
          test.fail("Delete succeeded but should have failed.");
 | 
			
		||||
@@ -86,7 +87,7 @@ module.exports = {
 | 
			
		||||
    var self = this;
 | 
			
		||||
    this.conn.deleteStream(this.testStreamName, 1, true)
 | 
			
		||||
        .then(function() {
 | 
			
		||||
          return self.conn.deleteStream(self.testStreamName, 1, true);
 | 
			
		||||
          return self.conn.deleteStream(self.testStreamName, Long.fromNumber(1), true);
 | 
			
		||||
        })
 | 
			
		||||
        .then(function(result) {
 | 
			
		||||
          test.fail("Delete succeeded but should have failed.");
 | 
			
		||||
@@ -101,4 +102,4 @@ module.exports = {
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
require('./common/base_test').init(module.exports);
 | 
			
		||||
require('./common/base_test').init(module.exports);
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user