-
Notifications
You must be signed in to change notification settings - Fork 0
Feature/ping services #23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 48 commits
cf6b853
dc9d2c9
8aa8aaa
6f17fd1
456202e
6a87e1a
d522262
e77b00e
b9edd24
befa352
1cd6462
17d9318
94ecadb
12ad87d
a690d43
ffcf8c4
af9773a
e78f88b
fe96048
d392ebd
b697b28
4be581c
f722f38
af93395
869b489
5816b0d
3f427b2
4357669
5bcc722
19cfef1
97f0726
3fd12d3
5e9d454
9b04c96
0fd1568
597ffcd
6254fb5
7e4ae5f
5fcce7c
7ef4f60
6bdbf6c
3cc0457
9303915
00c9538
185d932
3670d6a
2c59cca
228d0ac
cdfb9f3
3151c73
2044caa
f6e58e9
f0c14e7
1436e8f
b63e434
28715eb
2503fdc
8cc4b4f
b6f10b7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
import ping from 'ping'; | ||
// eslint-disable-next-line @typescript-eslint/no-unused-vars-experimental,@typescript-eslint/no-unused-vars | ||
import app from './../app'; | ||
import WorkspacesService from './../services/workspace'; | ||
import ServerProjectsStatuses, { ProjectStatus } from '../types/serverProjectsStatuses'; | ||
import IWorkspace from './../types/workspace'; | ||
// eslint-disable-next-line @typescript-eslint/no-unused-vars,@typescript-eslint/no-unused-vars-experimental | ||
import Client from 'ctproto/build/src/server/client'; | ||
// eslint-disable-next-line @typescript-eslint/no-unused-vars,@typescript-eslint/no-unused-vars-experimental | ||
import { DevopsToolboxAuthData } from '../types/api/responses/authorize'; | ||
// eslint-disable-next-line @typescript-eslint/no-unused-vars,@typescript-eslint/no-unused-vars-experimental | ||
import { ApiOutgoingMessage, ApiResponse } from '../types'; | ||
import Server from '../services/server'; | ||
// eslint-disable-next-line @typescript-eslint/no-unused-vars,@typescript-eslint/no-unused-vars-experimental | ||
import WorkspaceAggregation, { Server as IServer } from '../types/workspaceAggregation'; | ||
|
||
/** | ||
* Statuses controller to work with updating/checking/sending statuses of servers' statuses for each workspace | ||
*/ | ||
export default class StatusesController { | ||
/** | ||
* Update statuses and send to logged users | ||
*/ | ||
public static async updateStatuses(): Promise<void> { | ||
const workspaces: IWorkspace[] | null = await WorkspacesService.find({}); | ||
|
||
/** | ||
* If workspaces exist,then updating statuses for them | ||
*/ | ||
if (workspaces) { | ||
for (const workspace of workspaces) { | ||
/** | ||
* Get workspace servers and their projects | ||
*/ | ||
const workspaceAggregations: WorkspaceAggregation[] = await WorkspacesService.aggregateServices(workspace._id); | ||
|
||
|
||
/** | ||
* For each object with serverId and projects of the server update statuses | ||
*/ | ||
for (const w of workspaceAggregations) { | ||
for (const s of w.servers) { | ||
for (const service of s.services) { | ||
/** | ||
* If type of service is nginx, server's projects are pinged | ||
*/ | ||
if (service.type == 'nginx') { | ||
const projectsStatuses = await this.pingProjects(service.payload); | ||
const serverProjectsStatuses: ServerProjectsStatuses = {} as ServerProjectsStatuses; | ||
|
||
|
||
serverProjectsStatuses.projectsStatuses = projectsStatuses; | ||
serverProjectsStatuses.serverToken = s.token; | ||
await Server.updateServicesStatuses(serverProjectsStatuses); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Project availability check | ||
* | ||
* @param serverProject - array of workspace server's projects | ||
*/ | ||
public static async checkProjectAvailability(serverProject:string): Promise<ProjectStatus> { | ||
const pingServer = await ping.promise.probe(serverProject); | ||
|
||
if (serverProject === '') { | ||
neSpecc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return { | ||
host: 'Unnamed host', | ||
isOnline: false, | ||
}; | ||
} else { | ||
return { | ||
host: serverProject, | ||
isOnline: pingServer.alive, | ||
}; | ||
} | ||
} | ||
|
||
/** | ||
* Ping projects of some server | ||
* | ||
* @param projectList - list of project of payload of some service of some server | ||
*/ | ||
public static async pingProjects(projectList: Record<string, unknown>[]): Promise<ProjectStatus[]> { | ||
|
||
const projectsStatuses:ProjectStatus[] = []; | ||
|
||
for (const project of projectList) { | ||
projectsStatuses.push(await StatusesController.checkProjectAvailability(project['serverName'] as string)); | ||
} | ||
|
||
return projectsStatuses; | ||
} | ||
|
||
/** | ||
* Send statuses to clients | ||
* | ||
* @param statuses - array of statuses of all client services | ||
* @param user - user | ||
*/ | ||
// public static sendStatuses(statuses: ServerProjectsStatuses[], user: Client<DevopsToolboxAuthData, ApiResponse, ApiOutgoingMessage>): void { | ||
// if (typeof user.authData.userToken === 'string') { | ||
// app.context.transport | ||
// .clients | ||
// .find((client) => client.authData.userToken === user.authData.userToken) | ||
// .send('statuses-updated', { statuses }); | ||
// } | ||
// } | ||
Comment on lines
+100
to
+107
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Если это тебе не нужно, то можно убрать это вообще There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. комменты уберу в некст реквесте |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import mongoose from '..'; | ||
import ServerProjectsStatuses from '../../types/serverProjectsStatuses'; | ||
|
||
/** | ||
* Project status Schema | ||
*/ | ||
const serverProjectsStatusesSchema: mongoose.Schema = new mongoose.Schema({ | ||
/** | ||
* Workspace server's token | ||
*/ | ||
serverToken: { | ||
type: String, | ||
required: true, | ||
}, | ||
/** | ||
* Workspace server's projects' names and statuses | ||
*/ | ||
projectsStatuses: [ { | ||
/** | ||
* Host name | ||
*/ | ||
host: { | ||
type: String, | ||
required: true, | ||
}, | ||
/** | ||
* host status | ||
*/ | ||
isOnline: { | ||
neSpecc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
type: Boolean, | ||
required: true, | ||
}, | ||
} ], | ||
}); | ||
|
||
export default mongoose.model<ServerProjectsStatuses>('server_projects_statuses', serverProjectsStatusesSchema); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,9 +2,11 @@ | |
/// <reference path="./types/app.d.ts" /> | ||
import { CTProtoServer } from 'ctproto'; | ||
import app from './app'; | ||
import cron from 'node-cron'; | ||
import Config from './config'; | ||
import { WorkspacesController, ApiRequest, ApiResponse, ApiOutgoingMessage } from './types'; | ||
import WorkspacesService from './services/workspace'; | ||
import StatusesController from './controllers/statuses'; | ||
import { AuthorizeMessagePayload } from './types/api/requests/authorize'; | ||
import { DevopsToolboxAuthData } from './types/api/responses/authorize'; | ||
|
||
|
@@ -16,14 +18,12 @@ app.listen(Config.httpPort, Config.host, () => { | |
* Initialize CTProto server for API | ||
*/ | ||
const transport = new CTProtoServer<AuthorizeMessagePayload, DevopsToolboxAuthData, ApiRequest, ApiResponse, ApiOutgoingMessage>({ | ||
host: Config.host, | ||
port: Config.wsPort, | ||
async onAuth(authRequestPayload: AuthorizeMessagePayload): Promise<DevopsToolboxAuthData> { | ||
/** | ||
* Connected client's authorization token | ||
*/ | ||
const authToken = authRequestPayload.token.toString(); | ||
|
||
/** | ||
* Connected client's workspaces list | ||
*/ | ||
|
@@ -63,3 +63,10 @@ const transport = new CTProtoServer<AuthorizeMessagePayload, DevopsToolboxAuthDa | |
* @example req.app.locals.transport | ||
*/ | ||
app.context = { transport }; | ||
|
||
/** | ||
* Ping availability of connected user's services | ||
*/ | ||
cron.schedule(Config.pingSchedule, () => { | ||
StatusesController.updateStatuses(); | ||
|
||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import IServiceStatus from '../types/serverProjectsStatuses'; | ||
import mongoose from '../database'; | ||
import ServiceStatus from '../database/models/serverServicesStatuses'; | ||
|
||
/** | ||
* Server of workspace with token,services and projects | ||
*/ | ||
export default class Server { | ||
/** | ||
* Add new server | ||
* | ||
* @param server - new server | ||
*/ | ||
public static async add(server: IServiceStatus): Promise<IServiceStatus | null> { | ||
const newServer = new ServiceStatus(server); | ||
|
||
return newServer.save(); | ||
} | ||
|
||
/** | ||
* Update of services' statuses in DB | ||
neSpecc marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
* | ||
* @param serviceStatuses - services' statuses and server token | ||
*/ | ||
public static async updateServicesStatuses(serviceStatuses: IServiceStatus): Promise<mongoose.Document> { | ||
|
||
const server = await ServiceStatus.findOne({ serverToken: serviceStatuses.serverToken }); | ||
|
||
|
||
if (!server) { | ||
await this.add(serviceStatuses); | ||
} | ||
|
||
return ServiceStatus.updateOne({ | ||
|
||
serverToken: serviceStatuses.serverToken, | ||
}, { | ||
$set: { | ||
projectsStatuses: serviceStatuses.projectsStatuses, | ||
}, | ||
|
||
}, { | ||
new: true, | ||
}); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { NewMessage } from 'ctproto/types'; | ||
import ServerProjectsStatuses from '../../serverProjectsStatuses'; | ||
|
||
/** | ||
* Data about the updated statuses | ||
*/ | ||
interface StatusesUpdatedPayload { | ||
/** | ||
* The updated workspace | ||
*/ | ||
projectsStatuses: ServerProjectsStatuses; | ||
} | ||
|
||
/** | ||
* Describes the outgoing message that will be sent when statuses of services will be updated | ||
*/ | ||
export default interface StatusesUpdatedMessage extends NewMessage<StatusesUpdatedPayload> { | ||
type: 'statuses-updated'; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import * as mongoose from 'mongoose'; | ||
|
||
|
||
/** | ||
* Project status of the server | ||
*/ | ||
export interface ProjectStatus { | ||
/** | ||
* Name of host | ||
*/ | ||
host: string; | ||
/** | ||
* State of host (online/offline) | ||
*/ | ||
isOnline: boolean; | ||
} | ||
/** | ||
* Status of service in workspace | ||
*/ | ||
export default interface ServerProjectsStatuses extends mongoose.Document { | ||
/** | ||
* Server's (containing the services) id | ||
*/ | ||
serverToken: string; | ||
/** | ||
* Projects with their statuses of the server | ||
*/ | ||
projectsStatuses: ProjectStatus[]; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
А
eslint-disable
нужны?