Skip to content
This repository was archived by the owner on Mar 23, 2023. It is now read-only.

Commit 724c3e8

Browse files
author
Zane Starr
committed
Refactor fs datastore to us async/await
1 parent 45ec48b commit 724c3e8

File tree

3 files changed

+123
-161
lines changed

3 files changed

+123
-161
lines changed

package.json

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,15 @@
3535
"homepage": "https://github.com/ipfs/js-datastore-fs#readme",
3636
"dependencies": {
3737
"async": "^2.6.1",
38-
"datastore-core": "~0.6.0",
38+
"datastore-core": "git://github.com:zcstarr/js-datastore-core.git",
3939
"fast-write-atomic": "~0.2.0",
4040
"glob": "^7.1.3",
4141
"graceful-fs": "^4.1.11",
42-
"interface-datastore": "~0.6.0",
43-
"mkdirp": "~0.5.1",
44-
"pull-stream": "^3.6.9"
42+
"interface-datastore": "git://github.com/ipfs/interface-datastore.git#refactor/async-iterators",
43+
"mkdirp": "~0.5.1"
4544
},
4645
"devDependencies": {
47-
"aegir": "^15.3.1",
46+
"aegir": "^18.2.0",
4847
"chai": "^4.2.0",
4948
"cids": "~0.5.5",
5049
"dirty-chai": "^2.0.1",

src/index.js

Lines changed: 81 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,23 @@
44
/* :: import type {Batch, Query, QueryResult, Callback} from 'interface-datastore' */
55

66
const fs = require('graceful-fs')
7-
const pull = require('pull-stream')
87
const glob = require('glob')
9-
const setImmediate = require('async/setImmediate')
10-
const waterfall = require('async/series')
11-
const each = require('async/each')
128
const mkdirp = require('mkdirp')
13-
const writeFile = require('fast-write-atomic')
9+
const promisify = require('util').promisify
10+
const writeFile = promisify(require('fast-write-atomic'))
1411
const path = require('path')
1512

16-
const asyncFilter = require('interface-datastore').utils.asyncFilter
17-
const asyncSort = require('interface-datastore').utils.asyncSort
13+
const filter = require('interface-datastore').utils.filter
14+
const take = require('interface-datastore').utils.take
15+
const map = require('interface-datastore').utils.map
16+
const sortAll = require('interface-datastore').utils.sortAll
1817
const IDatastore = require('interface-datastore')
18+
19+
const asyncMkdirp = promisify(require('mkdirp'))
20+
const fsAccess = promisify(fs.access)
21+
const fsReadFile = promisify(fs.readFile)
22+
const fsUnlink = promisify(fs.unlink)
23+
1924
const Key = IDatastore.Key
2025
const Errors = IDatastore.Errors
2126

@@ -57,9 +62,8 @@ class FsDatastore {
5762
}
5863
}
5964

60-
open (callback /* : Callback<void> */) /* : void */ {
65+
open () /* : void */ {
6166
this._openOrCreate()
62-
setImmediate(callback)
6367
}
6468

6569
/**
@@ -150,104 +154,97 @@ class FsDatastore {
150154
*
151155
* @param {Key} key
152156
* @param {Buffer} val
153-
* @param {function(Error)} callback
154-
* @returns {void}
157+
* @returns {Promise<void>}
155158
*/
156-
putRaw (key /* : Key */, val /* : Buffer */, callback /* : Callback<void> */) /* : void */ {
159+
async putRaw (key /* : Key */, val /* : Buffer */) /* : void */ {
157160
const parts = this._encode(key)
158161
const file = parts.file.slice(0, -this.opts.extension.length)
159-
waterfall([
160-
(cb) => mkdirp(parts.dir, { fs: fs }, cb),
161-
(cb) => writeFile(file, val, cb)
162-
], (err) => callback(err))
162+
await asyncMkdirp(parts.dir, { fs: fs })
163+
await writeFile(file, val)
163164
}
164165

165166
/**
166167
* Store the given value under the key.
167168
*
168169
* @param {Key} key
169170
* @param {Buffer} val
170-
* @param {function(Error)} callback
171-
* @returns {void}
171+
* @returns {Promise<void>}
172172
*/
173-
put (key /* : Key */, val /* : Buffer */, callback /* : Callback<void> */) /* : void */ {
173+
async put (key /* : Key */, val /* : Buffer */) /* : void */ {
174174
const parts = this._encode(key)
175-
waterfall([
176-
(cb) => mkdirp(parts.dir, { fs: fs }, cb),
177-
(cb) => writeFile(parts.file, val, cb)
178-
], (err) => {
179-
if (err) {
180-
return callback(Errors.dbWriteFailedError(err))
181-
}
182-
callback()
183-
})
175+
try {
176+
await asyncMkdirp(parts.dir, { fs: fs })
177+
await writeFile(parts.file, val)
178+
} catch (err) {
179+
throw Errors.dbWriteFailedError(err)
180+
}
184181
}
185182

186183
/**
187184
* Read from the file system without extension.
188185
*
189186
* @param {Key} key
190-
* @param {function(Error, Buffer)} callback
191-
* @returns {void}
187+
* @returns {Promise<Buffer>}
192188
*/
193-
getRaw (key /* : Key */, callback /* : Callback<Buffer> */) /* : void */ {
189+
async getRaw (key /* : Key */) /* : void */ {
194190
const parts = this._encode(key)
195191
let file = parts.file
196192
file = file.slice(0, -this.opts.extension.length)
197-
fs.readFile(file, (err, data) => {
198-
if (err) {
199-
return callback(Errors.notFoundError(err))
200-
}
201-
callback(null, data)
202-
})
193+
let data
194+
try {
195+
data = await fsReadFile(file)
196+
} catch (err) {
197+
throw Errors.notFoundError(err)
198+
}
199+
return data
203200
}
204201

205202
/**
206203
* Read from the file system.
207204
*
208205
* @param {Key} key
209-
* @param {function(Error, Buffer)} callback
210-
* @returns {void}
206+
* @returns {Promise<Buffer>}
211207
*/
212-
get (key /* : Key */, callback /* : Callback<Buffer> */) /* : void */ {
208+
async get (key /* : Key */) /* : void */ {
213209
const parts = this._encode(key)
214-
fs.readFile(parts.file, (err, data) => {
215-
if (err) {
216-
return callback(Errors.notFoundError(err))
217-
}
218-
callback(null, data)
219-
})
210+
let data
211+
try {
212+
data = await fsReadFile(parts.file)
213+
} catch (err) {
214+
throw Errors.notFoundError(err)
215+
}
216+
return data
220217
}
221218

222219
/**
223220
* Check for the existence of the given key.
224221
*
225222
* @param {Key} key
226-
* @param {function(Error, bool)} callback
227-
* @returns {void}
223+
* @returns {Promise<bool>}
228224
*/
229-
has (key /* : Key */, callback /* : Callback<bool> */) /* : void */ {
225+
async has (key /* : Key */) /* : void */ {
230226
const parts = this._encode(key)
231-
fs.access(parts.file, err => {
232-
callback(null, !err)
233-
})
227+
try {
228+
await fsAccess(parts.file)
229+
} catch (err) {
230+
return false
231+
}
232+
return true
234233
}
235234

236235
/**
237236
* Delete the record under the given key.
238237
*
239238
* @param {Key} key
240-
* @param {function(Error)} callback
241-
* @returns {void}
239+
* @returns {Promise<void>}
242240
*/
243-
delete (key /* : Key */, callback /* : Callback<void> */) /* : void */ {
241+
async delete (key /* : Key */) /* : void */ {
244242
const parts = this._encode(key)
245-
fs.unlink(parts.file, (err) => {
246-
if (err) {
247-
return callback(Errors.dbDeleteFailedError(err))
248-
}
249-
callback()
250-
})
243+
try {
244+
await fsUnlink(parts.file)
245+
} catch (err) {
246+
throw Errors.dbDeleteFailedError(err)
247+
}
251248
}
252249

253250
/**
@@ -265,15 +262,9 @@ class FsDatastore {
265262
delete (key /* : Key */) /* : void */ {
266263
deletes.push(key)
267264
},
268-
commit: (callback /* : (err: ?Error) => void */) => {
269-
waterfall([
270-
(cb) => each(puts, (p, cb) => {
271-
this.put(p.key, p.value, cb)
272-
}, cb),
273-
(cb) => each(deletes, (k, cb) => {
274-
this.delete(k, cb)
275-
}, cb)
276-
], (err) => callback(err))
265+
commit: async () /* : Promise<void> */ => {
266+
await Promise.all((puts.map((put) => this.put(put.key, put.value))))
267+
await Promise.all((deletes.map((del) => this.delete(del))))
277268
}
278269
}
279270
}
@@ -282,7 +273,7 @@ class FsDatastore {
282273
* Query the store.
283274
*
284275
* @param {Object} q
285-
* @returns {PullStream}
276+
* @returns {Iterable}
286277
*/
287278
query (q /* : Query<Buffer> */) /* : QueryResult<Buffer> */ {
288279
// glob expects a POSIX path
@@ -291,53 +282,46 @@ class FsDatastore {
291282
.join(this.path, prefix, '*' + this.opts.extension)
292283
.split(path.sep)
293284
.join('/')
294-
let tasks = [pull.values(glob.sync(pattern))]
295-
285+
let files = glob.sync(pattern)
286+
let it
296287
if (!q.keysOnly) {
297-
tasks.push(pull.asyncMap((f, cb) => {
298-
fs.readFile(f, (err, buf) => {
299-
if (err) {
300-
return cb(err)
301-
}
302-
cb(null, {
303-
key: this._decode(f),
304-
value: buf
305-
})
306-
})
307-
}))
288+
it = map(files, async (f) => {
289+
const buf = await fsReadFile(f)
290+
return {
291+
key: this._decode(f),
292+
value: buf
293+
}
294+
})
308295
} else {
309-
tasks.push(pull.map(f => ({ key: this._decode(f) })))
296+
it = map(files, f => ({ key: this._decode(f) }))
310297
}
311298

312-
if (q.filters != null) {
313-
tasks = tasks.concat(q.filters.map(asyncFilter))
299+
if (Array.isArray(q.filters)) {
300+
it = q.filters.reduce((it, f) => filter(it, f), it)
314301
}
315302

316-
if (q.orders != null) {
317-
tasks = tasks.concat(q.orders.map(asyncSort))
303+
if (Array.isArray(q.orders)) {
304+
it = q.orders.reduce((it, f) => sortAll(it, f), it)
318305
}
319306

320307
if (q.offset != null) {
321308
let i = 0
322-
tasks.push(pull.filter(() => i++ >= q.offset))
309+
it = filter(it, () => i++ >= q.offset)
323310
}
324311

325312
if (q.limit != null) {
326-
tasks.push(pull.take(q.limit))
313+
it = take(it, q.limit)
327314
}
328315

329-
return pull.apply(null, tasks)
316+
return it
330317
}
331318

332319
/**
333320
* Close the store.
334321
*
335-
* @param {function(Error)} callback
336-
* @returns {void}
322+
* @returns {Promise<void>}
337323
*/
338-
close (callback /* : (err: ?Error) => void */) /* : void */ {
339-
setImmediate(callback)
340-
}
324+
async close () /* : Promise<void> */ { }
341325
}
342326

343327
module.exports = FsDatastore

0 commit comments

Comments
 (0)