chancancode / ember-concurrency-async

Async task functions for ember-concurrency
http://ember-concurrency.com/docs/typescript
MIT License
53 stars 6 forks source link

mono-repos: Async tasks not compiling back to generator functions with ember-concurrency 2.1.0 #15

Closed robertpbaxter closed 3 years ago

robertpbaxter commented 3 years ago

I wish there had been a followup for this issue: https://github.com/chancancode/ember-concurrency-async/issues/12

My company's monorepo has both an app and addon implementation. Neither compile back to generator functions. The functions would fire and the code works, but the console always throws a Uncaught TypeError: iterator[iteratorMethod] is not a function

maxfierke commented 3 years ago

@robertpbaxter this happens with some setups, the reasons are usually as follows:

  1. some dependency is still using ember-concurrency 1.x and pulling that into the build instead of 2.x
  2. ember-concurrency-async has not been declared as a dependency in an in-repo-addon or engine's package.json
robertpbaxter commented 3 years ago

I just resolved dependency clobbering across all 11 packages in our mono-repo, and the only EC version in our yarn.lock is 2.1.0. I do have ECA in our core package.json's dependencies (the rest are in devDependencies). I also made sure there was an index.d.ts that imported both EC-async and EC-ts/async as well.

maxfierke commented 3 years ago

@robertpbaxter I believe it may need to be dependencies for those other packages, as it's a babel plugin and is used at build time

robertpbaxter commented 3 years ago

Tried that just now. I still get errors saying the context is undefined, e.g. this.args.thing is undefined, which is the first line inside the arrow function

maxfierke commented 3 years ago

can you provide some sample code or an example repo that reproduces the issue, and some stack traces for the errors you're seeing?

robertpbaxter commented 3 years ago

I'll see if I can set some time aside to reproduce this weekend. Thanks for your help so far.

robertpbaxter commented 3 years ago

Here's an actual function I tried to debug with a little help from @NullVoxPopuli:

  @dropTask
  deleteRecordTask = taskFor(async function (this: DeleteConfirmation) {
    try {
      await this.args.record.destroyRecord();

      this.prompt.notify(success);

      const elasticRecord = this.store.peekRecord(model, this.args.record.id);
      if (elasticRecord) {
        elasticRecord.unloadRecord();
        this.router.transitionTo(route);
      } else {
        this.router.transitionTo(route, { queryParams: { records: { refreshModel: true } } });
      }
    } catch (error) {
      this.prompt.flashError(error);
    } finally {
      this.args.toggleModal();
    }
  });

I would attempt to delete my record, and I would get this error. This is the exact same message I got from a delete action, starting a download, and generating a report. error

He asked me what the source code looked like, and this is what we found. It's definitely not being converted back into a generator function again. If I were to implement the task above using an arrow function, it would throw an error on render from the component context not being defined (e.g. this.args.record is undefined)

let DeleteConfirmation = (_dec = Ember.inject.service, _dec2 = Ember.inject.service, _dec3 = Ember.inject.service, _dec4 = Ember.inject.service, (_class = class DeleteConfirmation extends _component.default {
    constructor(...args) {
      super(...args);

      _defineProperty(this, "layout", _template.default);

      _initializerDefineProperty(this, "intl", _descriptor, this);

      _initializerDefineProperty(this, "prompt", _descriptor2, this);

      _initializerDefineProperty(this, "router", _descriptor3, this);

      _initializerDefineProperty(this, "store", _descriptor4, this);

      _initializerDefineProperty(this, "deleteRecordTask", _descriptor5, this);
    }

  }, (_descriptor = _applyDecoratedDescriptor(_class.prototype, "intl", [_dec], {
    configurable: true,
    enumerable: true,
    writable: true,
    initializer: null
  }), _descriptor2 = _applyDecoratedDescriptor(_class.prototype, "prompt", [_dec2], {
    configurable: true,
    enumerable: true,
    writable: true,
    initializer: null
  }), _descriptor3 = _applyDecoratedDescriptor(_class.prototype, "router", [_dec3], {
    configurable: true,
    enumerable: true,
    writable: true,
    initializer: null
  }), _descriptor4 = _applyDecoratedDescriptor(_class.prototype, "store", [_dec4], {
    configurable: true,
    enumerable: true,
    writable: true,
    initializer: null
  }), _descriptor5 = _applyDecoratedDescriptor(_class.prototype, "deleteRecordTask", [_emberConcurrency.dropTask], {
    configurable: true,
    enumerable: true,
    writable: true,
    initializer: function () {
      return (0, _emberConcurrencyTs.taskFor)(async function () {
        try {
          await this.args.record.destroyRecord();
          this.prompt.notify(success);
          const elasticRecord = this.store.peekRecord(model, this.args.record.id);
          if (elasticRecord) {
            elasticRecord.unloadRecord();
            this.router.transitionTo(route);
          } else {
            this.router.transitionTo(route, {
              queryParams: {
                records: {
                  refreshModel: true
                }
              }
            });
          }
        } catch (error) {
          this.prompt.flashError(error);
        } finally {
          this.args.toggleModal();
        }
      });
    }
  })), _class));
  _exports.default = DeleteConfirmation;
});
maxfierke commented 3 years ago

Yeah that definitely looks like a case that is covered by ember-concurrency-async and should be handled properly.

My guess is the babel plugin just isn't running over it for some reason. Please ensure you're on the latest ember-concurrency-async and ember-concurrency-ts and have those all listed under dependency in any package that uses either. I don't use monorepos personally, so I can't provide much on setup other than that general advice. If you hop into the Ember Community Discord's #e-concurrency channel, someone else may be able to assist further.

One thread worth scrolling through is @fabmiz's earlier debugging on the same/similar issue: https://discord.com/channels/480462759797063690/484421754702397441/824302758550962186

robertpbaxter commented 3 years ago

@maxfierke So after a second pass following that similar thread, I managed to resolve the issue. Only some of our many addon apps actually have EC installed in their package.json, but the host application was not one of them. It worked fine previously because they all shared one collective node_modules directory. Tasks started compiling back again once I added the three EC to the host dependencies. Thanks for the help.

lolmaus commented 2 years ago

I'm running into exactly the same issue, also in a monorepo driven by Yarn v1 Workspaces.

I have this in the resolutions of the root package.json:

  "resolutions": {
    "**/@embroider/macros": "^0.41.0",
    "**/ember-concurrency": "2.2.0",
    "**/ember-concurrency-async": "1.0.0",
    "**/ember-concurrency-ts": "0.3.1",

This results in the following yarn.lock entries:

ember-concurrency-async@1.0.0, ember-concurrency-async@^0.3.2, ember-concurrency-async@^1.0.0:
  version "1.0.0"
  resolved "https://registry.yarnpkg.com/ember-concurrency-async/-/ember-concurrency-async-1.0.0.tgz#635ec2b7b11c083699801b85c5bb757bb7ebfd45"
  integrity sha512-otE1UcF+VYva8qdkYayHVBrGDG+Lt9oYLLMt3heEo98Mv9abdjrdaLzvSMMspzI3ncgKtmZsEwn+aubvq+Zhhw==
  dependencies:
    "@babel/helper-plugin-utils" "^7.10.1"
    "@babel/types" "^7.10.2"
    ember-cli-babel "^7.19.0"
    ember-cli-babel-plugin-helpers "^1.1.1"
    ember-cli-htmlbars "^4.3.1"

ember-concurrency-decorators@^2.0.0, ember-concurrency-decorators@^2.0.3:
  version "2.0.3"
  resolved "https://registry.yarnpkg.com/ember-concurrency-decorators/-/ember-concurrency-decorators-2.0.3.tgz#2816c9a0283b90ba5340fc5b4e0b92ea91f7d6e3"
  integrity sha512-r6O34YKI/slyYapVsuOPnmaKC4AsmBSwvgcadbdy+jHNj+mnryXPkm+3hhhRnFdlsKUKdEuXvl43lhjhYRLhhA==
  dependencies:
    "@ember-decorators/utils" "^6.1.0"
    ember-cli-babel "^7.19.0"
    ember-cli-htmlbars "^4.3.1"
    ember-cli-typescript "^3.1.4"

ember-concurrency-ts@0.3.1, ember-concurrency-ts@^0.2.0, ember-concurrency-ts@^0.2.2, ember-concurrency-ts@^0.3.1:
  version "0.3.1"
  resolved "https://registry.yarnpkg.com/ember-concurrency-ts/-/ember-concurrency-ts-0.3.1.tgz#0b3b524a6a96c8ab749b20e1d4da00569773567a"
  integrity sha512-lE9uqPgK1Y9PN/0BJ5zE2a+h95izRCn6FCyt7qVV3012TlblTynsBaoUuAbN1T3KfzFsrJaXwsxzRbDjEde2Sw==
  dependencies:
    ember-cli-babel "^7.19.0"
    ember-cli-htmlbars "^4.3.1"

ember-concurrency@2.2.0, "ember-concurrency@>=1.0.0 <3", "ember-concurrency@>=1.3.0 <3", ember-concurrency@^1.3.0, ember-concurrency@^2.0.3, ember-concurrency@^2.2.0:
  version "2.2.0"
  resolved "https://registry.yarnpkg.com/ember-concurrency/-/ember-concurrency-2.2.0.tgz#0acfb8ca855e0fdfa4c543be150028299a89ba32"
  integrity sha512-Ns1MH6t08oJqfeWQ4EMxyf6bLsXM87SbUPwGNUsg7idpikvkGr1PWqtvU6qxDTv1mA4Vrwdhv0I9yxN0ShH9Bg==
  dependencies:
    "@glimmer/tracking" "^1.0.4"
    ember-cli-babel "^7.26.6"
    ember-cli-htmlbars "^5.7.1"
    ember-compatibility-helpers "^1.2.0"

I have performed a file content search like this grep --include="package.json" -rnw . -e "ember-concurrency-async" and I can confirm that there is only only copy of ember-concurrency-async in node_modules/: it is on the root level and version is 1.0.0.

This started to happen during an attempt to upgrade Ember CLI from 3.20 to 3.28.

Please reopen.

CC @simonihmig

lolmaus commented 2 years ago

The issue happens in a component of an addon which is part of the monorepo. The addon does have EC dependencies defined in "dependencies":

  "dependencies": {
    "ember-concurrency": "^2.2.0",
    "ember-concurrency-async": "^1.0.0",
    "ember-concurrency-ts": "^0.3.1",
lolmaus commented 2 years ago

Ughm, I've converted all async/await tasks to generator/yield in the addon, and I still see the same issue.

Also, the issue happens in app modules too, even after all of them have been converted to yield.

So this seems not to be related to this addon.