Skip to content

Commit f3fc25c

Browse files
committed
Refactoring + better error handling
1 parent 108cd84 commit f3fc25c

File tree

3 files changed

+127
-120
lines changed

3 files changed

+127
-120
lines changed

bin/stop.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@ exports.handler = async function (argv) {
1717
})
1818
console.log(chalk.green(`The Hypermount daemon has been stopped.`))
1919
} catch (err) {
20-
console.log('err:', err)
21-
console.error(chalk.red(`Could not stop the daemon.`))
20+
console.error(chalk.red(`Could not stop the daemon. Are you using any mountpoints?`))
2221
}
2322
}
2423
}

index.js

Lines changed: 124 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,21 @@ const mkdirp = require('mkdirp')
1111
const collect = require('collect-stream')
1212
const argv = require('yargs').argv
1313

14-
const { loadMetadata } = require('./lib/metadata')
14+
const hypercore = require('hypercore')
1515

16-
const Status = {
17-
UNMOUNTED: 0,
18-
MOUNTED: 1
19-
}
16+
const { loadMetadata } = require('./lib/metadata')
2017

2118
class Hypermount {
22-
constructor (store) {
19+
constructor (store, db) {
2320
this.store = store
21+
this.db = db
2422
this.drives = new Map()
2523
}
2624

25+
ready () {
26+
return this.store.ready()
27+
}
28+
2729
async mount (key, mnt, opts) {
2830
if (typeof opts === 'function') return this.mount(key, mnt, null, opts)
2931
opts = opts || {}
@@ -32,14 +34,18 @@ class Hypermount {
3234
coreOpts.seed = (opts.seed !== undefined) ? opts.seed : true
3335
return this.store.get(key, coreOpts)
3436
}
37+
3538
const drive = hyperdrive(factory, key, {
3639
...opts,
3740
factory: true,
3841
sparse: (opts.sparse !== undefined) ? opts.sparse : true,
3942
sparseMetadata: (opts.sparseMetadata !== undefined) ? opts.sparseMetadata : true
4043
})
4144

42-
const mountInfo = await hyperfuse.mount(drive, mnt)
45+
const mountInfo = await hyperfuse.mount(drive, mnt, {
46+
force: true,
47+
displayFolder: true
48+
})
4349
this.drives.set(mountInfo.key, drive)
4450

4551
return mountInfo
@@ -52,32 +58,89 @@ class Hypermount {
5258
close () {
5359
return this.store.close()
5460
}
55-
}
5661

57-
async function start () {
58-
const metadata = await loadMetadata()
59-
const storageRoot = argv.storage || './storage'
62+
async mount (key, mnt, opts) {
63+
let { key: mountedKey } = await this.mount(key, mnt, opts)
6064

61-
await (() => {
65+
await this.db.put(mnt, {
66+
...opts,
67+
key: mountedKey,
68+
mnt
69+
})
70+
71+
return mountedKey
72+
}
73+
74+
async unmount (mnt) {
75+
await this.unmount(mnt)
76+
77+
let record = await this.db.get(mnt)
78+
if (!record) return
79+
80+
await this.db.put(mnt, record)
81+
}
82+
83+
unmountAll () {
6284
return new Promise((resolve, reject) => {
63-
mkdirp(storageRoot, err => {
64-
if (err) return reject(err)
65-
return resolve()
85+
pump(
86+
this.db.createReadStream(),
87+
through.obj(({ key, value: record }, enc, cb) => {
88+
let unmountPromise = this.unmount(key)
89+
unmountPromise.then(() => cb(null))
90+
unmountPromise.catch(err => cb(err))
91+
}),
92+
err => {
93+
if (err) return reject(err)
94+
return resolve()
95+
}
96+
)
97+
})
98+
}
99+
100+
refreshMounts () {
101+
return new Promise((resolve, reject) => {
102+
pump(
103+
this.db.createReadStream(),
104+
through.obj(({ key, value: record }, enc, cb) => {
105+
const mountPromise = this.mount(record.key, key, record)
106+
mountPromise.then(() => cb(null))
107+
mountPromise.catch(cb)
108+
}),
109+
err => {
110+
if (err) return reject(err)
111+
return resolve()
112+
}
113+
)
114+
})
115+
}
116+
117+
list () {
118+
return new Promise((resolve, reject) => {
119+
const result = {}
120+
const stream = this.db.createReadStream()
121+
stream.on('data', ({ key: mnt, value: record }) => {
122+
const entry = result[record.key] = { mnt }
123+
const drive = this.drives.get(record.key)
124+
entry.networking = {
125+
metadata: drive.metadata.stats,
126+
content: drive.content && drive.content.stats
127+
}
128+
})
129+
stream.on('end', () => {
130+
return resolve(result)
66131
})
132+
stream.on('error', reject)
67133
})
68-
})()
134+
}
69135

70-
const store = corestore(p.join(storageRoot, 'cores'), {
71-
network: {
72-
port: argv.replicationPort || 3006
73-
}
74-
})
75-
const db = level(p.join(storageRoot, 'db'), {
76-
valueEncoding: 'json'
77-
})
78-
const hypermount = new Hypermount(store)
79-
const app = express()
136+
async cleanup () {
137+
await this.unmountAll()
138+
await this.store.close()
139+
await this.db.close()
140+
}
141+
}
80142

143+
function bindRoutes (app, hypermount) {
81144
app.use(express.json())
82145
app.use((req, res, next) => {
83146
if (!req.headers.authorization) return res.sendStatus(403)
@@ -88,7 +151,7 @@ async function start () {
88151
app.post('/mount', async (req, res) => {
89152
try {
90153
let { key, mnt } = req.body
91-
key = await mount(hypermount, db, key, mnt, req.body)
154+
key = await hypermount.mount(key, mnt, req.body)
92155
return res.status(201).json({ key, mnt })
93156
} catch (err) {
94157
console.error('Mount error:', err)
@@ -99,7 +162,7 @@ async function start () {
99162
app.post('/unmount', async (req, res) => {
100163
try {
101164
const mnt = req.body.mnt
102-
await unmount(hypermount, db, mnt)
165+
await hypermount.unmount(mnt)
103166

104167
return res.sendStatus(200)
105168
} catch (err) {
@@ -124,113 +187,56 @@ async function start () {
124187

125188
app.get('/list', async (req, res) => {
126189
try {
127-
let result = await list(hypermount, db)
190+
let result = await hypermount.list()
128191
return res.json(result)
129192
} catch (err) {
130193
console.error('List error:', err)
131194
return res.sendStatus(500)
132195
}
133196
})
134-
135-
await store.ready()
136-
await refreshMounts(hypermount, db)
137-
138-
process.once('SIGINT', cleanup)
139-
process.once('SIGTERM', cleanup)
140-
141-
var server = app.listen(argv.port || 3005)
142-
143-
async function cleanup () {
144-
await unmountAll(hypermount, db)
145-
await store.close()
146-
await db.close()
147-
server.close()
148-
}
149197
}
150198

151-
function list (hypermount, db) {
152-
return new Promise((resolve, reject) => {
153-
const result = {}
154-
const stream = db.createReadStream()
155-
stream.on('data', ({ key: mnt, value: record }) => {
156-
const entry = result[record.key] = { mnt }
157-
const drive = hypermount.drives.get(record.key)
158-
entry.networking = {
159-
metadata: drive.metadata.stats,
160-
content: drive.content && drive.content.stats
161-
}
162-
})
163-
stream.on('end', () => {
164-
return resolve(result)
165-
})
166-
stream.on('error', reject)
167-
})
168-
}
199+
async function start () {
200+
const metadata = await loadMetadata()
201+
const storageRoot = argv.storage || './storage'
169202

170-
async function mount (hypermount, db, key, mnt, opts) {
171-
let { key: mountedKey } = await hypermount.mount(key, mnt, opts)
203+
await (() => {
204+
return new Promise((resolve, reject) => {
205+
mkdirp(storageRoot, err => {
206+
if (err) return reject(err)
207+
return resolve()
208+
})
209+
})
210+
})()
172211

173-
await db.put(mnt, {
174-
...opts,
175-
key: mountedKey,
176-
mnt,
177-
status: Status.MOUNTED
212+
const store = corestore(p.join(storageRoot, 'cores'), {
213+
network: {
214+
port: argv.replicationPort || 3006
215+
}
178216
})
217+
const db = level(p.join(storageRoot, 'db'), {
218+
valueEncoding: 'json'
219+
})
220+
const hypermount = new Hypermount(store, db)
221+
const app = express()
179222

180-
return mountedKey
181-
}
182-
183-
async function unmount (hypermount, db, mnt) {
184-
await hypermount.unmount(mnt)
223+
await hypermount.ready()
224+
await hypermount.refreshMounts()
185225

186-
let record = await db.get(mnt)
187-
if (!record) return
188-
record.status = Status.UNMOUNTED
226+
bindRoutes(app, hypermount)
227+
var server = app.listen(argv.port || 3005)
189228

190-
await db.put(mnt, record)
191-
}
229+
process.once('SIGINT', cleanup)
230+
process.once('SIGTERM', cleanup)
231+
process.once('unhandledRejection', cleanup)
232+
process.once('uncaughtException', cleanup)
192233

193-
function unmountAll (hypermount, db) {
194-
return new Promise((resolve, reject) => {
195-
pump(
196-
db.createReadStream(),
197-
through.obj(({ key, value: record }, enc, cb) => {
198-
if (record.status === Status.MOUNTED) {
199-
let unmountPromise = unmount(hypermount, db, key)
200-
unmountPromise.then(() => cb(null))
201-
unmountPromise.catch(err => cb(err))
202-
} else {
203-
return cb(null)
204-
}
205-
}),
206-
err => {
207-
if (err) return reject(err)
208-
return resolve()
209-
}
210-
)
211-
})
234+
async function cleanup () {
235+
await hypermount.cleanup()
236+
server.close()
237+
}
212238
}
213239

214-
function refreshMounts (hypermount, db) {
215-
return new Promise((resolve, reject) => {
216-
pump(
217-
db.createReadStream(),
218-
through.obj(({ key, value: record }, enc, cb) => {
219-
if (record.status === Status.UNMOUNTED) {
220-
const mountPromise = mount(hypermount, db, record.key, key, record)
221-
mountPromise.then(() => cb(null))
222-
mountPromise.catch(cb)
223-
} else {
224-
return cb(null)
225-
}
226-
}),
227-
err => {
228-
if (err) return reject(err)
229-
return resolve()
230-
}
231-
)
232-
})
233-
}
234240

235241
if (require.main === module) {
236242
start()

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,13 @@
3333
"forever": "^0.15.3",
3434
"forever-monitor": "^1.7.1",
3535
"fs-extra": "^7.0.1",
36+
"hypercore": "^6.26.0",
3637
"hyperdrive": "^10.0.0-rc0",
3738
"hyperdrive-fuse": "^1.0.0-rc0",
3839
"level": "^4.0.0",
3940
"mkdirp": "^0.5.1",
4041
"ora": "^3.4.0",
42+
"random-access-memory": "^3.1.1",
4143
"request": "^2.88.0",
4244
"request-promise-native": "^1.0.7",
4345
"sodium-universal": "^2.0.0",

0 commit comments

Comments
 (0)