hypercore 10.12.0 → 10.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +21 -2
- package/lib/batch.js +114 -0
- package/lib/errors.js +12 -0
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -14,8 +14,16 @@ const Core = require('./lib/core')
|
|
|
14
14
|
const BlockEncryption = require('./lib/block-encryption')
|
|
15
15
|
const Info = require('./lib/info')
|
|
16
16
|
const Download = require('./lib/download')
|
|
17
|
+
const Batch = require('./lib/batch')
|
|
17
18
|
const { ReadStream, WriteStream, ByteStream } = require('./lib/streams')
|
|
18
|
-
const {
|
|
19
|
+
const {
|
|
20
|
+
BAD_ARGUMENT,
|
|
21
|
+
BATCH_ALREADY_EXISTS,
|
|
22
|
+
BATCH_UNFLUSHED,
|
|
23
|
+
SESSION_CLOSED,
|
|
24
|
+
SESSION_NOT_WRITABLE,
|
|
25
|
+
SNAPSHOT_NOT_AVAILABLE
|
|
26
|
+
} = require('./lib/errors')
|
|
19
27
|
|
|
20
28
|
const promises = Symbol.for('hypercore.promises')
|
|
21
29
|
const inspect = Symbol.for('nodejs.util.inspect.custom')
|
|
@@ -82,6 +90,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
82
90
|
|
|
83
91
|
this._preappend = preappend.bind(this)
|
|
84
92
|
this._snapshot = null
|
|
93
|
+
this._batch = opts._batch || null
|
|
85
94
|
this._findingPeers = 0
|
|
86
95
|
}
|
|
87
96
|
|
|
@@ -214,7 +223,8 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
214
223
|
timeout,
|
|
215
224
|
writable,
|
|
216
225
|
_opening: this.opening,
|
|
217
|
-
_sessions: this.sessions
|
|
226
|
+
_sessions: this.sessions,
|
|
227
|
+
_batch: this._batch
|
|
218
228
|
})
|
|
219
229
|
|
|
220
230
|
s._passCapabilities(this)
|
|
@@ -684,6 +694,13 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
684
694
|
return true
|
|
685
695
|
}
|
|
686
696
|
|
|
697
|
+
batch () {
|
|
698
|
+
if (this._batch !== null) throw BATCH_ALREADY_EXISTS()
|
|
699
|
+
const batch = new Batch(this)
|
|
700
|
+
for (const session of this.sessions) session._batch = batch
|
|
701
|
+
return batch
|
|
702
|
+
}
|
|
703
|
+
|
|
687
704
|
async seek (bytes, opts) {
|
|
688
705
|
if (this.opened === false) await this.opening
|
|
689
706
|
|
|
@@ -846,6 +863,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
846
863
|
}
|
|
847
864
|
|
|
848
865
|
async truncate (newLength = 0, fork = -1) {
|
|
866
|
+
if (this._batch && !this._batch.flushed) throw BATCH_UNFLUSHED()
|
|
849
867
|
if (this.opened === false) await this.opening
|
|
850
868
|
if (this.writable === false) throw SESSION_NOT_WRITABLE()
|
|
851
869
|
|
|
@@ -857,6 +875,7 @@ module.exports = class Hypercore extends EventEmitter {
|
|
|
857
875
|
}
|
|
858
876
|
|
|
859
877
|
async append (blocks) {
|
|
878
|
+
if (this._batch && !this._batch.flushed) throw BATCH_UNFLUSHED()
|
|
860
879
|
if (this.opened === false) await this.opening
|
|
861
880
|
if (this.writable === false) throw SESSION_NOT_WRITABLE()
|
|
862
881
|
|
package/lib/batch.js
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
const { SESSION_NOT_WRITABLE, BATCH_ALREADY_FLUSHED } = require('./errors')
|
|
2
|
+
|
|
3
|
+
module.exports = class Batch {
|
|
4
|
+
constructor (session) {
|
|
5
|
+
this.session = session
|
|
6
|
+
this.flushed = false
|
|
7
|
+
|
|
8
|
+
this._appends = []
|
|
9
|
+
this._byteLength = 0
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
get length () {
|
|
13
|
+
return this.session.length + this._appends.length
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
ready () {
|
|
17
|
+
return this.session.ready()
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async info (opts) {
|
|
21
|
+
const session = this.session
|
|
22
|
+
const info = await session.info(opts)
|
|
23
|
+
|
|
24
|
+
if (info.contiguousLength === info.length) {
|
|
25
|
+
info.contiguousLength = info.length += this._appends.length
|
|
26
|
+
} else {
|
|
27
|
+
info.length += this._appends.length
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
info.byteLength += this._byteLength
|
|
31
|
+
|
|
32
|
+
return info
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async get (index, opts) {
|
|
36
|
+
const session = this.session
|
|
37
|
+
if (session.opened === false) await session.opening
|
|
38
|
+
|
|
39
|
+
const length = this.session.length
|
|
40
|
+
if (index < length) return this.session.get(index, opts)
|
|
41
|
+
|
|
42
|
+
return this._appends[index - length] || null
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async truncate (newLength) {
|
|
46
|
+
if (this.flushed) throw BATCH_ALREADY_FLUSHED()
|
|
47
|
+
|
|
48
|
+
const session = this.session
|
|
49
|
+
if (session.opened === false) await session.opening
|
|
50
|
+
if (session.writable === false) throw SESSION_NOT_WRITABLE()
|
|
51
|
+
|
|
52
|
+
const length = session.length
|
|
53
|
+
if (newLength < length) throw new Error('Cannot truncate committed blocks')
|
|
54
|
+
|
|
55
|
+
this._appends.length = newLength - length
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async append (blocks) {
|
|
59
|
+
if (this.flushed) throw BATCH_ALREADY_FLUSHED()
|
|
60
|
+
|
|
61
|
+
const session = this.session
|
|
62
|
+
if (session.opened === false) await session.opening
|
|
63
|
+
if (session.writable === false) throw SESSION_NOT_WRITABLE()
|
|
64
|
+
|
|
65
|
+
blocks = Array.isArray(blocks) ? blocks : [blocks]
|
|
66
|
+
|
|
67
|
+
const buffers = session.encodeBatch !== null
|
|
68
|
+
? session.encodeBatch(blocks)
|
|
69
|
+
: new Array(blocks.length)
|
|
70
|
+
|
|
71
|
+
if (session.encodeBatch === null) {
|
|
72
|
+
for (let i = 0; i < blocks.length; i++) {
|
|
73
|
+
const buffer = session._encode(session.valueEncoding, blocks[i])
|
|
74
|
+
buffers[i] = buffer
|
|
75
|
+
this._byteLength += buffer.byteLength
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
this._appends.push(...buffers)
|
|
80
|
+
|
|
81
|
+
const byteLength = session.byteLength + this._byteLength
|
|
82
|
+
|
|
83
|
+
return { length: this.length, byteLength }
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async flush () {
|
|
87
|
+
if (this.flushed) throw BATCH_ALREADY_FLUSHED()
|
|
88
|
+
this.flushed = true
|
|
89
|
+
|
|
90
|
+
try {
|
|
91
|
+
if (this._appends.length) await this.session.append(this._appends)
|
|
92
|
+
} finally {
|
|
93
|
+
this._clearBatch()
|
|
94
|
+
this._clearAppends()
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async close () {
|
|
99
|
+
if (this.flushed) throw BATCH_ALREADY_FLUSHED()
|
|
100
|
+
this.flushed = true
|
|
101
|
+
|
|
102
|
+
this._clearBatch()
|
|
103
|
+
this._clearAppends()
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
_clearAppends () {
|
|
107
|
+
this._appends = []
|
|
108
|
+
this._byteLength = 0
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
_clearBatch () {
|
|
112
|
+
for (const session of this.session.sessions) session._batch = null
|
|
113
|
+
}
|
|
114
|
+
}
|
package/lib/errors.js
CHANGED
|
@@ -64,6 +64,18 @@ module.exports = class HypercoreError extends Error {
|
|
|
64
64
|
return new HypercoreError(msg, 'SESSION_CLOSED', HypercoreError.SESSION_CLOSED)
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
+
static BATCH_UNFLUSHED (msg = 'Batch not yet flushed') {
|
|
68
|
+
return new HypercoreError(msg, 'BATCH_UNFLUSHED', HypercoreError.BATCH_UNFLUSHED)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
static BATCH_ALREADY_EXISTS (msg = 'Batch already exists') {
|
|
72
|
+
return new HypercoreError(msg, 'BATCH_ALREADY_EXISTS', HypercoreError.BATCH_ALREADY_EXISTS)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
static BATCH_ALREADY_FLUSHED (msg = 'Batch has already been flushed') {
|
|
76
|
+
return new HypercoreError(msg, 'BATCH_ALREADY_FLUSHED', HypercoreError.BATCH_ALREADY_FLUSHED)
|
|
77
|
+
}
|
|
78
|
+
|
|
67
79
|
static OPLOG_CORRUPT (msg = 'Oplog file appears corrupt or out of date') {
|
|
68
80
|
return new HypercoreError(msg, 'OPLOG_CORRUPT', HypercoreError.OPLOG_CORRUPT)
|
|
69
81
|
}
|