mirror of
https://github.com/whyour/qinglong.git
synced 2025-07-07 03:46:07 +08:00
增加容器健康检查
This commit is contained in:
parent
0af687f781
commit
d11d6d0c18
|
@ -15,6 +15,7 @@ export default defineConfig({
|
||||||
'/api/public': {
|
'/api/public': {
|
||||||
target: 'http://127.0.0.1:5400/',
|
target: 'http://127.0.0.1:5400/',
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
|
pathRewrite: { '^/api/public': '/api/' },
|
||||||
},
|
},
|
||||||
'/api': {
|
'/api': {
|
||||||
target: 'http://127.0.0.1:5600/',
|
target: 'http://127.0.0.1:5600/',
|
||||||
|
|
|
@ -2,21 +2,21 @@ syntax = "proto3";
|
||||||
|
|
||||||
package com.ql.cron;
|
package com.ql.cron;
|
||||||
|
|
||||||
service CronService {
|
service Cron {
|
||||||
rpc addCron(AddCronRequest) returns (AddCronResponse);
|
rpc addCron(AddCronRequest) returns (AddCronResponse);
|
||||||
rpc delCron(DeleteCronRequest) returns (DeleteCronResponse);
|
rpc delCron(DeleteCronRequest) returns (DeleteCronResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
message Cron {
|
message ICron {
|
||||||
string id = 1;
|
string id = 1;
|
||||||
string schedule = 2;
|
string schedule = 2;
|
||||||
string command = 3;
|
string command = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message AddCronRequest { repeated Cron crons = 1; }
|
message AddCronRequest { repeated ICron crons = 1; }
|
||||||
|
|
||||||
message AddCronResponse {}
|
message AddCronResponse {}
|
||||||
|
|
||||||
message DeleteCronRequest { repeated string ids = 1; }
|
message DeleteCronRequest { repeated string ids = 1; }
|
||||||
|
|
||||||
message DeleteCronResponse {}
|
message DeleteCronResponse {}
|
||||||
|
|
|
@ -15,14 +15,14 @@ import _m0 from 'protobufjs/minimal';
|
||||||
|
|
||||||
export const protobufPackage = 'com.ql.cron';
|
export const protobufPackage = 'com.ql.cron';
|
||||||
|
|
||||||
export interface Cron {
|
export interface ICron {
|
||||||
id: string;
|
id: string;
|
||||||
schedule: string;
|
schedule: string;
|
||||||
command: string;
|
command: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AddCronRequest {
|
export interface AddCronRequest {
|
||||||
crons: Cron[];
|
crons: ICron[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AddCronResponse {}
|
export interface AddCronResponse {}
|
||||||
|
@ -33,12 +33,12 @@ export interface DeleteCronRequest {
|
||||||
|
|
||||||
export interface DeleteCronResponse {}
|
export interface DeleteCronResponse {}
|
||||||
|
|
||||||
function createBaseCron(): Cron {
|
function createBaseICron(): ICron {
|
||||||
return { id: '', schedule: '', command: '' };
|
return { id: '', schedule: '', command: '' };
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Cron = {
|
export const ICron = {
|
||||||
encode(message: Cron, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
|
encode(message: ICron, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
|
||||||
if (message.id !== '') {
|
if (message.id !== '') {
|
||||||
writer.uint32(10).string(message.id);
|
writer.uint32(10).string(message.id);
|
||||||
}
|
}
|
||||||
|
@ -51,11 +51,11 @@ export const Cron = {
|
||||||
return writer;
|
return writer;
|
||||||
},
|
},
|
||||||
|
|
||||||
decode(input: _m0.Reader | Uint8Array, length?: number): Cron {
|
decode(input: _m0.Reader | Uint8Array, length?: number): ICron {
|
||||||
const reader =
|
const reader =
|
||||||
input instanceof _m0.Reader ? input : _m0.Reader.create(input);
|
input instanceof _m0.Reader ? input : _m0.Reader.create(input);
|
||||||
let end = length === undefined ? reader.len : reader.pos + length;
|
let end = length === undefined ? reader.len : reader.pos + length;
|
||||||
const message = createBaseCron();
|
const message = createBaseICron();
|
||||||
while (reader.pos < end) {
|
while (reader.pos < end) {
|
||||||
const tag = reader.uint32();
|
const tag = reader.uint32();
|
||||||
switch (tag >>> 3) {
|
switch (tag >>> 3) {
|
||||||
|
@ -89,7 +89,7 @@ export const Cron = {
|
||||||
return message;
|
return message;
|
||||||
},
|
},
|
||||||
|
|
||||||
fromJSON(object: any): Cron {
|
fromJSON(object: any): ICron {
|
||||||
return {
|
return {
|
||||||
id: isSet(object.id) ? String(object.id) : '',
|
id: isSet(object.id) ? String(object.id) : '',
|
||||||
schedule: isSet(object.schedule) ? String(object.schedule) : '',
|
schedule: isSet(object.schedule) ? String(object.schedule) : '',
|
||||||
|
@ -97,7 +97,7 @@ export const Cron = {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
toJSON(message: Cron): unknown {
|
toJSON(message: ICron): unknown {
|
||||||
const obj: any = {};
|
const obj: any = {};
|
||||||
message.id !== undefined && (obj.id = message.id);
|
message.id !== undefined && (obj.id = message.id);
|
||||||
message.schedule !== undefined && (obj.schedule = message.schedule);
|
message.schedule !== undefined && (obj.schedule = message.schedule);
|
||||||
|
@ -105,12 +105,12 @@ export const Cron = {
|
||||||
return obj;
|
return obj;
|
||||||
},
|
},
|
||||||
|
|
||||||
create<I extends Exact<DeepPartial<Cron>, I>>(base?: I): Cron {
|
create<I extends Exact<DeepPartial<ICron>, I>>(base?: I): ICron {
|
||||||
return Cron.fromPartial(base ?? {});
|
return ICron.fromPartial(base ?? {});
|
||||||
},
|
},
|
||||||
|
|
||||||
fromPartial<I extends Exact<DeepPartial<Cron>, I>>(object: I): Cron {
|
fromPartial<I extends Exact<DeepPartial<ICron>, I>>(object: I): ICron {
|
||||||
const message = createBaseCron();
|
const message = createBaseICron();
|
||||||
message.id = object.id ?? '';
|
message.id = object.id ?? '';
|
||||||
message.schedule = object.schedule ?? '';
|
message.schedule = object.schedule ?? '';
|
||||||
message.command = object.command ?? '';
|
message.command = object.command ?? '';
|
||||||
|
@ -128,7 +128,7 @@ export const AddCronRequest = {
|
||||||
writer: _m0.Writer = _m0.Writer.create(),
|
writer: _m0.Writer = _m0.Writer.create(),
|
||||||
): _m0.Writer {
|
): _m0.Writer {
|
||||||
for (const v of message.crons) {
|
for (const v of message.crons) {
|
||||||
Cron.encode(v!, writer.uint32(10).fork()).ldelim();
|
ICron.encode(v!, writer.uint32(10).fork()).ldelim();
|
||||||
}
|
}
|
||||||
return writer;
|
return writer;
|
||||||
},
|
},
|
||||||
|
@ -146,7 +146,7 @@ export const AddCronRequest = {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
message.crons.push(Cron.decode(reader, reader.uint32()));
|
message.crons.push(ICron.decode(reader, reader.uint32()));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ((tag & 7) == 4 || tag == 0) {
|
if ((tag & 7) == 4 || tag == 0) {
|
||||||
|
@ -160,7 +160,7 @@ export const AddCronRequest = {
|
||||||
fromJSON(object: any): AddCronRequest {
|
fromJSON(object: any): AddCronRequest {
|
||||||
return {
|
return {
|
||||||
crons: Array.isArray(object?.crons)
|
crons: Array.isArray(object?.crons)
|
||||||
? object.crons.map((e: any) => Cron.fromJSON(e))
|
? object.crons.map((e: any) => ICron.fromJSON(e))
|
||||||
: [],
|
: [],
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
@ -168,7 +168,7 @@ export const AddCronRequest = {
|
||||||
toJSON(message: AddCronRequest): unknown {
|
toJSON(message: AddCronRequest): unknown {
|
||||||
const obj: any = {};
|
const obj: any = {};
|
||||||
if (message.crons) {
|
if (message.crons) {
|
||||||
obj.crons = message.crons.map((e) => (e ? Cron.toJSON(e) : undefined));
|
obj.crons = message.crons.map((e) => (e ? ICron.toJSON(e) : undefined));
|
||||||
} else {
|
} else {
|
||||||
obj.crons = [];
|
obj.crons = [];
|
||||||
}
|
}
|
||||||
|
@ -185,7 +185,7 @@ export const AddCronRequest = {
|
||||||
object: I,
|
object: I,
|
||||||
): AddCronRequest {
|
): AddCronRequest {
|
||||||
const message = createBaseAddCronRequest();
|
const message = createBaseAddCronRequest();
|
||||||
message.crons = object.crons?.map((e) => Cron.fromPartial(e)) || [];
|
message.crons = object.crons?.map((e) => ICron.fromPartial(e)) || [];
|
||||||
return message;
|
return message;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -366,10 +366,10 @@ export const DeleteCronResponse = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export type CronServiceService = typeof CronServiceService;
|
export type CronService = typeof CronService;
|
||||||
export const CronServiceService = {
|
export const CronService = {
|
||||||
addCron: {
|
addCron: {
|
||||||
path: '/com.ql.cron.CronService/addCron',
|
path: '/com.ql.cron.Cron/addCron',
|
||||||
requestStream: false,
|
requestStream: false,
|
||||||
responseStream: false,
|
responseStream: false,
|
||||||
requestSerialize: (value: AddCronRequest) =>
|
requestSerialize: (value: AddCronRequest) =>
|
||||||
|
@ -380,7 +380,7 @@ export const CronServiceService = {
|
||||||
responseDeserialize: (value: Buffer) => AddCronResponse.decode(value),
|
responseDeserialize: (value: Buffer) => AddCronResponse.decode(value),
|
||||||
},
|
},
|
||||||
delCron: {
|
delCron: {
|
||||||
path: '/com.ql.cron.CronService/delCron',
|
path: '/com.ql.cron.Cron/delCron',
|
||||||
requestStream: false,
|
requestStream: false,
|
||||||
responseStream: false,
|
responseStream: false,
|
||||||
requestSerialize: (value: DeleteCronRequest) =>
|
requestSerialize: (value: DeleteCronRequest) =>
|
||||||
|
@ -392,12 +392,12 @@ export const CronServiceService = {
|
||||||
},
|
},
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export interface CronServiceServer extends UntypedServiceImplementation {
|
export interface CronServer extends UntypedServiceImplementation {
|
||||||
addCron: handleUnaryCall<AddCronRequest, AddCronResponse>;
|
addCron: handleUnaryCall<AddCronRequest, AddCronResponse>;
|
||||||
delCron: handleUnaryCall<DeleteCronRequest, DeleteCronResponse>;
|
delCron: handleUnaryCall<DeleteCronRequest, DeleteCronResponse>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CronServiceClient extends Client {
|
export interface CronClient extends Client {
|
||||||
addCron(
|
addCron(
|
||||||
request: AddCronRequest,
|
request: AddCronRequest,
|
||||||
callback: (error: ServiceError | null, response: AddCronResponse) => void,
|
callback: (error: ServiceError | null, response: AddCronResponse) => void,
|
||||||
|
@ -439,16 +439,16 @@ export interface CronServiceClient extends Client {
|
||||||
): ClientUnaryCall;
|
): ClientUnaryCall;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const CronServiceClient = makeGenericClientConstructor(
|
export const CronClient = makeGenericClientConstructor(
|
||||||
CronServiceService,
|
CronService,
|
||||||
'com.ql.cron.CronService',
|
'com.ql.cron.Cron',
|
||||||
) as unknown as {
|
) as unknown as {
|
||||||
new (
|
new (
|
||||||
address: string,
|
address: string,
|
||||||
credentials: ChannelCredentials,
|
credentials: ChannelCredentials,
|
||||||
options?: Partial<ClientOptions>,
|
options?: Partial<ClientOptions>,
|
||||||
): CronServiceClient;
|
): CronClient;
|
||||||
service: typeof CronServiceService;
|
service: typeof CronService;
|
||||||
};
|
};
|
||||||
|
|
||||||
type Builtin =
|
type Builtin =
|
||||||
|
|
22
back/protos/health.proto
Normal file
22
back/protos/health.proto
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package com.ql.health;
|
||||||
|
|
||||||
|
message HealthCheckRequest {
|
||||||
|
string service = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message HealthCheckResponse {
|
||||||
|
enum ServingStatus {
|
||||||
|
UNKNOWN = 0;
|
||||||
|
SERVING = 1;
|
||||||
|
NOT_SERVING = 2;
|
||||||
|
SERVICE_UNKNOWN = 3;
|
||||||
|
}
|
||||||
|
ServingStatus status = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
service Health {
|
||||||
|
rpc Check(HealthCheckRequest) returns (HealthCheckResponse);
|
||||||
|
rpc Watch(HealthCheckRequest) returns (stream HealthCheckResponse);
|
||||||
|
}
|
317
back/protos/health.ts
Normal file
317
back/protos/health.ts
Normal file
|
@ -0,0 +1,317 @@
|
||||||
|
/* eslint-disable */
|
||||||
|
import {
|
||||||
|
CallOptions,
|
||||||
|
ChannelCredentials,
|
||||||
|
Client,
|
||||||
|
ClientOptions,
|
||||||
|
ClientReadableStream,
|
||||||
|
ClientUnaryCall,
|
||||||
|
handleServerStreamingCall,
|
||||||
|
handleUnaryCall,
|
||||||
|
makeGenericClientConstructor,
|
||||||
|
Metadata,
|
||||||
|
ServiceError,
|
||||||
|
UntypedServiceImplementation,
|
||||||
|
} from '@grpc/grpc-js';
|
||||||
|
import _m0 from 'protobufjs/minimal';
|
||||||
|
|
||||||
|
export const protobufPackage = 'com.ql.health';
|
||||||
|
|
||||||
|
export interface HealthCheckRequest {
|
||||||
|
service: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HealthCheckResponse {
|
||||||
|
status: HealthCheckResponse_ServingStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum HealthCheckResponse_ServingStatus {
|
||||||
|
UNKNOWN = 0,
|
||||||
|
SERVING = 1,
|
||||||
|
NOT_SERVING = 2,
|
||||||
|
SERVICE_UNKNOWN = 3,
|
||||||
|
UNRECOGNIZED = -1,
|
||||||
|
}
|
||||||
|
|
||||||
|
export function healthCheckResponse_ServingStatusFromJSON(
|
||||||
|
object: any,
|
||||||
|
): HealthCheckResponse_ServingStatus {
|
||||||
|
switch (object) {
|
||||||
|
case 0:
|
||||||
|
case 'UNKNOWN':
|
||||||
|
return HealthCheckResponse_ServingStatus.UNKNOWN;
|
||||||
|
case 1:
|
||||||
|
case 'SERVING':
|
||||||
|
return HealthCheckResponse_ServingStatus.SERVING;
|
||||||
|
case 2:
|
||||||
|
case 'NOT_SERVING':
|
||||||
|
return HealthCheckResponse_ServingStatus.NOT_SERVING;
|
||||||
|
case 3:
|
||||||
|
case 'SERVICE_UNKNOWN':
|
||||||
|
return HealthCheckResponse_ServingStatus.SERVICE_UNKNOWN;
|
||||||
|
case -1:
|
||||||
|
case 'UNRECOGNIZED':
|
||||||
|
default:
|
||||||
|
return HealthCheckResponse_ServingStatus.UNRECOGNIZED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function healthCheckResponse_ServingStatusToJSON(
|
||||||
|
object: HealthCheckResponse_ServingStatus,
|
||||||
|
): string {
|
||||||
|
switch (object) {
|
||||||
|
case HealthCheckResponse_ServingStatus.UNKNOWN:
|
||||||
|
return 'UNKNOWN';
|
||||||
|
case HealthCheckResponse_ServingStatus.SERVING:
|
||||||
|
return 'SERVING';
|
||||||
|
case HealthCheckResponse_ServingStatus.NOT_SERVING:
|
||||||
|
return 'NOT_SERVING';
|
||||||
|
case HealthCheckResponse_ServingStatus.SERVICE_UNKNOWN:
|
||||||
|
return 'SERVICE_UNKNOWN';
|
||||||
|
case HealthCheckResponse_ServingStatus.UNRECOGNIZED:
|
||||||
|
default:
|
||||||
|
return 'UNRECOGNIZED';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function createBaseHealthCheckRequest(): HealthCheckRequest {
|
||||||
|
return { service: '' };
|
||||||
|
}
|
||||||
|
|
||||||
|
export const HealthCheckRequest = {
|
||||||
|
encode(
|
||||||
|
message: HealthCheckRequest,
|
||||||
|
writer: _m0.Writer = _m0.Writer.create(),
|
||||||
|
): _m0.Writer {
|
||||||
|
if (message.service !== '') {
|
||||||
|
writer.uint32(10).string(message.service);
|
||||||
|
}
|
||||||
|
return writer;
|
||||||
|
},
|
||||||
|
|
||||||
|
decode(input: _m0.Reader | Uint8Array, length?: number): HealthCheckRequest {
|
||||||
|
const reader =
|
||||||
|
input instanceof _m0.Reader ? input : _m0.Reader.create(input);
|
||||||
|
let end = length === undefined ? reader.len : reader.pos + length;
|
||||||
|
const message = createBaseHealthCheckRequest();
|
||||||
|
while (reader.pos < end) {
|
||||||
|
const tag = reader.uint32();
|
||||||
|
switch (tag >>> 3) {
|
||||||
|
case 1:
|
||||||
|
if (tag != 10) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
message.service = reader.string();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ((tag & 7) == 4 || tag == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
reader.skipType(tag & 7);
|
||||||
|
}
|
||||||
|
return message;
|
||||||
|
},
|
||||||
|
|
||||||
|
fromJSON(object: any): HealthCheckRequest {
|
||||||
|
return { service: isSet(object.service) ? String(object.service) : '' };
|
||||||
|
},
|
||||||
|
|
||||||
|
toJSON(message: HealthCheckRequest): unknown {
|
||||||
|
const obj: any = {};
|
||||||
|
message.service !== undefined && (obj.service = message.service);
|
||||||
|
return obj;
|
||||||
|
},
|
||||||
|
|
||||||
|
create<I extends Exact<DeepPartial<HealthCheckRequest>, I>>(
|
||||||
|
base?: I,
|
||||||
|
): HealthCheckRequest {
|
||||||
|
return HealthCheckRequest.fromPartial(base ?? {});
|
||||||
|
},
|
||||||
|
|
||||||
|
fromPartial<I extends Exact<DeepPartial<HealthCheckRequest>, I>>(
|
||||||
|
object: I,
|
||||||
|
): HealthCheckRequest {
|
||||||
|
const message = createBaseHealthCheckRequest();
|
||||||
|
message.service = object.service ?? '';
|
||||||
|
return message;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function createBaseHealthCheckResponse(): HealthCheckResponse {
|
||||||
|
return { status: 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
export const HealthCheckResponse = {
|
||||||
|
encode(
|
||||||
|
message: HealthCheckResponse,
|
||||||
|
writer: _m0.Writer = _m0.Writer.create(),
|
||||||
|
): _m0.Writer {
|
||||||
|
if (message.status !== 0) {
|
||||||
|
writer.uint32(8).int32(message.status);
|
||||||
|
}
|
||||||
|
return writer;
|
||||||
|
},
|
||||||
|
|
||||||
|
decode(input: _m0.Reader | Uint8Array, length?: number): HealthCheckResponse {
|
||||||
|
const reader =
|
||||||
|
input instanceof _m0.Reader ? input : _m0.Reader.create(input);
|
||||||
|
let end = length === undefined ? reader.len : reader.pos + length;
|
||||||
|
const message = createBaseHealthCheckResponse();
|
||||||
|
while (reader.pos < end) {
|
||||||
|
const tag = reader.uint32();
|
||||||
|
switch (tag >>> 3) {
|
||||||
|
case 1:
|
||||||
|
if (tag != 8) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
message.status = reader.int32() as any;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ((tag & 7) == 4 || tag == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
reader.skipType(tag & 7);
|
||||||
|
}
|
||||||
|
return message;
|
||||||
|
},
|
||||||
|
|
||||||
|
fromJSON(object: any): HealthCheckResponse {
|
||||||
|
return {
|
||||||
|
status: isSet(object.status)
|
||||||
|
? healthCheckResponse_ServingStatusFromJSON(object.status)
|
||||||
|
: 0,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
toJSON(message: HealthCheckResponse): unknown {
|
||||||
|
const obj: any = {};
|
||||||
|
message.status !== undefined &&
|
||||||
|
(obj.status = healthCheckResponse_ServingStatusToJSON(message.status));
|
||||||
|
return obj;
|
||||||
|
},
|
||||||
|
|
||||||
|
create<I extends Exact<DeepPartial<HealthCheckResponse>, I>>(
|
||||||
|
base?: I,
|
||||||
|
): HealthCheckResponse {
|
||||||
|
return HealthCheckResponse.fromPartial(base ?? {});
|
||||||
|
},
|
||||||
|
|
||||||
|
fromPartial<I extends Exact<DeepPartial<HealthCheckResponse>, I>>(
|
||||||
|
object: I,
|
||||||
|
): HealthCheckResponse {
|
||||||
|
const message = createBaseHealthCheckResponse();
|
||||||
|
message.status = object.status ?? 0;
|
||||||
|
return message;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export type HealthService = typeof HealthService;
|
||||||
|
export const HealthService = {
|
||||||
|
check: {
|
||||||
|
path: '/com.ql.health.Health/Check',
|
||||||
|
requestStream: false,
|
||||||
|
responseStream: false,
|
||||||
|
requestSerialize: (value: HealthCheckRequest) =>
|
||||||
|
Buffer.from(HealthCheckRequest.encode(value).finish()),
|
||||||
|
requestDeserialize: (value: Buffer) => HealthCheckRequest.decode(value),
|
||||||
|
responseSerialize: (value: HealthCheckResponse) =>
|
||||||
|
Buffer.from(HealthCheckResponse.encode(value).finish()),
|
||||||
|
responseDeserialize: (value: Buffer) => HealthCheckResponse.decode(value),
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
path: '/com.ql.health.Health/Watch',
|
||||||
|
requestStream: false,
|
||||||
|
responseStream: true,
|
||||||
|
requestSerialize: (value: HealthCheckRequest) =>
|
||||||
|
Buffer.from(HealthCheckRequest.encode(value).finish()),
|
||||||
|
requestDeserialize: (value: Buffer) => HealthCheckRequest.decode(value),
|
||||||
|
responseSerialize: (value: HealthCheckResponse) =>
|
||||||
|
Buffer.from(HealthCheckResponse.encode(value).finish()),
|
||||||
|
responseDeserialize: (value: Buffer) => HealthCheckResponse.decode(value),
|
||||||
|
},
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export interface HealthServer extends UntypedServiceImplementation {
|
||||||
|
check: handleUnaryCall<HealthCheckRequest, HealthCheckResponse>;
|
||||||
|
watch: handleServerStreamingCall<HealthCheckRequest, HealthCheckResponse>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HealthClient extends Client {
|
||||||
|
check(
|
||||||
|
request: HealthCheckRequest,
|
||||||
|
callback: (
|
||||||
|
error: ServiceError | null,
|
||||||
|
response: HealthCheckResponse,
|
||||||
|
) => void,
|
||||||
|
): ClientUnaryCall;
|
||||||
|
check(
|
||||||
|
request: HealthCheckRequest,
|
||||||
|
metadata: Metadata,
|
||||||
|
callback: (
|
||||||
|
error: ServiceError | null,
|
||||||
|
response: HealthCheckResponse,
|
||||||
|
) => void,
|
||||||
|
): ClientUnaryCall;
|
||||||
|
check(
|
||||||
|
request: HealthCheckRequest,
|
||||||
|
metadata: Metadata,
|
||||||
|
options: Partial<CallOptions>,
|
||||||
|
callback: (
|
||||||
|
error: ServiceError | null,
|
||||||
|
response: HealthCheckResponse,
|
||||||
|
) => void,
|
||||||
|
): ClientUnaryCall;
|
||||||
|
watch(
|
||||||
|
request: HealthCheckRequest,
|
||||||
|
options?: Partial<CallOptions>,
|
||||||
|
): ClientReadableStream<HealthCheckResponse>;
|
||||||
|
watch(
|
||||||
|
request: HealthCheckRequest,
|
||||||
|
metadata?: Metadata,
|
||||||
|
options?: Partial<CallOptions>,
|
||||||
|
): ClientReadableStream<HealthCheckResponse>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const HealthClient = makeGenericClientConstructor(
|
||||||
|
HealthService,
|
||||||
|
'com.ql.health.Health',
|
||||||
|
) as unknown as {
|
||||||
|
new (
|
||||||
|
address: string,
|
||||||
|
credentials: ChannelCredentials,
|
||||||
|
options?: Partial<ClientOptions>,
|
||||||
|
): HealthClient;
|
||||||
|
service: typeof HealthService;
|
||||||
|
};
|
||||||
|
|
||||||
|
type Builtin =
|
||||||
|
| Date
|
||||||
|
| Function
|
||||||
|
| Uint8Array
|
||||||
|
| string
|
||||||
|
| number
|
||||||
|
| boolean
|
||||||
|
| undefined;
|
||||||
|
|
||||||
|
export type DeepPartial<T> = T extends Builtin
|
||||||
|
? T
|
||||||
|
: T extends Array<infer U>
|
||||||
|
? Array<DeepPartial<U>>
|
||||||
|
: T extends ReadonlyArray<infer U>
|
||||||
|
? ReadonlyArray<DeepPartial<U>>
|
||||||
|
: T extends {}
|
||||||
|
? { [K in keyof T]?: DeepPartial<T[K]> }
|
||||||
|
: Partial<T>;
|
||||||
|
|
||||||
|
type KeysOfUnion<T> = T extends T ? keyof T : never;
|
||||||
|
export type Exact<P, I extends P> = P extends Builtin
|
||||||
|
? P
|
||||||
|
: P & { [K in keyof P]: Exact<P[K], I[K]> } & {
|
||||||
|
[K in Exclude<keyof I, KeysOfUnion<P>>]: never;
|
||||||
|
};
|
||||||
|
|
||||||
|
function isSet(value: any): boolean {
|
||||||
|
return value !== null && value !== undefined;
|
||||||
|
}
|
|
@ -2,15 +2,21 @@ import express from 'express';
|
||||||
import { exec } from 'child_process';
|
import { exec } from 'child_process';
|
||||||
import Logger from './loaders/logger';
|
import Logger from './loaders/logger';
|
||||||
import config from './config';
|
import config from './config';
|
||||||
|
import { HealthClient } from './protos/health';
|
||||||
|
import { credentials } from '@grpc/grpc-js';
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
|
const client = new HealthClient(
|
||||||
|
`localhost:${config.cronPort}`,
|
||||||
|
credentials.createInsecure(),
|
||||||
|
);
|
||||||
|
|
||||||
app.get('/api/public/panel/log', (req, res) => {
|
app.get('/api/health', (req, res) => {
|
||||||
exec('tail -n 300 ~/.pm2/logs/panel-error.log', (err, stdout, stderr) => {
|
client.check({ service: 'cron' }, (err, response) => {
|
||||||
if (err || stderr) {
|
if (err) {
|
||||||
return res.send({ code: 400, message: (err && err.message) || stderr });
|
return res.status(500).send({ error: err });
|
||||||
}
|
}
|
||||||
return res.send({ code: 200, data: stdout });
|
return res.status(200).send({ data: response });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -2,14 +2,14 @@ import { credentials } from '@grpc/grpc-js';
|
||||||
import {
|
import {
|
||||||
AddCronRequest,
|
AddCronRequest,
|
||||||
AddCronResponse,
|
AddCronResponse,
|
||||||
CronServiceClient,
|
CronClient,
|
||||||
DeleteCronRequest,
|
DeleteCronRequest,
|
||||||
DeleteCronResponse,
|
DeleteCronResponse,
|
||||||
} from '../protos/cron';
|
} from '../protos/cron';
|
||||||
import config from '../config';
|
import config from '../config';
|
||||||
|
|
||||||
class Client {
|
class Client {
|
||||||
private client = new CronServiceClient(
|
private client = new CronClient(
|
||||||
`localhost:${config.cronPort}`,
|
`localhost:${config.cronPort}`,
|
||||||
credentials.createInsecure(),
|
credentials.createInsecure(),
|
||||||
);
|
);
|
||||||
|
|
30
back/schedule/health.ts
Normal file
30
back/schedule/health.ts
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
import { ServerUnaryCall, sendUnaryData } from '@grpc/grpc-js';
|
||||||
|
import { HealthCheckRequest, HealthCheckResponse } from '../protos/health';
|
||||||
|
import { exec } from 'child_process';
|
||||||
|
import config from '../config';
|
||||||
|
import { promiseExec } from '../config/util';
|
||||||
|
|
||||||
|
const check = async (
|
||||||
|
call: ServerUnaryCall<HealthCheckRequest, HealthCheckResponse>,
|
||||||
|
callback: sendUnaryData<HealthCheckResponse>,
|
||||||
|
) => {
|
||||||
|
switch (call.request.service) {
|
||||||
|
case 'cron':
|
||||||
|
const res = await promiseExec(
|
||||||
|
`curl -sf http://localhost:${config.port}/api/system`,
|
||||||
|
);
|
||||||
|
console.log(res);
|
||||||
|
if (res.includes('200')) {
|
||||||
|
return callback(null, { status: 1 });
|
||||||
|
}
|
||||||
|
const errLog = await promiseExec(
|
||||||
|
`tail -n 300 ~/.pm2/logs/panel-error.log`,
|
||||||
|
);
|
||||||
|
return callback(new Error(errLog));
|
||||||
|
|
||||||
|
default:
|
||||||
|
return callback(null, { status: 1 });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export { check };
|
|
@ -1,12 +1,15 @@
|
||||||
import { Server, ServerCredentials } from '@grpc/grpc-js';
|
import { Server, ServerCredentials } from '@grpc/grpc-js';
|
||||||
import { CronServiceService } from '../protos/cron';
|
import { CronService } from '../protos/cron';
|
||||||
import { addCron } from './addCron';
|
import { addCron } from './addCron';
|
||||||
import { delCron } from './delCron';
|
import { delCron } from './delCron';
|
||||||
|
import { HealthService } from '../protos/health';
|
||||||
|
import { check } from './health';
|
||||||
import config from '../config';
|
import config from '../config';
|
||||||
import Logger from '../loaders/logger';
|
import Logger from '../loaders/logger';
|
||||||
|
|
||||||
const server = new Server();
|
const server = new Server();
|
||||||
server.addService(CronServiceService, { addCron, delCron });
|
server.addService(HealthService, { check });
|
||||||
|
server.addService(CronService, { addCron, delCron });
|
||||||
server.bindAsync(
|
server.bindAsync(
|
||||||
`localhost:${config.cronPort}`,
|
`localhost:${config.cronPort}`,
|
||||||
ServerCredentials.createInsecure(),
|
ServerCredentials.createInsecure(),
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
FROM python:3.10-alpine as builder
|
FROM python:3.10-alpine as builder
|
||||||
COPY package.json .npmrc pnpm-lock.yaml /tmp/build/
|
COPY package.json .npmrc pnpm-lock.yaml /tmp/build/
|
||||||
RUN set -x \
|
RUN set -x \
|
||||||
&& apk update \
|
&& apk update \
|
||||||
&& apk add nodejs npm git \
|
&& apk add nodejs npm git \
|
||||||
&& npm i -g pnpm \
|
&& npm i -g pnpm \
|
||||||
&& cd /tmp/build \
|
&& cd /tmp/build \
|
||||||
&& pnpm install --prod
|
&& pnpm install --prod
|
||||||
|
|
||||||
FROM python:3.10-alpine
|
FROM python:3.10-alpine
|
||||||
|
|
||||||
|
@ -15,59 +15,62 @@ ARG QL_URL=https://github.com/${QL_MAINTAINER}/qinglong.git
|
||||||
ARG QL_BRANCH=develop
|
ARG QL_BRANCH=develop
|
||||||
|
|
||||||
ENV PNPM_HOME=/root/.local/share/pnpm \
|
ENV PNPM_HOME=/root/.local/share/pnpm \
|
||||||
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/root/.local/share/pnpm:/root/.local/share/pnpm/global/5/node_modules:$PNPM_HOME \
|
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/root/.local/share/pnpm:/root/.local/share/pnpm/global/5/node_modules:$PNPM_HOME \
|
||||||
NODE_PATH=/usr/local/bin:/usr/local/pnpm-global/5/node_modules:/usr/local/lib/node_modules:/root/.local/share/pnpm/global/5/node_modules \
|
NODE_PATH=/usr/local/bin:/usr/local/pnpm-global/5/node_modules:/usr/local/lib/node_modules:/root/.local/share/pnpm/global/5/node_modules \
|
||||||
LANG=C.UTF-8 \
|
LANG=C.UTF-8 \
|
||||||
SHELL=/bin/bash \
|
SHELL=/bin/bash \
|
||||||
PS1="\u@\h:\w \$ " \
|
PS1="\u@\h:\w \$ " \
|
||||||
QL_DIR=/ql \
|
QL_DIR=/ql \
|
||||||
QL_BRANCH=${QL_BRANCH}
|
QL_BRANCH=${QL_BRANCH}
|
||||||
|
|
||||||
RUN set -x \
|
RUN set -x \
|
||||||
&& sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories \
|
&& sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories \
|
||||||
&& apk update -f \
|
&& apk update -f \
|
||||||
&& apk upgrade \
|
&& apk upgrade \
|
||||||
&& apk --no-cache add -f bash \
|
&& apk --no-cache add -f bash \
|
||||||
coreutils \
|
coreutils \
|
||||||
moreutils \
|
moreutils \
|
||||||
git \
|
git \
|
||||||
curl \
|
curl \
|
||||||
wget \
|
wget \
|
||||||
tzdata \
|
tzdata \
|
||||||
perl \
|
perl \
|
||||||
openssl \
|
openssl \
|
||||||
nginx \
|
nginx \
|
||||||
nodejs \
|
nodejs \
|
||||||
jq \
|
jq \
|
||||||
openssh \
|
openssh \
|
||||||
npm \
|
npm \
|
||||||
&& rm -rf /var/cache/apk/* \
|
&& rm -rf /var/cache/apk/* \
|
||||||
&& apk update \
|
&& apk update \
|
||||||
&& ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
|
&& ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
|
||||||
&& echo "Asia/Shanghai" > /etc/timezone \
|
&& echo "Asia/Shanghai" > /etc/timezone \
|
||||||
&& git config --global user.email "qinglong@@users.noreply.github.com" \
|
&& git config --global user.email "qinglong@@users.noreply.github.com" \
|
||||||
&& git config --global user.name "qinglong" \
|
&& git config --global user.name "qinglong" \
|
||||||
&& git config --global http.postBuffer 524288000 \
|
&& git config --global http.postBuffer 524288000 \
|
||||||
&& npm install -g pnpm \
|
&& npm install -g pnpm \
|
||||||
&& pnpm add -g pm2 tsx \
|
&& pnpm add -g pm2 tsx \
|
||||||
&& rm -rf /root/.pnpm-store \
|
&& rm -rf /root/.pnpm-store \
|
||||||
&& rm -rf /root/.local/share/pnpm/store \
|
&& rm -rf /root/.local/share/pnpm/store \
|
||||||
&& rm -rf /root/.cache \
|
&& rm -rf /root/.cache \
|
||||||
&& rm -rf /root/.npm
|
&& rm -rf /root/.npm
|
||||||
|
|
||||||
ARG SOURCE_COMMIT
|
ARG SOURCE_COMMIT
|
||||||
RUN git clone --depth=1 -b ${QL_BRANCH} ${QL_URL} ${QL_DIR} \
|
RUN git clone --depth=1 -b ${QL_BRANCH} ${QL_URL} ${QL_DIR} \
|
||||||
&& cd ${QL_DIR} \
|
&& cd ${QL_DIR} \
|
||||||
&& cp -f .env.example .env \
|
&& cp -f .env.example .env \
|
||||||
&& chmod 777 ${QL_DIR}/shell/*.sh \
|
&& chmod 777 ${QL_DIR}/shell/*.sh \
|
||||||
&& chmod 777 ${QL_DIR}/docker/*.sh \
|
&& chmod 777 ${QL_DIR}/docker/*.sh \
|
||||||
&& git clone --depth=1 -b ${QL_BRANCH} https://github.com/${QL_MAINTAINER}/qinglong-static.git /static \
|
&& git clone --depth=1 -b ${QL_BRANCH} https://github.com/${QL_MAINTAINER}/qinglong-static.git /static \
|
||||||
&& mkdir -p ${QL_DIR}/static \
|
&& mkdir -p ${QL_DIR}/static \
|
||||||
&& cp -rf /static/* ${QL_DIR}/static \
|
&& cp -rf /static/* ${QL_DIR}/static \
|
||||||
&& rm -rf /static
|
&& rm -rf /static
|
||||||
|
|
||||||
COPY --from=builder /tmp/build/node_modules/. /ql/node_modules/
|
COPY --from=builder /tmp/build/node_modules/. /ql/node_modules/
|
||||||
|
|
||||||
WORKDIR ${QL_DIR}
|
WORKDIR ${QL_DIR}
|
||||||
|
|
||||||
|
HEALTHCHECK --interval=5s --timeout=2s --retries=10 \
|
||||||
|
CMD curl -sf http://127.0.0.1:5400/api/health || exit 1
|
||||||
|
|
||||||
ENTRYPOINT ["./docker/docker-entrypoint.sh"]
|
ENTRYPOINT ["./docker/docker-entrypoint.sh"]
|
||||||
|
|
|
@ -7,3 +7,8 @@ services:
|
||||||
ports:
|
ports:
|
||||||
- "0.0.0.0:5700:5700"
|
- "0.0.0.0:5700:5700"
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-sf", "http://127.0.0.1:5400/api/health", "||", "exit", "1"]
|
||||||
|
interval: 2m
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
|
|
@ -12,6 +12,7 @@ make_dir /run/nginx
|
||||||
init_nginx
|
init_nginx
|
||||||
|
|
||||||
pm2 l &>/dev/null
|
pm2 l &>/dev/null
|
||||||
|
pm2 flush &>/dev/null
|
||||||
|
|
||||||
echo -e "======================2. 安装依赖========================\n"
|
echo -e "======================2. 安装依赖========================\n"
|
||||||
patch_version
|
patch_version
|
||||||
|
|
|
@ -21,7 +21,7 @@ server {
|
||||||
proxy_set_header Host $http_host;
|
proxy_set_header Host $http_host;
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
proxy_pass http://publicApi/api/public/;
|
proxy_pass http://publicApi/api/;
|
||||||
}
|
}
|
||||||
|
|
||||||
location QL_BASE_URL/api/ {
|
location QL_BASE_URL/api/ {
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
"panel": "npm run build:back && node static/build/app.js",
|
"panel": "npm run build:back && node static/build/app.js",
|
||||||
"schedule": "npm run build:back && node static/build/schedule/index.js",
|
"schedule": "npm run build:back && node static/build/schedule/index.js",
|
||||||
"public": "npm run build:back && node static/build/public.js",
|
"public": "npm run build:back && node static/build/public.js",
|
||||||
"gen:proto": "protoc --experimental_allow_proto3_optional --plugin=./node_modules/.bin/protoc-gen-ts_proto ./back/protos/cron.proto --ts_proto_out=./ --ts_proto_opt=outputServices=grpc-js,env=node,esModuleInterop=true",
|
"gen:proto": "protoc --experimental_allow_proto3_optional --plugin=./node_modules/.bin/protoc-gen-ts_proto ./back/protos/*.proto --ts_proto_out=./ --ts_proto_opt=outputServices=grpc-js,env=node,esModuleInterop=true",
|
||||||
"prettier": "prettier --write '**/*.{js,jsx,tsx,ts,less,md,json}'",
|
"prettier": "prettier --write '**/*.{js,jsx,tsx,ts,less,md,json}'",
|
||||||
"postinstall": "max setup 2>/dev/null || true",
|
"postinstall": "max setup 2>/dev/null || true",
|
||||||
"test": "umi-test",
|
"test": "umi-test",
|
||||||
|
|
|
@ -33,8 +33,8 @@ pm2_log() {
|
||||||
echo -e "---> pm2日志"
|
echo -e "---> pm2日志"
|
||||||
local panelOut="/root/.pm2/logs/panel-out.log"
|
local panelOut="/root/.pm2/logs/panel-out.log"
|
||||||
local panelError="/root/.pm2/logs/panel-error.log"
|
local panelError="/root/.pm2/logs/panel-error.log"
|
||||||
tail -n 100 "$panelOut"
|
tail -n 300 "$panelOut"
|
||||||
tail -n 100 "$panelError"
|
tail -n 300 "$panelError"
|
||||||
}
|
}
|
||||||
|
|
||||||
check_nginx() {
|
check_nginx() {
|
||||||
|
|
|
@ -382,6 +382,7 @@ random_range() {
|
||||||
|
|
||||||
reload_pm2() {
|
reload_pm2() {
|
||||||
pm2 l &>/dev/null
|
pm2 l &>/dev/null
|
||||||
|
pm2 flush &>/dev/null
|
||||||
|
|
||||||
echo -e "启动面板服务\n"
|
echo -e "启动面板服务\n"
|
||||||
pm2 delete panel --source-map-support --time &>/dev/null
|
pm2 delete panel --source-map-support --time &>/dev/null
|
||||||
|
|
|
@ -9,4 +9,44 @@
|
||||||
height: calc(100vh - 80px);
|
height: calc(100vh - 80px);
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.code-box {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
width: 80%;
|
||||||
|
margin: 16px;
|
||||||
|
background-color: #ffffff;
|
||||||
|
border: 1px solid rgba(5, 5, 5, 0.06);
|
||||||
|
border-radius: 6px;
|
||||||
|
-webkit-transition: all 0.2s;
|
||||||
|
transition: all 0.2s;
|
||||||
|
border-radius: 6px 6px 0 0;
|
||||||
|
color: rgba(0, 0, 0, 0.88);
|
||||||
|
border-bottom: 1px solid rgba(5, 5, 5, 0.06);
|
||||||
|
|
||||||
|
.browser-markup {
|
||||||
|
position: relative;
|
||||||
|
border-top: 2em solid rgba(230, 230, 230, 0.7);
|
||||||
|
border-radius: 3px 3px 0 0;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
position: absolute;
|
||||||
|
top: -1.25em;
|
||||||
|
left: 1em;
|
||||||
|
display: block;
|
||||||
|
width: 0.5em;
|
||||||
|
height: 0.5em;
|
||||||
|
background-color: #f44;
|
||||||
|
border-radius: 50%;
|
||||||
|
box-shadow: 0 0 0 2px #f44, 1.5em 0 0 2px #9b3, 3em 0 0 2px #fb5;
|
||||||
|
content: '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.log {
|
||||||
|
height: calc(100vh - 150px);
|
||||||
|
overflow-y: auto;
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,43 +1,37 @@
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect, useRef } from 'react';
|
||||||
import config from '@/utils/config';
|
import config from '@/utils/config';
|
||||||
import { request } from '@/utils/http';
|
import { request } from '@/utils/http';
|
||||||
import Terminal, { ColorMode, LineType } from '../../components/terminal';
|
|
||||||
import { PageLoading } from '@ant-design/pro-layout';
|
import { PageLoading } from '@ant-design/pro-layout';
|
||||||
import { history, useOutletContext } from '@umijs/max';
|
import { history, useOutletContext } from '@umijs/max';
|
||||||
import Ansi from 'ansi-to-react';
|
|
||||||
import './index.less';
|
import './index.less';
|
||||||
import { SharedContext } from '@/layouts';
|
import { SharedContext } from '@/layouts';
|
||||||
|
import { Alert, Typography } from 'antd';
|
||||||
|
|
||||||
const Error = () => {
|
const Error = () => {
|
||||||
const { user, theme, reloadUser } = useOutletContext<SharedContext>();
|
const { user, theme, reloadUser } = useOutletContext<SharedContext>();
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [data, setData] = useState('暂无日志');
|
const [data, setData] = useState('暂无日志');
|
||||||
|
const retryTimes = useRef(1);
|
||||||
|
|
||||||
const getTimes = () => {
|
console.log(retryTimes.current);
|
||||||
return parseInt(localStorage.getItem('error_retry_times') || '0', 10);
|
|
||||||
};
|
|
||||||
|
|
||||||
let times = getTimes();
|
|
||||||
|
|
||||||
const getLog = (needLoading: boolean = true) => {
|
const getLog = (needLoading: boolean = true) => {
|
||||||
needLoading && setLoading(true);
|
needLoading && setLoading(true);
|
||||||
request
|
request
|
||||||
.get(`${config.apiPrefix}public/panel/log`)
|
.get(`${config.apiPrefix}public/health`)
|
||||||
.then(({ code, data }) => {
|
.then(({ status, error }) => {
|
||||||
if (code === 200) {
|
if (status === 1) {
|
||||||
setData(data);
|
return reloadUser();
|
||||||
if (!data) {
|
|
||||||
times = getTimes();
|
|
||||||
if (times > 5) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
localStorage.setItem('error_retry_times', `${times + 1}`);
|
|
||||||
setTimeout(() => {
|
|
||||||
reloadUser();
|
|
||||||
getLog(false);
|
|
||||||
}, 3000);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (retryTimes.current > 3) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setData(error.details);
|
||||||
|
retryTimes.current += 1;
|
||||||
|
setTimeout(() => {
|
||||||
|
reloadUser();
|
||||||
|
getLog(false);
|
||||||
|
}, 3000);
|
||||||
})
|
})
|
||||||
.finally(() => needLoading && setLoading(false));
|
.finally(() => needLoading && setLoading(false));
|
||||||
};
|
};
|
||||||
|
@ -56,24 +50,16 @@ const Error = () => {
|
||||||
<div className="error-wrapper">
|
<div className="error-wrapper">
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<PageLoading />
|
<PageLoading />
|
||||||
) : data ? (
|
) : retryTimes.current < 3 ? (
|
||||||
<Terminal
|
<div className="code-box">
|
||||||
name="服务错误"
|
<div className="browser-markup"></div>
|
||||||
colorMode={theme === 'vs-dark' ? ColorMode.Dark : ColorMode.Light}
|
<Alert
|
||||||
lineData={[
|
type="error"
|
||||||
{ type: LineType.Input, value: 'pm2 logs panel' },
|
message="服务启动超时,请检查如下日志或者进入容器执行 ql -l check 后刷新再试"
|
||||||
{
|
banner
|
||||||
type: LineType.Output,
|
/>
|
||||||
value: (
|
<Typography.Paragraph className="log">{data}</Typography.Paragraph>
|
||||||
<pre>
|
</div>
|
||||||
<Ansi>{data}</Ansi>
|
|
||||||
</pre>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
) : times > 5 ? (
|
|
||||||
<>服务启动超时,请手动进入容器执行 ql -l check 后刷新再试</>
|
|
||||||
) : (
|
) : (
|
||||||
<PageLoading tip="启动中,请稍后..." />
|
<PageLoading tip="启动中,请稍后..." />
|
||||||
)}
|
)}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user