🚨🩹 ooconnector: pass linter, fix bug where ignored promises in poller caused crash (#525)

This commit is contained in:
Eric Doughty-Papassideris
2024-08-25 22:26:28 +02:00
parent ca3ebcc83d
commit 3c156c4421
4 changed files with 29 additions and 19 deletions
@@ -85,9 +85,9 @@ class OnlyOfficeController {
switch (req.body.status) { switch (req.body.status) {
case OnlyOffice.Callback.Status.BEING_EDITED: case OnlyOffice.Callback.Status.BEING_EDITED:
// TODO this call back we recieve almost all the time, and here we save // TODO this call back we recieve almost all the time, and here we save
// the user identifiers who start file editing and even control the amount of onlin users // the user identifiers who start file editing and even control the amount of onlin users
// to have license constraint warning before OnlyOffice error about this // to have license constraint warning before OnlyOffice error about this
case OnlyOffice.Callback.Status.BEING_EDITED_BUT_IS_SAVED: case OnlyOffice.Callback.Status.BEING_EDITED_BUT_IS_SAVED:
// No-op // No-op
break; break;
@@ -19,8 +19,8 @@ export class PolledThingieValue<ValueType> {
private readonly getTheThingieValue: () => Promise<NotUndefined<ValueType>>, private readonly getTheThingieValue: () => Promise<NotUndefined<ValueType>>,
private readonly intervalMs: number, private readonly intervalMs: number,
) { ) {
this.run(); this.runIgnoringRejection();
setInterval(() => this.run(), this.intervalMs); setInterval(() => this.runIgnoringRejection(), this.intervalMs);
} }
protected setResult(value: undefined, error?: NotUndefined<ValueType>, ts?: number); protected setResult(value: undefined, error?: NotUndefined<ValueType>, ts?: number);
@@ -52,6 +52,12 @@ export class PolledThingieValue<ValueType> {
})); }));
} }
private runIgnoringRejection() {
return this.run().catch(() => {
/* active ignoring going on here */
});
}
public lastFailed() { public lastFailed() {
return !!this.lastKoTimeMs; return !!this.lastKoTimeMs;
} }
@@ -50,13 +50,12 @@ class DriveService implements IDriveService {
}; };
public beginEditing(drive_file_id: string): string { public beginEditing(drive_file_id: string): string {
return ""; return '';
} }
public endEditing(editing_session_id: string) { public endEditing(editing_session_id: string) {
return ""; return '';
} }
} }
export default new DriveService(); export default new DriveService();
@@ -25,6 +25,11 @@ export namespace Callback {
USER_INITIATED_FORCE_SAVE = 2, USER_INITIATED_FORCE_SAVE = 2,
} }
interface Action {
type: ActionType;
userid: string;
}
enum ForceSaveType { enum ForceSaveType {
FROM_COMMAND_SERVICE = 0, FROM_COMMAND_SERVICE = 0,
FORCE_SAVE_BUTTON_CLICKED = 1, FORCE_SAVE_BUTTON_CLICKED = 1,
@@ -45,10 +50,6 @@ export namespace Callback {
ERROR_FORCE_SAVING = 7, ERROR_FORCE_SAVING = 7,
} }
interface Action {
type: ActionType;
userid: string;
}
/** Parameters given to the callback by the editing service */ /** Parameters given to the callback by the editing service */
export interface Parameters { export interface Parameters {
key: string; key: string;
@@ -86,18 +87,18 @@ namespace CommandService {
} }
} }
abstract class BaseRequest<TSuccessResponse extends BaseResponse> { abstract class BaseRequest<TSuccessResponse extends SuccessResponse> {
constructor(public c: string) {} constructor(public readonly c: string) {}
/** POST this OnlyOffice command, does not check the `error` field of the response */ /** POST this OnlyOffice command, does not check the `error` field of the response */
async postUnsafe(): Promise<ErrorResponse | TSuccessResponse> { async postUnsafe(): Promise<ErrorResponse | TSuccessResponse> {
logger.silly(`OnlyOffice command ${this.c} sent: ${JSON.stringify(this)}`); logger.silly(`OnlyOffice command ${this.c} sent: ${JSON.stringify(this)}`);
const result = await axios.post(`${ONLY_OFFICE_SERVER}coauthoring/CommandService.ashx`, this); const result = await axios.post(Utils.joinURL([ONLY_OFFICE_SERVER, 'coauthoring/CommandService.ashx']), this);
logger.info(`OnlyOffice command ${this.c} response: ${result.status}: ${JSON.stringify(result.data)}`); logger.info(`OnlyOffice command ${this.c} response: ${result.status}: ${JSON.stringify(result.data)}`);
return result.data as ErrorResponse | TSuccessResponse; return result.data as ErrorResponse | TSuccessResponse;
} }
/** POST this request, and return the result, or throw if the `errorCode` returned isn't 0 */ /** POST this request, and return the result, or throws if the `errorCode` returned isn't `ErrorCode.SUCCESS` */
async post(): Promise<TSuccessResponse> { async post(): Promise<TSuccessResponse> {
const result = await this.postUnsafe(); const result = await this.postUnsafe();
if (result.error === ErrorCode.SUCCESS) return result; if (result.error === ErrorCode.SUCCESS) return result;
@@ -121,7 +122,7 @@ namespace CommandService {
key: string; key: string;
} }
export class Request extends BaseRequest<Response> { export class Request extends BaseRequest<Response> {
constructor(public key: string, public userdata: string = '') { constructor(public readonly key: string, public readonly userdata: string = '') {
super('forcesave'); super('forcesave');
} }
} }
@@ -133,7 +134,7 @@ namespace CommandService {
url: string; url: string;
} }
export class Request extends BaseRequest<Response> { export class Request extends BaseRequest<Response> {
constructor(public key: string) { constructor(public readonly key: string) {
super('getForgotten'); super('getForgotten');
} }
} }
@@ -155,7 +156,7 @@ namespace CommandService {
key: string; key: string;
} }
export class Request extends BaseRequest<Response> { export class Request extends BaseRequest<Response> {
constructor(public key: string) { constructor(public readonly key: string) {
super('deleteForgotten'); super('deleteForgotten');
} }
} }
@@ -178,6 +179,10 @@ class OnlyOfficeService {
public getLatestVersion() { public getLatestVersion() {
return this.poller.latest(); return this.poller.latest();
} }
// Note that `async` is important in the functions below. While they avoid the overhead
// of `await`, the `async` is still required to catch the throw in `.post()`
/** Return the version string of OnlyOffice */ /** Return the version string of OnlyOffice */
async getVersion(): Promise<string> { async getVersion(): Promise<string> {
return new CommandService.Version.Request().post().then(response => response.version); return new CommandService.Version.Request().post().then(response => response.version);