Skip to content
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

Dependencies inside Resources in forked modules #45

Open
Windsdon opened this issue Jan 18, 2020 · 1 comment
Open

Dependencies inside Resources in forked modules #45

Windsdon opened this issue Jan 18, 2020 · 1 comment

Comments

@Windsdon
Copy link

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?

@pct-cclausen
Copy link

pct-cclausen commented Nov 19, 2020

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]
    });

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants