mirror of
https://github.com/status-im/codimd.git
synced 2025-02-23 18:48:06 +00:00
refactor(realtime): add test case for clean dangling user
Signed-off-by: BoHong Li <a60814billy@gmail.com>
This commit is contained in:
parent
d8b18ee241
commit
ab37a33e0b
@ -24,6 +24,7 @@ const ot = require('./ot')
|
|||||||
const { ProcessQueue } = require('./processQueue')
|
const { ProcessQueue } = require('./processQueue')
|
||||||
const { RealtimeClientConnection } = require('./realtimeClientConnection')
|
const { RealtimeClientConnection } = require('./realtimeClientConnection')
|
||||||
const { UpdateDirtyNoteJob } = require('./realtimeUpdateDirtyNoteJob')
|
const { UpdateDirtyNoteJob } = require('./realtimeUpdateDirtyNoteJob')
|
||||||
|
const { CleanDanglingUserJob } = require('./realtimeCleanDanglingUserJob')
|
||||||
|
|
||||||
// public
|
// public
|
||||||
const realtime = {
|
const realtime = {
|
||||||
@ -164,29 +165,8 @@ function finishUpdateNote (note, _note, callback) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// clean when user not in any rooms or user not in connected list
|
const cleanDanglingUserJob = new CleanDanglingUserJob(realtime)
|
||||||
setInterval(function () {
|
cleanDanglingUserJob.start()
|
||||||
async.each(Object.keys(users), function (key, callback) {
|
|
||||||
var socket = realtime.io.sockets.connected[key]
|
|
||||||
if ((!socket && users[key]) ||
|
|
||||||
(socket && (!socket.rooms || socket.rooms.length <= 0))) {
|
|
||||||
if (config.debug) {
|
|
||||||
logger.info('cleaner found redundant user: ' + key)
|
|
||||||
}
|
|
||||||
if (!socket) {
|
|
||||||
socket = {
|
|
||||||
id: key
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!disconnectProcessQueue.checkTaskIsInQueue(socket.id)) {
|
|
||||||
exports.queueForDisconnect(socket)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return callback(null, null)
|
|
||||||
}, function (err) {
|
|
||||||
if (err) return logger.error('cleaner error', err)
|
|
||||||
})
|
|
||||||
}, 60000)
|
|
||||||
|
|
||||||
var saverSleep = false
|
var saverSleep = false
|
||||||
// save note revision in interval
|
// save note revision in interval
|
||||||
|
49
lib/realtimeCleanDanglingUserJob.js
Normal file
49
lib/realtimeCleanDanglingUserJob.js
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const async = require('async')
|
||||||
|
const config = require('./config')
|
||||||
|
const logger = require('./logger')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clean when user not in any rooms or user not in connected list
|
||||||
|
*/
|
||||||
|
class CleanDanglingUserJob {
|
||||||
|
constructor (realtime) {
|
||||||
|
this.realtime = realtime
|
||||||
|
}
|
||||||
|
|
||||||
|
start () {
|
||||||
|
if (this.timer) return
|
||||||
|
this.timer = setInterval(this.cleanDanglingUser.bind(this), 60000)
|
||||||
|
}
|
||||||
|
|
||||||
|
stop () {
|
||||||
|
if (!this.timer) return
|
||||||
|
clearInterval(this.timer)
|
||||||
|
this.timer = undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanDanglingUser () {
|
||||||
|
const users = this.realtime.getUserPool()
|
||||||
|
async.each(Object.keys(users), (key, callback) => {
|
||||||
|
const socket = this.realtime.io.sockets.connected[key]
|
||||||
|
if ((!socket && users[key]) ||
|
||||||
|
(socket && (!socket.rooms || socket.rooms.length <= 0))) {
|
||||||
|
if (config.debug) {
|
||||||
|
logger.info('cleaner found redundant user: ' + key)
|
||||||
|
}
|
||||||
|
if (!socket) {
|
||||||
|
return callback(null, null)
|
||||||
|
}
|
||||||
|
if (!this.realtime.disconnectProcessQueue.checkTaskIsInQueue(socket.id)) {
|
||||||
|
this.realtime.queueForDisconnect(socket)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return callback(null, null)
|
||||||
|
}, function (err) {
|
||||||
|
if (err) return logger.error('cleaner error', err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.CleanDanglingUserJob = CleanDanglingUserJob
|
68
test/realtime/cleanDanglingUser.test.js
Normal file
68
test/realtime/cleanDanglingUser.test.js
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/* eslint-env node, mocha */
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const assert = require('assert')
|
||||||
|
const mock = require('mock-require')
|
||||||
|
const sinon = require('sinon')
|
||||||
|
const {removeModuleFromRequireCache, makeMockSocket} = require('./utils')
|
||||||
|
|
||||||
|
describe('cleanDanglingUser', function () {
|
||||||
|
let clock
|
||||||
|
beforeEach(() => {
|
||||||
|
clock = sinon.useFakeTimers()
|
||||||
|
mock('../../lib/processQueue', require('../testDoubles/ProcessQueueFake'))
|
||||||
|
mock('../../lib/logger', {
|
||||||
|
error: () => {},
|
||||||
|
info: () => {}
|
||||||
|
})
|
||||||
|
mock('../../lib/history', {})
|
||||||
|
mock('../../lib/models', {
|
||||||
|
Revision: {
|
||||||
|
saveAllNotesRevision: () => {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
mock('../../lib/config', {
|
||||||
|
debug: true
|
||||||
|
})
|
||||||
|
mock('../../lib/realtimeUpdateDirtyNoteJob', require('../testDoubles/realtimeUpdateDirtyNoteJobStub'))
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
clock.restore()
|
||||||
|
removeModuleFromRequireCache('../../lib/realtime')
|
||||||
|
mock.stopAll()
|
||||||
|
sinon.restore()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should ', (done) => {
|
||||||
|
const realtime = require('../../lib/realtime')
|
||||||
|
const queueForDisconnectSpy = sinon.spy(realtime, 'queueForDisconnect')
|
||||||
|
realtime.io = {
|
||||||
|
to: sinon.stub().callsFake(function () {
|
||||||
|
return {
|
||||||
|
emit: sinon.fake()
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
sockets: {
|
||||||
|
connected: {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let user1Socket = makeMockSocket()
|
||||||
|
let user2Socket = makeMockSocket()
|
||||||
|
|
||||||
|
user1Socket.rooms.push('room1')
|
||||||
|
|
||||||
|
realtime.io.sockets.connected[user1Socket.id] = user1Socket
|
||||||
|
realtime.io.sockets.connected[user2Socket.id] = user2Socket
|
||||||
|
|
||||||
|
realtime.users[user1Socket.id] = user1Socket
|
||||||
|
realtime.users[user2Socket.id] = user2Socket
|
||||||
|
clock.tick(60000)
|
||||||
|
clock.restore()
|
||||||
|
setTimeout(() => {
|
||||||
|
assert(queueForDisconnectSpy.called)
|
||||||
|
done()
|
||||||
|
}, 50)
|
||||||
|
})
|
||||||
|
})
|
@ -66,7 +66,6 @@ describe('realtime#update note is dirty timer', function () {
|
|||||||
realtime.notes['note2'] = note2
|
realtime.notes['note2'] = note2
|
||||||
|
|
||||||
clock.tick(1000)
|
clock.tick(1000)
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
assert(note2.server.isDirty === false)
|
assert(note2.server.isDirty === false)
|
||||||
done()
|
done()
|
||||||
@ -126,5 +125,4 @@ describe('realtime#update note is dirty timer', function () {
|
|||||||
done()
|
done()
|
||||||
}, 50)
|
}, 50)
|
||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
@ -24,7 +24,8 @@ function makeMockSocket (headers, query) {
|
|||||||
return broadCastChannelCache[channel]
|
return broadCastChannelCache[channel]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
disconnect: sinon.fake()
|
disconnect: sinon.fake(),
|
||||||
|
rooms: []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
35
test/testDoubles/ProcessQueueFake.js
Normal file
35
test/testDoubles/ProcessQueueFake.js
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
class ProcessQueueFake {
|
||||||
|
constructor () {
|
||||||
|
this.taskMap = new Map()
|
||||||
|
this.queue = []
|
||||||
|
}
|
||||||
|
|
||||||
|
start () {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
stop () {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
checkTaskIsInQueue (id) {
|
||||||
|
return this.taskMap.has(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
push (id, processFunc) {
|
||||||
|
this.queue.push({
|
||||||
|
id: id,
|
||||||
|
processFunc: processFunc
|
||||||
|
})
|
||||||
|
this.taskMap.set(id, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
process () {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.ProcessQueueFake = ProcessQueueFake
|
||||||
|
exports.ProcessQueue = ProcessQueueFake
|
12
test/testDoubles/realtimeUpdateDirtyNoteJobStub.js
Normal file
12
test/testDoubles/realtimeUpdateDirtyNoteJobStub.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
class UpdateDirtyNoteJobStub {
|
||||||
|
start() {
|
||||||
|
}
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.UpdateDirtyNoteJobStub = UpdateDirtyNoteJobStub
|
||||||
|
exports.UpdateDirtyNoteJob = UpdateDirtyNoteJobStub
|
Loading…
x
Reference in New Issue
Block a user