Fix request schedulers stats

This commit is contained in:
Chocobozzz 2017-02-27 21:56:55 +01:00
parent 05a9feaa48
commit 99fdec4648
8 changed files with 148 additions and 62 deletions

View File

@ -1,33 +1,37 @@
<h3>Requests stats</h3> <h3>Requests stats</h3>
<div *ngIf="stats !== null"> <div *ngFor="let requestSchedulerName of statsTitles | keys">
<div class="requests-general"> <div class="block" *ngIf="stats[requestSchedulerName] !== null">
<div> <h4>{{ statsTitles[requestSchedulerName] }}</h4>
<span class="label-description">Remaining requests:</span>
{{ stats.totalRequests }} <div class="requests-general">
<div>
<span class="label-description">Remaining requests:</span>
{{ stats[requestSchedulerName].totalRequests }}
</div>
<div>
<span class="label-description">Interval seconds between requests:</span>
{{ stats[requestSchedulerName].secondsInterval }}
</div>
<div>
<span class="label-description">Remaining time before the scheduled request:</span>
{{ stats[requestSchedulerName].remainingSeconds }}
</div>
</div> </div>
<div> <div class="requests-limit">
<span class="label-description">Interval seconds between requests:</span> <div>
{{ stats.secondsInterval }} <span class="label-description">Maximum number of different pods for a scheduled request:</span>
{{ stats[requestSchedulerName].requestsLimitPods }}
</div>
<div>
<span class="label-description">Maximum number of requests per pod for a scheduled request:</span>
{{ stats[requestSchedulerName].requestsLimitPerPod }}
</div>
</div> </div>
<div>
<span class="label-description">Remaining time before the scheduled request:</span>
{{ stats.remainingSeconds }}
</div>
</div> </div>
<div class="requests-limit">
<div>
<span class="label-description">Maximum number of different pods for a scheduled request:</span>
{{ stats.requestsLimitPods }}
</div>
<div>
<span class="label-description">Maximum number of requests per pod for a scheduled request:</span>
{{ stats.requestsLimitPerPod }}
</div>
</div>
</div> </div>

View File

@ -1,3 +1,7 @@
.block {
margin-bottom: 40px;
}
.label-description { .label-description {
display: inline-block; display: inline-block;
font-weight: bold; font-weight: bold;

View File

@ -10,10 +10,30 @@ import { RequestService, RequestStats } from '../shared';
styleUrls: [ './request-stats.component.scss' ] styleUrls: [ './request-stats.component.scss' ]
}) })
export class RequestStatsComponent implements OnInit, OnDestroy { export class RequestStatsComponent implements OnInit, OnDestroy {
stats: RequestStats = null; statsTitles = {
requestScheduler: 'Basic request scheduler',
requestVideoEventScheduler: 'Video events request scheduler',
requestVideoQaduScheduler: 'Quick and dirty video updates request scheduler'
};
stats: { [ id: string ]: RequestStats } = {
requestScheduler: null,
requestVideoEventScheduler: null,
requestVideoQaduScheduler: null
};
private intervals: { [ id: string ]: number } = {
requestScheduler: null,
requestVideoEventScheduler: null,
requestVideoQaduScheduler: null
};
private timeouts: { [ id: string ]: number } = {
requestScheduler: null,
requestVideoEventScheduler: null,
requestVideoQaduScheduler: null
};
private interval: number = null;
private timeout: number = null;
constructor( constructor(
private notificationsService: NotificationsService, private notificationsService: NotificationsService,
@ -22,17 +42,19 @@ export class RequestStatsComponent implements OnInit, OnDestroy {
ngOnInit() { ngOnInit() {
this.getStats(); this.getStats();
this.runInterval(); this.runIntervals();
} }
ngOnDestroy() { ngOnDestroy() {
if (this.interval !== null) { Object.keys(this.stats).forEach(requestSchedulerName => {
window.clearInterval(this.interval); if (this.intervals[requestSchedulerName] !== null) {
} window.clearInterval(this.intervals[requestSchedulerName]);
}
if (this.timeout !== null) { if (this.timeouts[requestSchedulerName] !== null) {
window.clearTimeout(this.timeout); window.clearTimeout(this.timeouts[requestSchedulerName]);
} }
});
} }
getStats() { getStats() {
@ -43,14 +65,18 @@ export class RequestStatsComponent implements OnInit, OnDestroy {
); );
} }
private runInterval() { private runIntervals() {
this.interval = window.setInterval(() => { Object.keys(this.intervals).forEach(requestSchedulerName => {
this.stats.remainingMilliSeconds -= 1000; this.intervals[requestSchedulerName] = window.setInterval(() => {
const stats = this.stats[requestSchedulerName];
if (this.stats.remainingMilliSeconds <= 0) { stats.remainingMilliSeconds -= 1000;
this.timeout = window.setTimeout(() => this.getStats(), this.stats.remainingMilliSeconds + 100);
} if (stats.remainingMilliSeconds <= 0) {
}, 1000); this.timeouts[requestSchedulerName] = window.setTimeout(() => this.getStats(), stats.remainingMilliSeconds + 100);
}
}, 1000);
});
} }

View File

@ -15,10 +15,20 @@ export class RequestService {
private restExtractor: RestExtractor private restExtractor: RestExtractor
) {} ) {}
getStats(): Observable<RequestStats> { getStats(): Observable<{ [ id: string ]: RequestStats }> {
return this.authHttp.get(RequestService.BASE_REQUEST_URL + 'stats') return this.authHttp.get(RequestService.BASE_REQUEST_URL + 'stats')
.map(this.restExtractor.extractDataGet) .map(this.restExtractor.extractDataGet)
.map((data) => new RequestStats(data)) .map(this.buildRequestObjects)
.catch((res) => this.restExtractor.handleError(res)); .catch((res) => this.restExtractor.handleError(res));
} }
private buildRequestObjects(data: any) {
const requestSchedulers = {};
Object.keys(data).forEach(requestSchedulerName => {
requestSchedulers[requestSchedulerName] = new RequestStats(data[requestSchedulerName]);
});
return requestSchedulers;
}
} }

View File

@ -5,6 +5,7 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router'; import { RouterModule } from '@angular/router';
import { BytesPipe } from 'angular-pipes/src/math/bytes.pipe'; import { BytesPipe } from 'angular-pipes/src/math/bytes.pipe';
import { KeysPipe } from 'angular-pipes/src/object/keys.pipe';
import { DropdownModule } from 'ng2-bootstrap/dropdown'; import { DropdownModule } from 'ng2-bootstrap/dropdown';
import { ProgressbarModule } from 'ng2-bootstrap/progressbar'; import { ProgressbarModule } from 'ng2-bootstrap/progressbar';
import { PaginationModule } from 'ng2-bootstrap/pagination'; import { PaginationModule } from 'ng2-bootstrap/pagination';
@ -36,6 +37,7 @@ import { VideoAbuseService } from './video-abuse';
declarations: [ declarations: [
BytesPipe, BytesPipe,
KeysPipe,
SearchComponent SearchComponent
], ],
@ -53,6 +55,7 @@ import { VideoAbuseService } from './video-abuse';
ProgressbarModule, ProgressbarModule,
Ng2SmartTableModule, Ng2SmartTableModule,
BytesPipe, BytesPipe,
KeysPipe,
SearchComponent SearchComponent
], ],

View File

@ -1,9 +1,10 @@
'use strict' 'use strict'
const express = require('express') const express = require('express')
const parallel = require('async/parallel')
const constants = require('../../initializers/constants') const constants = require('../../initializers/constants')
const db = require('../../initializers/database') const friends = require('../../lib/friends')
const middlewares = require('../../middlewares') const middlewares = require('../../middlewares')
const admin = middlewares.admin const admin = middlewares.admin
const oAuth = middlewares.oauth const oAuth = middlewares.oauth
@ -23,15 +24,33 @@ module.exports = router
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
function getStatsRequests (req, res, next) { function getStatsRequests (req, res, next) {
db.Request.countTotalRequests(function (err, totalRequests) { parallel({
requestScheduler: buildRequestSchedulerFunction(friends.getRequestScheduler()),
requestVideoQaduScheduler: buildRequestSchedulerFunction(friends.getRequestVideoQaduScheduler()),
requestVideoEventScheduler: buildRequestSchedulerFunction(friends.getRequestVideoEventScheduler())
}, function (err, result) {
if (err) return next(err) if (err) return next(err)
return res.json({ return res.json(result)
totalRequests: totalRequests,
requestsLimitPods: constants.REQUESTS_LIMIT_PODS,
requestsLimitPerPod: constants.REQUESTS_LIMIT_PER_POD,
remainingMilliSeconds: db.Request.remainingMilliSeconds(),
milliSecondsInterval: constants.REQUESTS_INTERVAL
})
}) })
} }
// ---------------------------------------------------------------------------
function buildRequestSchedulerFunction (requestScheduler) {
return function (callback) {
requestScheduler.remainingRequestsCount(function (err, count) {
if (err) return callback(err)
const result = {
totalRequests: count,
requestsLimitPods: requestScheduler.limitPods,
requestsLimitPerPod: requestScheduler.limitPerPod,
remainingMilliSeconds: requestScheduler.remainingMilliSeconds(),
milliSecondsInterval: requestScheduler.requestInterval
}
return callback(null, result)
})
}
}

View File

@ -12,6 +12,7 @@ module.exports = class BaseRequestScheduler {
constructor (options) { constructor (options) {
this.lastRequestTimestamp = 0 this.lastRequestTimestamp = 0
this.timer = null this.timer = null
this.requestInterval = constants.REQUESTS_INTERVAL
} }
activate () { activate () {
@ -21,7 +22,7 @@ module.exports = class BaseRequestScheduler {
this.timer = setInterval(() => { this.timer = setInterval(() => {
this.lastRequestTimestamp = Date.now() this.lastRequestTimestamp = Date.now()
this.makeRequests() this.makeRequests()
}, constants.REQUESTS_INTERVAL) }, this.requestInterval)
} }
deactivate () { deactivate () {
@ -41,6 +42,10 @@ module.exports = class BaseRequestScheduler {
return constants.REQUESTS_INTERVAL - (Date.now() - this.lastRequestTimestamp) return constants.REQUESTS_INTERVAL - (Date.now() - this.lastRequestTimestamp)
} }
remainingRequestsCount (callback) {
return this.getRequestModel().countTotalRequests(callback)
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Make a requests to friends of a certain type // Make a requests to friends of a certain type

View File

@ -19,8 +19,8 @@ const RequestVideoEventScheduler = require('./request-video-event-scheduler')
const ENDPOINT_ACTIONS = constants.REQUEST_ENDPOINT_ACTIONS[constants.REQUEST_ENDPOINTS.VIDEOS] const ENDPOINT_ACTIONS = constants.REQUEST_ENDPOINT_ACTIONS[constants.REQUEST_ENDPOINTS.VIDEOS]
const requestScheduler = new RequestScheduler() const requestScheduler = new RequestScheduler()
const requestSchedulerVideoQadu = new RequestVideoQaduScheduler() const requestVideoQaduScheduler = new RequestVideoQaduScheduler()
const requestSchedulerVideoEvent = new RequestVideoEventScheduler() const requestVideoEventScheduler = new RequestVideoEventScheduler()
const friends = { const friends = {
activate, activate,
@ -33,13 +33,16 @@ const friends = {
makeFriends, makeFriends,
quitFriends, quitFriends,
removeVideoToFriends, removeVideoToFriends,
sendOwnedVideosToPod sendOwnedVideosToPod,
getRequestScheduler,
getRequestVideoQaduScheduler,
getRequestVideoEventScheduler
} }
function activate () { function activate () {
requestScheduler.activate() requestScheduler.activate()
requestSchedulerVideoQadu.activate() requestVideoQaduScheduler.activate()
requestSchedulerVideoEvent.activate() requestVideoEventScheduler.activate()
} }
function addVideoToFriends (videoData, transaction, callback) { function addVideoToFriends (videoData, transaction, callback) {
@ -142,7 +145,7 @@ function quitFriends (callback) {
}, },
function flushVideoQaduRequests (callbackAsync) { function flushVideoQaduRequests (callbackAsync) {
requestSchedulerVideoQadu.flush(err => callbackAsync(err)) requestVideoQaduScheduler.flush(err => callbackAsync(err))
}, },
function getPodsList (callbackAsync) { function getPodsList (callbackAsync) {
@ -215,6 +218,18 @@ function sendOwnedVideosToPod (podId) {
}) })
} }
function getRequestScheduler () {
return requestScheduler
}
function getRequestVideoQaduScheduler () {
return requestVideoQaduScheduler
}
function getRequestVideoEventScheduler () {
return requestVideoEventScheduler
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
module.exports = friends module.exports = friends
@ -345,13 +360,13 @@ function createRequest (options, callback) {
function createVideoQaduRequest (options, callback) { function createVideoQaduRequest (options, callback) {
if (!callback) callback = utils.createEmptyCallback() if (!callback) callback = utils.createEmptyCallback()
requestSchedulerVideoQadu.createRequest(options, callback) requestVideoQaduScheduler.createRequest(options, callback)
} }
function createVideoEventRequest (options, callback) { function createVideoEventRequest (options, callback) {
if (!callback) callback = utils.createEmptyCallback() if (!callback) callback = utils.createEmptyCallback()
requestSchedulerVideoEvent.createRequest(options, callback) requestVideoEventScheduler.createRequest(options, callback)
} }
function isMe (host) { function isMe (host) {