-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathzipbuilder.js
More file actions
143 lines (132 loc) · 4.4 KB
/
zipbuilder.js
File metadata and controls
143 lines (132 loc) · 4.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// node
var fs = require('fs')
// npm
var Promise = require('bluebird')
var rethink = require('rethinkdb')
var then_redis = require('then-redis')
var mkdirp = Promise.promisify(require('mkdirp'))
// local
var major_version = 2
var settings = require('./lib/settings')(major_version)
var emailer = require('./lib/email').factory(settings.email)
var r = rethink.connect(settings.rethinkdb)
var redis = then_redis.createClient();
var lock = false
cleanUp()
downloadCheck()
setInterval(downloadCheck, 30 * 1000)
function cleanUp() {
redis.hgetall('zipq')
.then(function(zipq) {
var keys = Object.keys(zipq)
keys.forEach(function(user_id) {
var list = JSON.parse(zipq[user_id])
list.forEach(function(entry, idx) {
if (entry.status == 'building') {
// broken
console.log('clean', entry, idx)
list[idx] = null
}
})
list = list.filter(function(e) { return e })
redis.hset('zipq', user_id, JSON.stringify(list))
})
})
}
function downloadCheck() {
console.log('## dumpQueueCheck', new Date())
if (lock) { console.log('abort! lock held.'); return }
lock = true
redis.hgetall('zipq')
.then(function(zipq) {
var keys = Object.keys(zipq)
keys.forEach(function(user_id) {
var list = JSON.parse(zipq[user_id])
list.forEach(function(entry) {
if (entry.status == 'waiting') {
entry.status = 'building'
console.log(user_id, entry)
redis.hset('zipq', user_id, JSON.stringify(list))
doZip(user_id, new Date('2008-01-01'), new Date())
.then(function(out) {
entry.status = 'finished'
entry.url = out.url
entry.count = out.count
entry.size = out.size
console.log(entry)
redis.hset('zipq', user_id, JSON.stringify(list))
})
}
})
})
lock = false
})
}
function doZip(user_id, start, stop) {
return r.then(function(conn) {
conn.use('icecondor')
return rethink.table('users').get(user_id).run(conn)
.then(function(user) {
return rethink.table('activities')
.between([user_id, start.toISOString()],
[user_id, stop.toISOString()],
{
index: 'user_id_date',
left_bound: 'open',
right_bound: 'closed'
})
.orderBy({ index: rethink.asc('user_id_date') })
.run(conn)
.then(function(cursor) {
var nonce = newId(36, 5)
var web_dir = 'gpx/' + nonce
var fs_dir = settings.web.root + '/' + web_dir
return mkdirp(fs_dir).then(function() {
var filename = user.username + '-icecondor.gpx'
var fs_path = fs_dir + '/' + filename
var url_path = web_dir + '/' + filename
console.log(fs_path, url_path)
var gpx = fs.createWriteStream(fs_path)
return doWrite(user, gpx, cursor)
.then(function(count) {
var stat = fs.statSync(fs_path)
var mb_size = stat.size / 1024 / 1024
var email = emailer.build_dump_email(user.email, url_path,
count, mb_size)
emailer.send_email(email)
return { url: '/' + url_path, count: count, size: stat.size }
})
})
})
})
})
}
function doWrite(user, gpx, cursor) {
return new Promise(function(resolve, reject) {
gpx.write('<?xml version="1.0" encoding="UTF-8"?>\n')
gpx.write('<gpx version="1.0">\n')
gpx.write(' <name>IceCondor export for ' + user.username + '</name>\n')
gpx.write(' <trk><name>History</name><number>1</number>\n')
gpx.write(' <trkseg>\n')
var count = 0
cursor.each(function(err, act) {
if (act.type === 'location') {
gpx.write(' <trkpt lat="' + act.latitude + '" lon="' + act.longitude + '">' +
'<time>' + act.date + '</time></trkpt>\n')
count = count + 1
}
}, function() {
gpx.write(' </trkseg>\n')
gpx.write(' </trk>\n')
gpx.write('</gpx>\n')
gpx.end()
resolve(count)
})
})
}
function newId(base, length) {
var unit = Math.pow(base, length - 1)
var add = Math.random() * unit * (base - 1)
var idInt = unit + Math.floor(add) - 1
return idInt.toString(base)
}