Contact
CoCalc Logo Icon
StoreFeaturesDocsShareSupport News AboutSign UpSign In
| Download
Views: 39539
1
##############################################################################
2
#
3
# CoCalc: Collaborative Calculation in the Cloud
4
#
5
# Copyright (C) 2016, Sagemath Inc.
6
#
7
# This program is free software: you can redistribute it and/or modify
8
# it under the terms of the GNU General Public License as published by
9
# the Free Software Foundation, either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# This program is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with this program. If not, see <http://www.gnu.org/licenses/>.
19
#
20
###############################################################################
21
22
###
23
Periodically check the current version of the SMC code. When it changes fire a change event.
24
25
To use, do
26
27
smc_version = require('hub-version')
28
smc_version.on('change', console.log) # emited when version changes (waits CHECK_AGE_M after version time)
29
smc_version.version # current version
30
###
31
32
CHECK_INTERVAL_S = 10
33
34
# Do not fire change event utnil this many minutes after version updated.
35
# We wait to give webpack (etc.) a chance to get updated.
36
CHECK_AGE_M = 6
37
#CHECK_AGE_M = 0
38
39
{EventEmitter} = require('events')
40
path = require('path')
41
fs = require('fs')
42
winston = require('winston')
43
require_reload = require('require-reload')(require) # used to reload the smc-version file properly
44
underscore = require('underscore')
45
misc = require('smc-util/misc')
46
misc_node = require('smc-util-node/misc_node')
47
48
# smc webapp version: when compiling with webpack, the smc-version file is read by webpack.config
49
# and its `version` compiled into the resulting javascript and also stored in the assets.js file.
50
# In the `metadata` entry, it does contain the version, build date, build timestamp, and git revision.
51
# Here, we are only interested in the `version`, to compare it with the version of smc-version.
52
53
get_smc_webapp_version = (cb) ->
54
# with the new containerized setup, the compiled smc webapp is separated from the hub
55
# therefore, there is no direct file-based information about the webapp available
56
# TODO replace this useless callback with a http call, to retrieve the assets.json file
57
# History: revision 6d7dc3067c82830 shows how this has been done before that!
58
59
# temporarily disabled
60
cb(null, 0); return
61
# TODO assets_json = retrieve base_url/assets.json
62
try
63
data = JSON.parse(assets_json)
64
webapp_ver = data.metadata?.version ? 0
65
# winston.debug("get_smc_webapp_version: #{webapp_ver}")
66
cb(null, webapp_ver)
67
catch err
68
winston.warn("get_smc_webapp_version: error reading webapp's assets.json -- #{err}")
69
cb(err, 0)
70
71
72
# Do a sanity check on the ver object to make sure it doesn't make it impossible
73
# for clients to update. (I'm just imaging future me doing some stupid editing of
74
# the version field by hand.)
75
sanity_check = (ver) ->
76
# ver should have fields version, min_browser_version, and min_project_version.
77
ver.version ?= 0
78
ver.min_browser_version ?= 0
79
ver.min_project_version ?= 0
80
ver.webapp_version ?= 0
81
# the browser can only update to the latest available code
82
if ver.webapp_version > 0 and ver.webapp_version < ver.min_browser_version
83
ver.min_browser_version = ver.webapp_version
84
# The min version shouldn't be bigger than the actual version
85
# (which is the newest the client can update to).
86
if ver.version < ver.min_browser_version
87
ver.min_browser_version = ver.version
88
if ver.version < ver.min_project_version
89
ver.min_project_version = ver.version
90
return ver
91
92
class Version extends EventEmitter
93
constructor: (@check_interval_s=CHECK_INTERVAL_S, @check_age_m=CHECK_AGE_M) ->
94
# check_interval_s -- How frequently to check if the smc-util/smc-version
95
# module has changed.
96
# check_age_m -- Don't tell browser clients to upgrade until this
97
# many minutes after version file updated.
98
# initialization: short-circuit the @update check
99
@load_smc_version (err, smc_version) =>
100
if err?
101
winston.debug("Version.constructor err=#{err}")
102
@set_smc_version(smc_version)
103
@_check = setInterval(@update, @check_interval_s*1000)
104
105
load_smc_version: (cb) ->
106
ver = require_reload('smc-util/smc-version')
107
get_smc_webapp_version (err, webapp_version) ->
108
ver.webapp_version = webapp_version
109
cb(err, sanity_check(ver))
110
111
set_smc_version: (smc_version) =>
112
for k, v of smc_version
113
@[k] = v
114
115
close: =>
116
if @_check?
117
clearInterval(@_check)
118
delete @_check
119
120
update: =>
121
@load_smc_version (err, smc_version) =>
122
# winston.debug("Version.update: smc_version = #{misc.to_json(smc_version)}")
123
if err?
124
winston.debug("Version.update err=#{err}")
125
if not smc_version.version
126
# not using versions
127
return
128
ver_age_s = (new Date() - smc_version.version * 1000)/1000
129
# winston.debug("Version.update: ver_age_s=#{ver_age_s}, CHECK_AGE_M*60=#{CHECK_AGE_M*60}")
130
if ver_age_s <= @check_age_m * 60
131
# do nothing - we wait until the version in the file is at least SMC_VERSION_CHECK_AGE_M old
132
return
133
if not underscore.isEqual(@version, smc_version.version)
134
# we have a new version: updating the instance fields and emitting it to listeners
135
@set_smc_version(smc_version)
136
winston.debug("update_smc_version: update -- #{misc.to_json(smc_version)}")
137
@emit('change', smc_version)
138
139
# export a single version object
140
module.exports = new Version()
141
142