Skip to content

Commit e02e511

Browse files
committed
add: view duration releated constants
1 parent 5f6186c commit e02e511

33 files changed

Lines changed: 1328 additions & 116 deletions

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
66

77
## [Unreleased]
88

9+
### Added
10+
11+
- Page view duration limit and interval is configurable now at system level, could be changed via API and Settings panel
12+
913
### Changed
1014

1115
- The official Docker image is now based on Node.js 22 (#343)

dist/index.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/index.js

Lines changed: 124 additions & 94 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
"devDependencies": {
6262
"@apollo/client": "^3.7.2",
6363
"@electerious/eslint-config": "^3.5.0",
64+
"@types/sinon": "^17.0.3",
6465
"ava": "5.1.0",
6566
"classnames": "^2.3.1",
6667
"coveralls": "^3.1.1",
@@ -73,6 +74,7 @@
7374
"normalize.css": "^8.0.1",
7475
"nyc": "^15.1.0",
7576
"prop-types": "^15.8.1",
77+
"ramda": "^0.30.1",
7678
"react": "^18.1.0",
7779
"react-apollo-network-status": "^5.0.1",
7880
"react-dom": "^18.1.0",
@@ -83,6 +85,7 @@
8385
"rosid-handler-sass": "^8.0.0",
8486
"s-ago": "^2.2.0",
8587
"shortid": "^2.2.16",
88+
"sinon": "^19.0.2",
8689
"test-listen": "^1.1.0",
8790
"url-pattern": "^1.0.3"
8891
},

src/aggregations/aggregateActiveVisitors.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use strict'
22

3-
const { DURATIONS_LIMIT, DURATIONS_INTERVAL } = require('../constants/durations')
3+
const constants = require('../constants/durations')
44
const matchDomains = require('../stages/matchDomains')
55

66
module.exports = (ids, dateDetails) => {
@@ -19,10 +19,10 @@ module.exports = (ids, dateDetails) => {
1919
}
2020

2121
// Ignore users that are on the page for too long
22-
aggregation[0].$match.created = { $gte: dateDetails.lastMilliseconds(DURATIONS_LIMIT) }
22+
aggregation[0].$match.created = { $gte: dateDetails.lastMilliseconds(constants.DURATIONS_LIMIT) }
2323

2424
// Ignore users that aren't active anymore
25-
aggregation[0].$match.updated = { $gte: dateDetails.lastMilliseconds(DURATIONS_INTERVAL * 2) }
25+
aggregation[0].$match.updated = { $gte: dateDetails.lastMilliseconds(constants.DURATIONS_INTERVAL * 2) }
2626

2727
return aggregation
2828
}

src/constants/durations.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
'use strict'
22

3-
const { hour } = require('../utils/times')
3+
const { customise } = require('../utils/constants')
4+
const { hour, second } = require('../utils/times')
45

5-
const DURATIONS_INTERVAL = 15000
6+
const DURATIONS_INTERVAL = 15 * second
67
const DURATIONS_LIMIT = hour / 2
78

8-
module.exports = {
9+
module.exports = customise({
910
DURATIONS_INTERVAL,
1011
DURATIONS_LIMIT,
11-
}
12+
}, [
13+
'DURATIONS_INTERVAL',
14+
'DURATIONS_LIMIT',
15+
])

src/database/constants.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
'use strict'
2+
3+
const Constant = require('../models/Constant')
4+
5+
const response = (entry) => ({
6+
id: entry.id,
7+
name: entry.name,
8+
value: entry.value,
9+
unit: entry.unit,
10+
created: entry.created,
11+
updated: entry.updated,
12+
})
13+
14+
const enhance = (entry) => {
15+
return entry == null ? entry : response(entry)
16+
}
17+
18+
const get = async (name) => enhance(
19+
await Constant.findOne({ name }),
20+
)
21+
22+
const update = async (name, value, unit) => enhance(
23+
await Constant.findOneAndUpdate({
24+
name,
25+
}, {
26+
$set: {
27+
updated: Date.now(),
28+
value,
29+
unit,
30+
},
31+
}, {
32+
new: true,
33+
upsert: true,
34+
}),
35+
)
36+
37+
module.exports = {
38+
get,
39+
update,
40+
}

src/models/Constant.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
'use strict'
2+
3+
const mongoose = require('mongoose')
4+
const uuid = require('crypto').randomUUID
5+
6+
const schema = new mongoose.Schema({
7+
id: {
8+
type: String,
9+
required: true,
10+
unique: true,
11+
default: () => uuid(),
12+
},
13+
created: {
14+
type: Date,
15+
required: true,
16+
default: Date.now,
17+
},
18+
updated: {
19+
type: Date,
20+
required: true,
21+
default: Date.now,
22+
},
23+
name: {
24+
type: String,
25+
required: true,
26+
unique: true,
27+
},
28+
value: {
29+
type: Number,
30+
required: true,
31+
},
32+
unit: {
33+
type: String,
34+
required: true,
35+
},
36+
})
37+
38+
module.exports = mongoose.model('Constant', schema)

src/resolvers/contants.js

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
const { DURATIONS_INTERVAL, DURATIONS_LIMIT } = require('../constants/durations')
2+
const constants = require('../database/constants')
3+
const requireAuth = require('../middlewares/requireAuth')
4+
const pipe = require('../utils/pipe')
5+
6+
const response = (entry) => ({
7+
created: entry.created,
8+
updated: entry.updated,
9+
id: entry.name,
10+
value: entry.value,
11+
unit: entry.unit,
12+
})
13+
14+
const toApi = ({ name, ...data }) => ({
15+
...data,
16+
id: name,
17+
})
18+
const interval = async () => {
19+
const name = 'DURATIONS_INTERVAL'
20+
return toApi(await constants.get(name) || {
21+
name,
22+
value: DURATIONS_INTERVAL,
23+
unit: 'seconds',
24+
})
25+
}
26+
const limit = async () => {
27+
const name = 'DURATIONS_LIMIT'
28+
return toApi(await constants.get(name) || {
29+
name,
30+
value: DURATIONS_LIMIT,
31+
unit: 'minutes',
32+
})
33+
}
34+
35+
module.exports = {
36+
Query: {
37+
constants: pipe(requireAuth, async () => ({
38+
durationsInterval: await interval(),
39+
durationsLimit: await limit(),
40+
})),
41+
},
42+
Mutation: {
43+
setConstant: pipe(requireAuth, async (parent, { input }) => {
44+
const { id, value, unit } = input
45+
46+
const entry = await constants.update(id, value, unit)
47+
return {
48+
success: true,
49+
payload: response(entry),
50+
}
51+
}),
52+
},
53+
}

src/resolvers/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ const { mergeResolvers } = require('@graphql-tools/merge')
55
module.exports = mergeResolvers([
66
require('./tokens'),
77
require('./permanentTokens'),
8+
require('./contants'),
89
require('./records'),
910
require('./domains'),
1011
require('./events'),

0 commit comments

Comments
 (0)