-
Notifications
You must be signed in to change notification settings - Fork 0
/
deleter.js
177 lines (146 loc) Β· 4.31 KB
/
deleter.js
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
const rimraf = require('rimraf')
const fetch = require('node-fetch')
const fs = require('fs')
const fsp = require('fsp')
const path = require('path')
const moment = require('moment')
const touch = require('touch')
const mkdirp = require('mkdirp')
const config = require('./config.js').config()
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
// temp folder is used to cache site meta between deploys
// example.com/.forge-meta.json
const tmpDir = (process.env.NODE_ENV === 'development' ?
path.resolve(__dirname, './tmp/') :
path.resolve(__dirname, '/tmp/cache/')
)
const forgercDir = (process.env.NODE_ENV === 'development' ?
path.resolve(__dirname, './tmp/forgerc_sites') :
path.resolve(__dirname, '/tmp/forgerc_sites/')
)
const logger = (...args) => {
console.log(`π ${moment().format('MM.DD.YYYY HH:mm:ss')} #`, ...args)
}
/*
* In order to provide downtime support
* we use time of the last sucessfull check
*/
const lastCheckedAtFile = path.join(tmpDir, '.deleter-last-check')
let lastCheckAt = null
try {
lastCheckAt = new Date( fs.readFileSync(lastCheckedAtFile, 'utf-8') )
} catch(err) {
lastCheckAt = moment().toDate()
}
logger(`π Last check was performed ${moment(lastCheckAt).format('MM.DD HH:mm')}`)
const updateLastCheck = () => {
lastCheckAt = new Date
fs.writeFile(lastCheckedAtFile, lastCheckAt.toString(), (err) => {
if(err) return err
})
}
/*
* Utility fs functions (Promise-compliant)
*/
const removeDir = (dir) => {
logger(`βοΈ Removing dir ${dir}`)
return new Promise( (resolve, reject) => {
rimraf(dir, (err) => {
if(err) return reject(err)
resolve()
})
})
}
const touchFile = (fname) => {
logger(`π Touching file ${fname}`)
return new Promise( (resolve, reject) => {
const directory = path.dirname(fname)
logger(`π Creating dir ${directory}`)
mkdirp(directory, (err) => {
if(err) return reject(err)
fsp.writeFile(fname, 'w00t', (err) => {
if(err) return err
})
})
})
}
const cleanSite = (site) => {
logger(`π£ Cleaning site ${site.url}`)
return Promise.all([
removeDir(path.join(tmpDir, site.url)),
removeDir(path.join(tmpDir, `www.${site.url}`)),
removeDir(path.join(forgercDir, site.url)),
removeDir(path.join(forgercDir, `www.${site.url}`))
])
.then( _ => {
if(site.has_config) {
return Promise.all([
touchFile(path.join(forgercDir, site.url, '.forge-config')),
touchFile(path.join(forgercDir, `www.${site.url}`, '.forge-config'))
])
}
})
}
// Strips www. part of an URL
const normalizeUrl = (url) => {
return (url || '').replace(/^www\./, '')
}
const cleanSites = (sites) => {
if(!sites.length) {
// TODO: output this message with some throttle
// e.g. once in X seconds only
// logger('π Nothing to do...')
}
const normalizedUrls = sites.map((site) => {
return Object.assign({}, site, { url: normalizeUrl(site.url) })
})
Promise.all( normalizedUrls.map(cleanSite) )
return updateLastCheck()
}
/*
* Fetches deployed sites data from API
* and cleans the caches
*/
const CHECK_INTERVAL = 5000
const checkDeployed = () => {
let since = moment(lastCheckAt).unix() - 5;
fetch(`${config.forge_api}/deployed_sites.json?deployed_since=${since}`)
.then((response) => {
if(response.status != 200)
throw new Error('API is unavailable!')
return response.json()
})
.then((json) => {
sitesToUpdate = json.sites || []
cleanSites(sitesToUpdate)
})
.catch( err => {
logger('π£ BOOM! Error happened', err)
return null
})
.finally
{
setTimeout(checkDeployed, CHECK_INTERVAL)
}
}
//Clear folder every 5 minutes
const CLEAR_INTERVAL = 5000*60;
const rmDir = function(dirPath, removeSelf) {
if (removeSelf === undefined)
removeSelf = true;
try { var files = fs.readdirSync(dirPath); }
catch(e) { return; }
if (files.length > 0)
for (var i = 0; i < files.length; i++) {
var filePath = dirPath + '/' + files[i];
if (fs.statSync(filePath).isFile())
fs.unlinkSync(filePath);
else
rmDir(filePath);
}
if (dirPath !== tmpDir && removeSelf)
fs.rmdirSync(dirPath);
};
var intervalTimer = null;
checkDeployed();
setInterval(function() {rmDir(tmpDir)}, CLEAR_INTERVAL);