diff options
Diffstat (limited to 'server/lib/request')
-rw-r--r-- | server/lib/request/abstract-request-scheduler.ts | 168 | ||||
-rw-r--r-- | server/lib/request/index.ts | 4 | ||||
-rw-r--r-- | server/lib/request/request-scheduler.ts | 96 | ||||
-rw-r--r-- | server/lib/request/request-video-event-scheduler.ts | 129 | ||||
-rw-r--r-- | server/lib/request/request-video-qadu-scheduler.ts | 148 |
5 files changed, 0 insertions, 545 deletions
diff --git a/server/lib/request/abstract-request-scheduler.ts b/server/lib/request/abstract-request-scheduler.ts deleted file mode 100644 index f838c47f2..000000000 --- a/server/lib/request/abstract-request-scheduler.ts +++ /dev/null | |||
@@ -1,168 +0,0 @@ | |||
1 | import { isEmpty } from 'lodash' | ||
2 | import * as Bluebird from 'bluebird' | ||
3 | |||
4 | import { database as db } from '../../initializers/database' | ||
5 | import { logger, makeSecureRequest } from '../../helpers' | ||
6 | import { AbstractRequestClass, AbstractRequestToPodClass, PodInstance } from '../../models' | ||
7 | import { | ||
8 | API_VERSION, | ||
9 | REQUESTS_IN_PARALLEL, | ||
10 | REQUESTS_INTERVAL | ||
11 | } from '../../initializers' | ||
12 | |||
13 | interface RequestsObjects<U> { | ||
14 | [ id: string ]: { | ||
15 | toPod: PodInstance | ||
16 | endpoint: string | ||
17 | ids: number[] // ids | ||
18 | datas: U[] | ||
19 | } | ||
20 | } | ||
21 | |||
22 | abstract class AbstractRequestScheduler <T> { | ||
23 | requestInterval: number | ||
24 | limitPods: number | ||
25 | limitPerPod: number | ||
26 | |||
27 | protected lastRequestTimestamp: number | ||
28 | protected timer: NodeJS.Timer | ||
29 | protected description: string | ||
30 | |||
31 | constructor () { | ||
32 | this.lastRequestTimestamp = 0 | ||
33 | this.timer = null | ||
34 | this.requestInterval = REQUESTS_INTERVAL | ||
35 | } | ||
36 | |||
37 | abstract getRequestModel (): AbstractRequestClass<T> | ||
38 | abstract getRequestToPodModel (): AbstractRequestToPodClass | ||
39 | abstract buildRequestsObjects (requestsGrouped: T): RequestsObjects<any> | ||
40 | |||
41 | activate () { | ||
42 | logger.info('Requests scheduler activated.') | ||
43 | this.lastRequestTimestamp = Date.now() | ||
44 | |||
45 | this.timer = setInterval(() => { | ||
46 | this.lastRequestTimestamp = Date.now() | ||
47 | this.makeRequests() | ||
48 | }, this.requestInterval) | ||
49 | } | ||
50 | |||
51 | deactivate () { | ||
52 | logger.info('Requests scheduler deactivated.') | ||
53 | clearInterval(this.timer) | ||
54 | this.timer = null | ||
55 | } | ||
56 | |||
57 | forceSend () { | ||
58 | logger.info('Force requests scheduler sending.') | ||
59 | this.makeRequests() | ||
60 | } | ||
61 | |||
62 | remainingMilliSeconds () { | ||
63 | if (this.timer === null) return -1 | ||
64 | |||
65 | return REQUESTS_INTERVAL - (Date.now() - this.lastRequestTimestamp) | ||
66 | } | ||
67 | |||
68 | remainingRequestsCount () { | ||
69 | return this.getRequestModel().countTotalRequests() | ||
70 | } | ||
71 | |||
72 | flush () { | ||
73 | return this.getRequestModel().removeAll() | ||
74 | } | ||
75 | |||
76 | // --------------------------------------------------------------------------- | ||
77 | |||
78 | // Make a requests to friends of a certain type | ||
79 | protected async makeRequest (toPod: PodInstance, requestEndpoint: string, requestsToMake: any) { | ||
80 | const params = { | ||
81 | toPod: toPod, | ||
82 | method: 'POST' as 'POST', | ||
83 | path: '/api/' + API_VERSION + '/remote/' + requestEndpoint, | ||
84 | data: requestsToMake // Requests we need to make | ||
85 | } | ||
86 | |||
87 | // Make multiple retry requests to all of pods | ||
88 | // The function fire some useful callbacks | ||
89 | try { | ||
90 | const { response } = await makeSecureRequest(params) | ||
91 | |||
92 | // 400 because if the other pod is not up to date, it may not understand our request | ||
93 | if ([ 200, 201, 204, 400 ].indexOf(response.statusCode) === -1) { | ||
94 | throw new Error('Status code not 20x or 400 : ' + response.statusCode) | ||
95 | } | ||
96 | } catch (err) { | ||
97 | logger.error('Error sending secure request to %s pod.', toPod.host, err) | ||
98 | |||
99 | throw err | ||
100 | } | ||
101 | } | ||
102 | |||
103 | // Make all the requests of the scheduler | ||
104 | protected async makeRequests () { | ||
105 | let requestsGrouped: T | ||
106 | |||
107 | try { | ||
108 | requestsGrouped = await this.getRequestModel().listWithLimitAndRandom(this.limitPods, this.limitPerPod) | ||
109 | } catch (err) { | ||
110 | logger.error('Cannot get the list of "%s".', this.description, { error: err.stack }) | ||
111 | throw err | ||
112 | } | ||
113 | |||
114 | // We want to group requests by destinations pod and endpoint | ||
115 | const requestsToMake = this.buildRequestsObjects(requestsGrouped) | ||
116 | |||
117 | // If there are no requests, abort | ||
118 | if (isEmpty(requestsToMake) === true) { | ||
119 | logger.info('No "%s" to make.', this.description) | ||
120 | return { goodPods: [], badPods: [] } | ||
121 | } | ||
122 | |||
123 | logger.info('Making "%s" to friends.', this.description) | ||
124 | |||
125 | const goodPods: number[] = [] | ||
126 | const badPods: number[] = [] | ||
127 | |||
128 | await Bluebird.map(Object.keys(requestsToMake), async hashKey => { | ||
129 | const requestToMake = requestsToMake[hashKey] | ||
130 | const toPod: PodInstance = requestToMake.toPod | ||
131 | |||
132 | try { | ||
133 | await this.makeRequest(toPod, requestToMake.endpoint, requestToMake.datas) | ||
134 | logger.debug('Removing requests for pod %s.', requestToMake.toPod.id, { requestsIds: requestToMake.ids }) | ||
135 | goodPods.push(requestToMake.toPod.id) | ||
136 | |||
137 | this.afterRequestHook() | ||
138 | |||
139 | // Remove the pod id of these request ids | ||
140 | await this.getRequestToPodModel() | ||
141 | .removeByRequestIdsAndPod(requestToMake.ids, requestToMake.toPod.id) | ||
142 | } catch (err) { | ||
143 | badPods.push(requestToMake.toPod.id) | ||
144 | logger.info('Cannot make request to %s.', toPod.host, err) | ||
145 | } | ||
146 | }, { concurrency: REQUESTS_IN_PARALLEL }) | ||
147 | |||
148 | this.afterRequestsHook() | ||
149 | |||
150 | // All the requests were made, we update the pods score | ||
151 | db.Pod.updatePodsScore(goodPods, badPods) | ||
152 | } | ||
153 | |||
154 | protected afterRequestHook () { | ||
155 | // Nothing to do, let children re-implement it | ||
156 | } | ||
157 | |||
158 | protected afterRequestsHook () { | ||
159 | // Nothing to do, let children re-implement it | ||
160 | } | ||
161 | } | ||
162 | |||
163 | // --------------------------------------------------------------------------- | ||
164 | |||
165 | export { | ||
166 | AbstractRequestScheduler, | ||
167 | RequestsObjects | ||
168 | } | ||
diff --git a/server/lib/request/index.ts b/server/lib/request/index.ts deleted file mode 100644 index 47d60e5b4..000000000 --- a/server/lib/request/index.ts +++ /dev/null | |||
@@ -1,4 +0,0 @@ | |||
1 | export * from './abstract-request-scheduler' | ||
2 | export * from './request-scheduler' | ||
3 | export * from './request-video-event-scheduler' | ||
4 | export * from './request-video-qadu-scheduler' | ||
diff --git a/server/lib/request/request-scheduler.ts b/server/lib/request/request-scheduler.ts deleted file mode 100644 index c3f7f6429..000000000 --- a/server/lib/request/request-scheduler.ts +++ /dev/null | |||
@@ -1,96 +0,0 @@ | |||
1 | import * as Sequelize from 'sequelize' | ||
2 | |||
3 | import { database as db } from '../../initializers/database' | ||
4 | import { AbstractRequestScheduler, RequestsObjects } from './abstract-request-scheduler' | ||
5 | import { logger } from '../../helpers' | ||
6 | import { REQUESTS_LIMIT_PODS, REQUESTS_LIMIT_PER_POD } from '../../initializers' | ||
7 | import { RequestsGrouped } from '../../models' | ||
8 | import { RequestEndpoint, RemoteVideoRequest } from '../../../shared' | ||
9 | |||
10 | export type RequestSchedulerOptions = { | ||
11 | type: string | ||
12 | endpoint: RequestEndpoint | ||
13 | data: Object | ||
14 | toIds: number[] | ||
15 | transaction: Sequelize.Transaction | ||
16 | } | ||
17 | |||
18 | class RequestScheduler extends AbstractRequestScheduler<RequestsGrouped> { | ||
19 | constructor () { | ||
20 | super() | ||
21 | |||
22 | // We limit the size of the requests | ||
23 | this.limitPods = REQUESTS_LIMIT_PODS | ||
24 | this.limitPerPod = REQUESTS_LIMIT_PER_POD | ||
25 | |||
26 | this.description = 'requests' | ||
27 | } | ||
28 | |||
29 | getRequestModel () { | ||
30 | return db.Request | ||
31 | } | ||
32 | |||
33 | getRequestToPodModel () { | ||
34 | return db.RequestToPod | ||
35 | } | ||
36 | |||
37 | buildRequestsObjects (requestsGrouped: RequestsGrouped) { | ||
38 | const requestsToMakeGrouped: RequestsObjects<RemoteVideoRequest> = {} | ||
39 | |||
40 | for (const toPodId of Object.keys(requestsGrouped)) { | ||
41 | for (const data of requestsGrouped[toPodId]) { | ||
42 | const request = data.request | ||
43 | const pod = data.pod | ||
44 | const hashKey = toPodId + request.endpoint | ||
45 | |||
46 | if (!requestsToMakeGrouped[hashKey]) { | ||
47 | requestsToMakeGrouped[hashKey] = { | ||
48 | toPod: pod, | ||
49 | endpoint: request.endpoint, | ||
50 | ids: [], // request ids, to delete them from the DB in the future | ||
51 | datas: [] // requests data, | ||
52 | } | ||
53 | } | ||
54 | |||
55 | requestsToMakeGrouped[hashKey].ids.push(request.id) | ||
56 | requestsToMakeGrouped[hashKey].datas.push(request.request) | ||
57 | } | ||
58 | } | ||
59 | |||
60 | return requestsToMakeGrouped | ||
61 | } | ||
62 | |||
63 | async createRequest ({ type, endpoint, data, toIds, transaction }: RequestSchedulerOptions) { | ||
64 | // If there are no destination pods abort | ||
65 | if (toIds.length === 0) return undefined | ||
66 | |||
67 | const createQuery = { | ||
68 | endpoint, | ||
69 | request: { | ||
70 | type: type, | ||
71 | data: data | ||
72 | } | ||
73 | } | ||
74 | |||
75 | const dbRequestOptions: Sequelize.CreateOptions = { | ||
76 | transaction | ||
77 | } | ||
78 | |||
79 | const request = await db.Request.create(createQuery, dbRequestOptions) | ||
80 | await request.setPods(toIds, dbRequestOptions) | ||
81 | } | ||
82 | |||
83 | // --------------------------------------------------------------------------- | ||
84 | |||
85 | afterRequestsHook () { | ||
86 | // Flush requests with no pod | ||
87 | this.getRequestModel().removeWithEmptyTo() | ||
88 | .catch(err => logger.error('Error when removing requests with no pods.', err)) | ||
89 | } | ||
90 | } | ||
91 | |||
92 | // --------------------------------------------------------------------------- | ||
93 | |||
94 | export { | ||
95 | RequestScheduler | ||
96 | } | ||
diff --git a/server/lib/request/request-video-event-scheduler.ts b/server/lib/request/request-video-event-scheduler.ts deleted file mode 100644 index 5f21287f0..000000000 --- a/server/lib/request/request-video-event-scheduler.ts +++ /dev/null | |||
@@ -1,129 +0,0 @@ | |||
1 | import * as Sequelize from 'sequelize' | ||
2 | |||
3 | import { database as db } from '../../initializers/database' | ||
4 | import { AbstractRequestScheduler, RequestsObjects } from './abstract-request-scheduler' | ||
5 | import { | ||
6 | REQUESTS_VIDEO_EVENT_LIMIT_PODS, | ||
7 | REQUESTS_VIDEO_EVENT_LIMIT_PER_POD, | ||
8 | REQUEST_VIDEO_EVENT_ENDPOINT | ||
9 | } from '../../initializers' | ||
10 | import { RequestsVideoEventGrouped } from '../../models' | ||
11 | import { RequestVideoEventType, RemoteVideoEventRequest, RemoteVideoEventType } from '../../../shared' | ||
12 | |||
13 | export type RequestVideoEventSchedulerOptions = { | ||
14 | type: RequestVideoEventType | ||
15 | videoId: number | ||
16 | count?: number | ||
17 | transaction?: Sequelize.Transaction | ||
18 | } | ||
19 | |||
20 | class RequestVideoEventScheduler extends AbstractRequestScheduler<RequestsVideoEventGrouped> { | ||
21 | constructor () { | ||
22 | super() | ||
23 | |||
24 | // We limit the size of the requests | ||
25 | this.limitPods = REQUESTS_VIDEO_EVENT_LIMIT_PODS | ||
26 | this.limitPerPod = REQUESTS_VIDEO_EVENT_LIMIT_PER_POD | ||
27 | |||
28 | this.description = 'video event requests' | ||
29 | } | ||
30 | |||
31 | getRequestModel () { | ||
32 | return db.RequestVideoEvent | ||
33 | } | ||
34 | |||
35 | getRequestToPodModel () { | ||
36 | return db.RequestVideoEvent | ||
37 | } | ||
38 | |||
39 | buildRequestsObjects (eventRequests: RequestsVideoEventGrouped) { | ||
40 | const requestsToMakeGrouped: RequestsObjects<RemoteVideoEventRequest> = {} | ||
41 | |||
42 | /* Example: | ||
43 | { | ||
44 | pod1: { | ||
45 | video1: { views: 4, likes: 5 }, | ||
46 | video2: { likes: 5 } | ||
47 | } | ||
48 | } | ||
49 | */ | ||
50 | const eventsPerVideoPerPod: { | ||
51 | [ podId: string ]: { | ||
52 | [ videoUUID: string ]: { | ||
53 | views?: number | ||
54 | likes?: number | ||
55 | dislikes?: number | ||
56 | } | ||
57 | } | ||
58 | } = {} | ||
59 | |||
60 | // We group video events per video and per pod | ||
61 | // We add the counts of the same event types | ||
62 | for (const toPodId of Object.keys(eventRequests)) { | ||
63 | for (const eventToProcess of eventRequests[toPodId]) { | ||
64 | if (!eventsPerVideoPerPod[toPodId]) eventsPerVideoPerPod[toPodId] = {} | ||
65 | |||
66 | if (!requestsToMakeGrouped[toPodId]) { | ||
67 | requestsToMakeGrouped[toPodId] = { | ||
68 | toPod: eventToProcess.pod, | ||
69 | endpoint: REQUEST_VIDEO_EVENT_ENDPOINT, | ||
70 | ids: [], // request ids, to delete them from the DB in the future | ||
71 | datas: [] // requests data | ||
72 | } | ||
73 | } | ||
74 | requestsToMakeGrouped[toPodId].ids.push(eventToProcess.id) | ||
75 | |||
76 | const eventsPerVideo = eventsPerVideoPerPod[toPodId] | ||
77 | const uuid = eventToProcess.video.uuid | ||
78 | if (!eventsPerVideo[uuid]) eventsPerVideo[uuid] = {} | ||
79 | |||
80 | const events = eventsPerVideo[uuid] | ||
81 | if (!events[eventToProcess.type]) events[eventToProcess.type] = 0 | ||
82 | |||
83 | events[eventToProcess.type] += eventToProcess.count | ||
84 | } | ||
85 | } | ||
86 | |||
87 | // Now we build our requests array per pod | ||
88 | for (const toPodId of Object.keys(eventsPerVideoPerPod)) { | ||
89 | const eventsForPod = eventsPerVideoPerPod[toPodId] | ||
90 | |||
91 | for (const uuid of Object.keys(eventsForPod)) { | ||
92 | const eventsForVideo = eventsForPod[uuid] | ||
93 | |||
94 | for (const eventType of Object.keys(eventsForVideo)) { | ||
95 | requestsToMakeGrouped[toPodId].datas.push({ | ||
96 | data: { | ||
97 | uuid, | ||
98 | eventType: eventType as RemoteVideoEventType, | ||
99 | count: +eventsForVideo[eventType] | ||
100 | } | ||
101 | }) | ||
102 | } | ||
103 | } | ||
104 | } | ||
105 | |||
106 | return requestsToMakeGrouped | ||
107 | } | ||
108 | |||
109 | createRequest ({ type, videoId, count, transaction }: RequestVideoEventSchedulerOptions) { | ||
110 | if (count === undefined) count = 1 | ||
111 | |||
112 | const dbRequestOptions: Sequelize.CreateOptions = {} | ||
113 | if (transaction) dbRequestOptions.transaction = transaction | ||
114 | |||
115 | const createQuery = { | ||
116 | type, | ||
117 | count, | ||
118 | videoId | ||
119 | } | ||
120 | |||
121 | return db.RequestVideoEvent.create(createQuery, dbRequestOptions) | ||
122 | } | ||
123 | } | ||
124 | |||
125 | // --------------------------------------------------------------------------- | ||
126 | |||
127 | export { | ||
128 | RequestVideoEventScheduler | ||
129 | } | ||
diff --git a/server/lib/request/request-video-qadu-scheduler.ts b/server/lib/request/request-video-qadu-scheduler.ts deleted file mode 100644 index 24ee59d29..000000000 --- a/server/lib/request/request-video-qadu-scheduler.ts +++ /dev/null | |||
@@ -1,148 +0,0 @@ | |||
1 | import * as Sequelize from 'sequelize' | ||
2 | |||
3 | import { database as db } from '../../initializers/database' | ||
4 | import { AbstractRequestScheduler, RequestsObjects } from './abstract-request-scheduler' | ||
5 | import { logger } from '../../helpers' | ||
6 | import { | ||
7 | REQUESTS_VIDEO_QADU_LIMIT_PODS, | ||
8 | REQUESTS_VIDEO_QADU_LIMIT_PER_POD, | ||
9 | REQUEST_VIDEO_QADU_ENDPOINT, | ||
10 | REQUEST_VIDEO_QADU_TYPES | ||
11 | } from '../../initializers' | ||
12 | import { RequestsVideoQaduGrouped, PodInstance } from '../../models' | ||
13 | import { RemoteQaduVideoRequest, RequestVideoQaduType } from '../../../shared' | ||
14 | |||
15 | // We create a custom interface because we need "videos" attribute for our computations | ||
16 | interface RequestsObjectsCustom<U> extends RequestsObjects<U> { | ||
17 | [ id: string ]: { | ||
18 | toPod: PodInstance | ||
19 | endpoint: string | ||
20 | ids: number[] // ids | ||
21 | datas: U[] | ||
22 | |||
23 | videos: { | ||
24 | [ uuid: string ]: { | ||
25 | uuid: string | ||
26 | likes?: number | ||
27 | dislikes?: number | ||
28 | views?: number | ||
29 | } | ||
30 | } | ||
31 | } | ||
32 | } | ||
33 | |||
34 | export type RequestVideoQaduSchedulerOptions = { | ||
35 | type: RequestVideoQaduType | ||
36 | videoId: number | ||
37 | transaction?: Sequelize.Transaction | ||
38 | } | ||
39 | |||
40 | class RequestVideoQaduScheduler extends AbstractRequestScheduler<RequestsVideoQaduGrouped> { | ||
41 | constructor () { | ||
42 | super() | ||
43 | |||
44 | // We limit the size of the requests | ||
45 | this.limitPods = REQUESTS_VIDEO_QADU_LIMIT_PODS | ||
46 | this.limitPerPod = REQUESTS_VIDEO_QADU_LIMIT_PER_POD | ||
47 | |||
48 | this.description = 'video QADU requests' | ||
49 | } | ||
50 | |||
51 | getRequestModel () { | ||
52 | return db.RequestVideoQadu | ||
53 | } | ||
54 | |||
55 | getRequestToPodModel () { | ||
56 | return db.RequestVideoQadu | ||
57 | } | ||
58 | |||
59 | buildRequestsObjects (requests: RequestsVideoQaduGrouped) { | ||
60 | const requestsToMakeGrouped: RequestsObjectsCustom<RemoteQaduVideoRequest> = {} | ||
61 | |||
62 | for (const toPodId of Object.keys(requests)) { | ||
63 | for (const data of requests[toPodId]) { | ||
64 | const request = data.request | ||
65 | const video = data.video | ||
66 | const pod = data.pod | ||
67 | const hashKey = toPodId | ||
68 | |||
69 | if (!requestsToMakeGrouped[hashKey]) { | ||
70 | requestsToMakeGrouped[hashKey] = { | ||
71 | toPod: pod, | ||
72 | endpoint: REQUEST_VIDEO_QADU_ENDPOINT, | ||
73 | ids: [], // request ids, to delete them from the DB in the future | ||
74 | datas: [], // requests data | ||
75 | videos: {} | ||
76 | } | ||
77 | } | ||
78 | |||
79 | // Maybe another attribute was filled for this video | ||
80 | let videoData = requestsToMakeGrouped[hashKey].videos[video.id] | ||
81 | if (!videoData) videoData = { uuid: null } | ||
82 | |||
83 | switch (request.type) { | ||
84 | case REQUEST_VIDEO_QADU_TYPES.LIKES: | ||
85 | videoData.likes = video.likes | ||
86 | break | ||
87 | |||
88 | case REQUEST_VIDEO_QADU_TYPES.DISLIKES: | ||
89 | videoData.dislikes = video.dislikes | ||
90 | break | ||
91 | |||
92 | case REQUEST_VIDEO_QADU_TYPES.VIEWS: | ||
93 | videoData.views = video.views | ||
94 | break | ||
95 | |||
96 | default: | ||
97 | logger.error('Unknown request video QADU type %s.', request.type) | ||
98 | return undefined | ||
99 | } | ||
100 | |||
101 | // Do not forget the uuid so the remote pod can identify the video | ||
102 | videoData.uuid = video.uuid | ||
103 | requestsToMakeGrouped[hashKey].ids.push(request.id) | ||
104 | |||
105 | // Maybe there are multiple quick and dirty update for the same video | ||
106 | // We use this hash map to dedupe them | ||
107 | requestsToMakeGrouped[hashKey].videos[video.id] = videoData | ||
108 | } | ||
109 | } | ||
110 | |||
111 | // Now we deduped similar quick and dirty updates, we can build our requests data | ||
112 | for (const hashKey of Object.keys(requestsToMakeGrouped)) { | ||
113 | for (const videoUUID of Object.keys(requestsToMakeGrouped[hashKey].videos)) { | ||
114 | const videoData = requestsToMakeGrouped[hashKey].videos[videoUUID] | ||
115 | |||
116 | requestsToMakeGrouped[hashKey].datas.push({ | ||
117 | data: videoData | ||
118 | }) | ||
119 | } | ||
120 | |||
121 | // We don't need it anymore, it was just to build our data array | ||
122 | delete requestsToMakeGrouped[hashKey].videos | ||
123 | } | ||
124 | |||
125 | return requestsToMakeGrouped | ||
126 | } | ||
127 | |||
128 | async createRequest ({ type, videoId, transaction }: RequestVideoQaduSchedulerOptions) { | ||
129 | const dbRequestOptions: Sequelize.BulkCreateOptions = {} | ||
130 | if (transaction) dbRequestOptions.transaction = transaction | ||
131 | |||
132 | // Send the update to all our friends | ||
133 | const podIds = await db.Pod.listAllIds(transaction) | ||
134 | const queries = [] | ||
135 | for (const podId of podIds) { | ||
136 | queries.push({ type, videoId, podId }) | ||
137 | } | ||
138 | |||
139 | await db.RequestVideoQadu.bulkCreate(queries, dbRequestOptions) | ||
140 | return undefined | ||
141 | } | ||
142 | } | ||
143 | |||
144 | // --------------------------------------------------------------------------- | ||
145 | |||
146 | export { | ||
147 | RequestVideoQaduScheduler | ||
148 | } | ||