comedy icon indicating copy to clipboard operation
comedy copied to clipboard

Dependencies inside Resources in forked modules

Open Windsdon opened this issue 6 years ago • 1 comments

Hello!

I'm starting a new project with TypeScript and currently experimenting with Comedy as a solution for scaling the application.

I ran into an issue with the way Resources are serialized and sent to the forked process which is causing a lot of headaches and seems like a big limitation (if I'm understanding this correctly).

The original Resource definition is as follows:

import { ActorSystem, ResourceDefinition } from 'comedy';
import { getResource } from '../helpers/test';
import { ComedyResource } from '../decorators/ComedyResource';

@ComedyResource('TestResource')
export default class TestResource implements ResourceDefinition<string> {
	destroy(): Promise<void> | void {
		// nothing to do here
		return undefined;
	}

	getResource(): string {
		// return from an imported function as a test
		return getResource();
	}

	initialize(system: ActorSystem): Promise<void> | void {
		// nothing to do here
		return undefined;
	}
}

But what is sent to the child process (in the create-actor message) is:

class TestResource {
    destroy() {
        // nothing to do here
        return undefined;
    }
    getResource() {
        // return from an imported function as a test
        return test_1.getResource();
    }
    initialize(system) {
        // nothing to do here
        return undefined;
    }
}; TestResource;

As you can see, the imports are all missing and there is no way this can work.

@Zephyrrus noticed that you can use require() inside the definition and to import things, but they are imported from the wrong working directory and therefore don't resolve properly.

As a workaround I considered creating dummy "shells" that would dynamically load the correct file (from disk) with require(), but that sounds very cumbersome to maintain.

Is there any solution to this? Am I missing something?

Windsdon avatar Jan 18 '20 20:01 Windsdon

I think you need to define the resource via a path instead of passing the object itself. For my resources and actors I create them in a file like this:

import { ResourceDefinition, ActorSystem } from "comedy";
import Knex from "knex";
import fs from "fs";

export class KnexResource implements ResourceDefinition<Knex> {
// this resource is in a package called @pct-digital/knex-db-resource
    static RESOURCE_PATH =  "@pct-digital/knex-db-resource/dist/KnexDbResourceModule";

    log: any;
    knex: Knex = null as any;

    async initialize(system: ActorSystem) {
        this.log = system.getLog();
        this.log.info("init KnexResource");

        let knexConfig = (system as any).options.config.knex;

        if (knexConfig == null) {
            this.log.error("Cannot initialize KnexResource, the global configuration must contain a knex property!");
        }

        this.log.info("Initializing knex.js pool");
        this.knex = Knex(knexConfig);
        let result = await this.knex.raw("SELECT 1");
        if (result.rowCount !== 1 || result.rows.length !== 1) {
            this.log.error("knex pool test failed!");
        } else {
            this.log.info("knex pool setup completed!");
        }
    }

    destroy() {
        this.log.info("Destroying knex.js pool");
        return this.knex.destroy();
    }
  
    getName() {
        return "KnexResource";
    }

    getResource() {
        return this.knex;
    }

}

Then I add an extra file from this this actually will be loaded by comedy:

import { KnexResource } from "./KnexDbResource";
module.exports = KnexResource;

I've not found a way to use the file that contains the normal "export class KnexResource" directly, the path I use to define the resource has to point to the file that does module.exports = ...

My system is initialized like this:

    const system = actors.createSystem({
        config: {
            knex: serverCfg.knex,
        },
        resources: [KnexResource.RESOURCE_PATH]
    });

pct-cclausen avatar Nov 19 '20 13:11 pct-cclausen