Add more logs through main services

This commit is contained in:
Hakan Shehu
2024-11-22 18:26:58 +01:00
parent 2b356513f5
commit 844165664a
7 changed files with 101 additions and 10 deletions

View File

@@ -7,10 +7,12 @@ import { accountService } from '@/main/services/account-service';
import { syncService } from '@/main/services/sync-service';
import { notificationService } from '@/main/services/notification-service';
import { fileService } from '@/main/services/file-service';
import { logService } from '@/main/services/log-service';
const EVENT_LOOP_INTERVAL = 1000 * 60;
class Bootstrapper {
private readonly logger = logService.createLogger('bootstrapper');
private initPromise: Promise<void> | null = null;
private eventLoop: NodeJS.Timeout | null = null;
@@ -27,6 +29,8 @@ class Bootstrapper {
}
private async executeInit() {
this.logger.info('Initializing');
await databaseService.init();
await assetService.checkAssets();
await serverService.syncServers();
@@ -40,6 +44,8 @@ class Bootstrapper {
}
private async executeEventLoop() {
this.logger.info('Executing event loop');
try {
await serverService.syncServers();
await accountService.syncAccounts();
@@ -50,7 +56,7 @@ class Bootstrapper {
notificationService.checkBadge();
} catch (error) {
console.log('error', error);
this.logger.error('Error executing event loop', error);
}
this.eventLoop = setTimeout(this.executeEventLoop, EVENT_LOOP_INTERVAL);

View File

@@ -4,6 +4,7 @@ import fs from 'fs';
import unzipper from 'unzipper';
import { EmojiData } from '@/shared/types/emojis';
import { IconData } from '@/shared/types/icons';
import { logService } from './log-service';
type AssetsVersion = {
date: string;
@@ -15,11 +16,11 @@ const EMOJIS_VERSION = '1.0.0';
const ICONS_VERSION = '1.0.0';
class AssetService {
private readonly assetsDir: string;
constructor() {
this.assetsDir = path.join(app.getPath('userData'), 'assets');
}
private readonly assetsDir: string = path.join(
app.getPath('userData'),
'assets'
);
private readonly logger = logService.createLogger('asset-service');
public async handleAssetRequest(request: Request): Promise<Response> {
const url = request.url.replace('asset://', '');
@@ -50,6 +51,7 @@ class AssetService {
public async checkAssets(): Promise<void> {
if (!this.shouldUpdateAssets()) {
this.logger.debug('Assets are up to date');
return;
}
@@ -57,6 +59,8 @@ class AssetService {
}
private async updateAssets(): Promise<void> {
this.logger.debug('Updating assets');
await this.updateEmojis();
await this.updateIcons();
@@ -64,6 +68,8 @@ class AssetService {
}
private async updateEmojis(): Promise<void> {
this.logger.debug('Updating emojis');
const emojisZipPath = path.join(this.getAssetsSourcePath(), 'emojis.zip');
const emojisDir = path.join(this.assetsDir, 'emojis');
if (fs.existsSync(emojisDir)) {
@@ -78,6 +84,8 @@ class AssetService {
}
private async updateIcons(): Promise<void> {
this.logger.debug('Updating icons');
const iconsZipPath = path.join(this.getAssetsSourcePath(), 'icons.zip');
const iconsDir = path.join(this.assetsDir, 'icons');
if (fs.existsSync(iconsDir)) {
@@ -94,6 +102,7 @@ class AssetService {
private shouldUpdateAssets(): boolean {
const assetsVersion = this.readAssetsVersion();
if (!assetsVersion) {
this.logger.debug('No assets version found, updating assets');
return true;
}
@@ -106,6 +115,7 @@ class AssetService {
private readAssetsVersion(): AssetsVersion | null {
const assetsVersionPath = path.join(this.assetsDir, 'version.json');
if (!fs.existsSync(assetsVersionPath)) {
this.logger.debug('No assets version found');
return null;
}

View File

@@ -4,12 +4,16 @@ import fs from 'fs';
import { databaseService } from '@/main/data/database-service';
import { httpClient } from '@/shared/lib/http-client';
import { getAccountAvatarsDirectoryPath } from '@/main/utils';
import { logService } from '@/main/services/log-service';
class AvatarService {
private readonly logger = logService.createLogger('avatar-service');
public async handleAvatarRequest(request: Request): Promise<Response> {
const url = request.url.replace('avatar://', '');
const [accountId, avatarId] = url.split('/');
if (!accountId || !avatarId) {
this.logger.warn(`Invalid avatar request url: ${url}`);
return new Response(null, { status: 400 });
}
@@ -22,6 +26,9 @@ class AvatarService {
return net.fetch(avatarLocalUrl);
}
this.logger.debug(
`Downloading avatar ${avatarId} for account ${accountId}`
);
// Download the avatar file if it doesn't exist
const credentials = await databaseService.appDatabase
.selectFrom('accounts')
@@ -31,6 +38,7 @@ class AvatarService {
.executeTakeFirst();
if (!credentials) {
this.logger.warn(`Account ${accountId} not found`);
return new Response(null, { status: 404 });
}
@@ -41,6 +49,9 @@ class AvatarService {
});
if (response.status !== 200 || !response.data) {
this.logger.warn(
`Failed to download avatar ${avatarId} for account ${accountId}`
);
return new Response(null, { status: 404 });
}
@@ -55,10 +66,16 @@ class AvatarService {
fileStream.on('finish', async () => {
// Ensure the file is written before trying to fetch it
this.logger.debug(
`Avatar ${avatarId} for account ${accountId} downloaded`
);
resolve(net.fetch(avatarLocalUrl));
});
fileStream.on('error', (err) => {
this.logger.warn(
`Failed to download avatar ${avatarId} for account ${accountId}`
);
reject(new Response(null, { status: 500, statusText: err.message }));
});
});

View File

@@ -1,18 +1,23 @@
import { CommandInput } from '@/shared/commands';
import { logService } from '@/main/services/log-service';
import { CommandMap } from '@/shared/commands';
import { commandHandlerMap } from '@/main/commands';
import { CommandHandler } from '@/main/types';
class CommandService {
private readonly logger = logService.createLogger('command-service');
public async executeCommand<T extends CommandInput>(
input: T
): Promise<CommandMap[T['type']]['output']> {
this.logger.debug(`Executing command: ${input.type}`);
const handler = commandHandlerMap[
input.type
] as unknown as CommandHandler<T>;
if (!handler) {
this.logger.warn(`No handler found for command type: ${input.type}`);
throw new Error(`No handler found for command type: ${input.type}`);
}

View File

@@ -16,6 +16,7 @@ import {
} from '@colanode/core';
import { eventBus } from '@/shared/lib/event-bus';
import { serverService } from '@/main/services/server-service';
import { logService } from '@/main/services/log-service';
type WorkspaceFileState = {
isUploading: boolean;
@@ -25,7 +26,8 @@ type WorkspaceFileState = {
};
class FileService {
private fileStates: Map<string, WorkspaceFileState> = new Map();
private readonly logger = logService.createLogger('file-service');
private readonly fileStates: Map<string, WorkspaceFileState> = new Map();
constructor() {
eventBus.subscribe((event) => {
@@ -41,6 +43,7 @@ class FileService {
const url = request.url.replace('local-file://', '');
const [userId, file] = url.split('/');
if (!userId || !file) {
this.logger.warn(`Invalid file request url: ${url}`);
return new Response(null, { status: 400 });
}
@@ -52,6 +55,7 @@ class FileService {
return net.fetch(fileUrl);
}
this.logger.warn(`File ${file} not found for user ${userId}`);
return new Response(null, { status: 404 });
}
@@ -77,18 +81,26 @@ class FileService {
filesDir,
`${fileId}_${uploadId}${fileExtension}`
);
this.logger.debug(
`Copying file ${filePath} to ${destinationFilePath} for user ${userId}`
);
fs.copyFileSync(filePath, destinationFilePath);
}
public openFile(userId: string, id: string, extension: string): void {
const filesDir = getWorkspaceFilesDirectoryPath(userId);
const filePath = path.join(filesDir, `${id}${extension}`);
this.logger.debug(`Opening file ${filePath} for user ${userId}`);
shell.openPath(filePath);
}
public deleteFile(userId: string, id: string, extension: string): void {
const filesDir = getWorkspaceFilesDirectoryPath(userId);
const filePath = path.join(filesDir, `${id}${extension}`);
this.logger.debug(`Deleting file ${filePath} for user ${userId}`);
fs.rmSync(filePath, { force: true });
}
@@ -105,6 +117,8 @@ class FileService {
const stats = fs.statSync(filePath);
const type = extractFileType(mimeType);
this.logger.debug(`Getting file metadata for ${filePath}`);
return {
path: filePath,
mimeType,
@@ -116,6 +130,8 @@ class FileService {
}
public async syncFiles() {
this.logger.info('Syncing files');
const workspaces = await databaseService.appDatabase
.selectFrom('workspaces')
.select(['user_id'])
@@ -139,6 +155,9 @@ class FileService {
const fileState = this.fileStates.get(userId)!;
if (fileState.isUploading) {
fileState.isUploadScheduled = true;
this.logger.debug(
`Uploading files for user ${userId} is in progress, scheduling upload`
);
return;
}
@@ -146,7 +165,7 @@ class FileService {
try {
await this.uploadWorkspaceFiles(userId);
} catch (error) {
console.log('error', error);
this.logger.error(`Error uploading files for user ${userId}`, error);
} finally {
fileState.isUploading = false;
if (fileState.isUploadScheduled) {
@@ -169,6 +188,9 @@ class FileService {
const fileState = this.fileStates.get(userId)!;
if (fileState.isDownloading) {
fileState.isDownloadScheduled = true;
this.logger.debug(
`Downloading files for user ${userId} is in progress, scheduling download`
);
return;
}
@@ -176,7 +198,7 @@ class FileService {
try {
await this.downloadWorkspaceFiles(userId);
} catch (error) {
console.log('error', error);
this.logger.error(`Error downloading files for user ${userId}`, error);
} finally {
fileState.isDownloading = false;
if (fileState.isDownloadScheduled) {
@@ -187,6 +209,8 @@ class FileService {
}
private async uploadWorkspaceFiles(userId: string): Promise<void> {
this.logger.debug(`Uploading files for user ${userId}`);
if (!this.fileStates.has(userId)) {
this.fileStates.set(userId, {
isUploading: false,
@@ -199,6 +223,9 @@ class FileService {
const fileState = this.fileStates.get(userId)!;
if (fileState.isUploading) {
fileState.isUploadScheduled = true;
this.logger.debug(
`Uploading files for user ${userId} is in progress, scheduling upload`
);
return;
}
@@ -233,6 +260,7 @@ class FileService {
.executeTakeFirst();
if (!workspace) {
this.logger.warn(`Workspace not found for user ${userId}`);
return;
}
@@ -354,6 +382,7 @@ class FileService {
.executeTakeFirst();
if (!workspace) {
this.logger.warn(`Workspace not found for user ${userId}`);
return;
}

View File

@@ -3,8 +3,11 @@ import { MutationInput } from '@/shared/mutations';
import { MutationMap } from '@/shared/mutations';
import { mutationHandlerMap } from '@/main/mutations';
import { MutationHandler } from '@/main/types';
import { logService } from '@/main/services/log-service';
class MutationService {
private readonly logger = logService.createLogger('mutation-service');
public async executeMutation<T extends MutationInput>(
input: T
): Promise<MutationMap[T['type']]['output']> {
@@ -12,7 +15,10 @@ class MutationService {
input.type
] as unknown as MutationHandler<T>;
this.logger.debug(`Executing mutation: ${input.type}`);
if (!handler) {
this.logger.warn(`No handler found for mutation type: ${input.type}`);
throw new Error(`No handler found for mutation type: ${input.type}`);
}

View File

@@ -4,8 +4,10 @@ import { queryHandlerMap } from '@/main/queries';
import { eventBus } from '@/shared/lib/event-bus';
import { Event } from '@/shared/types/events';
import { isEqual } from 'lodash-es';
import { logService } from '@/main/services/log-service';
class QueryService {
private readonly logger = logService.createLogger('query-service');
private readonly subscribedQueries: Map<string, SubscribedQuery<QueryInput>> =
new Map();
@@ -26,7 +28,15 @@ class QueryService {
public async executeQuery<T extends QueryInput>(
input: T
): Promise<QueryMap[T['type']]['output']> {
this.logger.debug(`Executing query: ${input.type}`);
const handler = queryHandlerMap[input.type] as unknown as QueryHandler<T>;
if (!handler) {
this.logger.warn(`No handler found for query type: ${input.type}`);
throw new Error(`No handler found for query type: ${input.type}`);
}
const result = await handler.handleQuery(input);
return result;
}
@@ -35,11 +45,18 @@ class QueryService {
id: string,
input: T
): Promise<QueryMap[T['type']]['output']> {
this.logger.debug(`Executing query and subscribing: ${input.type}`);
if (this.subscribedQueries.has(id)) {
return this.subscribedQueries.get(id)!.result;
}
const handler = queryHandlerMap[input.type] as unknown as QueryHandler<T>;
if (!handler) {
this.logger.warn(`No handler found for query type: ${input.type}`);
throw new Error(`No handler found for query type: ${input.type}`);
}
const result = await handler.handleQuery(input);
this.subscribedQueries.set(id, {
input,
@@ -49,6 +66,7 @@ class QueryService {
}
public unsubscribeQuery(id: string) {
this.logger.debug(`Unsubscribing query: ${id}`);
this.subscribedQueries.delete(id);
}