aws-amplify / amplify-category-api

The AWS Amplify CLI is a toolchain for simplifying serverless web and mobile development. This plugin provides functionality for the API category, allowing for the creation and management of GraphQL and REST based backends for your amplify project.
https://docs.amplify.aws/
Apache License 2.0
89 stars 77 forks source link

GraphQL subscription failed when filter by field in a @searchable model in a mocked enviroment #2086

Open Phok7 opened 11 months ago

Phok7 commented 11 months ago

Before opening, please confirm:

JavaScript Framework

Angular

Amplify APIs

GraphQL API

Amplify Categories

api

Environment information

``` System: OS: Linux 4.15 Ubuntu 18.04.6 LTS (Bionic Beaver) CPU: (12) x64 Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz Memory: 512.21 MB / 15.51 GB Container: Yes Shell: 2.7.1 - /usr/bin/fish Binaries: Node: 16.13.0 - ~/.nvm/versions/node/v16.13.0/bin/node npm: 9.7.2 - ~/.nvm/versions/node/v16.13.0/bin/npm Browsers: Chrome: 117.0.5938.132 npmPackages: @angular-devkit/build-angular: ^15.2.9 => 15.2.9 @angular/animations: ^15.2.0 => 15.2.9 @angular/cdk: ^15.2.9 => 15.2.9 @angular/cli: ~15.2.9 => 15.2.9 @angular/common: ^15.2.0 => 15.2.9 @angular/compiler: ^15.2.0 => 15.2.9 @angular/compiler-cli: ^15.2.0 => 15.2.9 @angular/core: ^15.2.0 => 15.2.9 @angular/forms: ^15.2.0 => 15.2.9 @angular/material: ^15.2.9 => 15.2.9 @angular/platform-browser: ^15.2.0 => 15.2.9 @angular/platform-browser-dynamic: ^15.2.0 => 15.2.9 @angular/router: ^15.2.0 => 15.2.9 @aws-amplify/cli: ^12.0.0 => 12.6.0 @aws-amplify/ui-angular: ^4.0.9 => 4.0.9 @types/jasmine: ~4.3.0 => 4.3.6 aws-amplify: ^5.3.11 => 5.3.11 bootstrap: ^5.3.2 => 5.3.2 jasmine-core: ~4.5.0 => 4.5.0 karma: ~6.4.0 => 6.4.2 karma-chrome-launcher: ~3.1.0 => 3.1.1 karma-coverage: ~2.2.0 => 2.2.1 karma-coverage-coffee-example: 1.0.0 karma-jasmine: ~5.1.0 => 5.1.0 karma-jasmine-html-reporter: ~2.0.0 => 2.0.0 rxjs: ~7.8.0 => 7.8.1 (6.6.7) rxjs/ajax: undefined () rxjs/fetch: undefined () rxjs/internal-compatibility: undefined () rxjs/operators: undefined () rxjs/testing: undefined () rxjs/webSocket: undefined () tslib: ^2.3.0 => 2.6.2 (1.14.1, 2.5.0, 2.3.1, 2.4.1) typescript: ~4.9.4 => 4.9.5 zone-mix: undefined () zone-node: undefined () zone-testing: undefined () zone.js: ~0.12.0 => 0.12.0 zone.js/async-test: undefined () zone.js/async-test.min: undefined () zone.js/fake-async-test: undefined () zone.js/fake-async-test.min: undefined () zone.js/jasmine-patch: undefined () zone.js/jasmine-patch.min: undefined () zone.js/long-stack-trace-zone: undefined () zone.js/long-stack-trace-zone.min: undefined () zone.js/mocha-patch: undefined () zone.js/mocha-patch.min: undefined () zone.js/proxy: undefined () zone.js/proxy.min: undefined () zone.js/sync-test: undefined () zone.js/sync-test.min: undefined () zone.js/task-tracking: undefined () zone.js/task-tracking.min: undefined () zone.js/webapis-media-query: undefined () zone.js/webapis-media-query.min: undefined () zone.js/webapis-notification: undefined () zone.js/webapis-notification.min: undefined () zone.js/webapis-rtc-peer-connection: undefined () zone.js/webapis-rtc-peer-connection.min: undefined () zone.js/webapis-shadydom: undefined () zone.js/webapis-shadydom.min: undefined () zone.js/wtf: undefined () zone.js/wtf.min: undefined () zone.js/zone-bluebird: undefined () zone.js/zone-bluebird.min: undefined () zone.js/zone-error: undefined () zone.js/zone-error.min: undefined () zone.js/zone-legacy: undefined () zone.js/zone-legacy.min: undefined () zone.js/zone-patch-canvas: undefined () zone.js/zone-patch-canvas.min: undefined () zone.js/zone-patch-cordova: undefined () zone.js/zone-patch-cordova.min: undefined () zone.js/zone-patch-electron: undefined () zone.js/zone-patch-electron.min: undefined () zone.js/zone-patch-fetch: undefined () zone.js/zone-patch-fetch.min: undefined () zone.js/zone-patch-jsonp: undefined () zone.js/zone-patch-jsonp.min: undefined () zone.js/zone-patch-message-port: undefined () zone.js/zone-patch-message-port.min: undefined () zone.js/zone-patch-promise-test: undefined () zone.js/zone-patch-promise-test.min: undefined () zone.js/zone-patch-resize-observer: undefined () zone.js/zone-patch-resize-observer.min: undefined () zone.js/zone-patch-rxjs: undefined () zone.js/zone-patch-rxjs-fake-async: undefined () zone.js/zone-patch-rxjs-fake-async.min: undefined () zone.js/zone-patch-rxjs.min: undefined () zone.js/zone-patch-socket-io: undefined () zone.js/zone-patch-socket-io.min: undefined () zone.js/zone-patch-user-media: undefined () zone.js/zone-patch-user-media.min: undefined () npmGlobalPackages: @angular/cli: 15.2.3 @aws-amplify/cli: 12.4.0 corepack: 0.10.0 node-gyp: 9.4.0 npm-check-updates: 16.14.4 npm: 9.7.2 ```

Describe the bug

Hello! I'm running an Amplify project locally with the amplify mock command and having some issues.

I have the next model:

type StatusNode @model @searchable @auth(rules: [{allow: public}]) {
  id: ID!
  nodeID: ID! @index(name: "byNode")
  Value: String
  Time: String
  StatusTypeID: String
}

That have a hasMany relation with this other model:

type Node @model @auth(rules: [{allow: public}]) {
  id: ID!
  Name: String
  ...
  StatusNodes: [StatusNode] @hasMany(indexName: "byNode", fields: ["id"])
}

In the frontend, when I try to subscribe to a new StatusNode created (but only for a specific Node) by the subscrption generated by Amplify:

/* subscribe to new status_nodes being created */
this.subscription_status_nodes = this.api.OnCreateStatusNodeListener({
    nodeID: {
        eq: '5f3ce941-f35a-40ab-a679-35272abc7f19'
    }
}).subscribe(
    (event: any) => {
        console.log(event);
    }
);

The subscription failed with the error:

'Connection failed: {"errors":[{"message":"Unable to convert $extensions.setSubscriptionFilter($util.transform.toSubscriptionFilter($ctx.args.filter))\\nnull\\n to class com.amazonaws.deepdish.transform.model.lambda.LambdaVersionedConfig.","errorType":"MappingTemplate","data":null,"errorInfo":null,"path":["onCreateStatusNode"],"locations":[{"line":2,"column":3,"sourceName":"GraphQL request"}]}],"data":{"onCreateStatusNode":null}}'

The response VTL template where the error is going on is:

## [Start] Subscription Response template. **
#if( !$util.isNullOrEmpty($ctx.args.filter) )
$extensions.setSubscriptionFilter($util.transform.toSubscriptionFilter($ctx.args.filter))
#end
$util.toJson(null)
## [End] Subscription Response template. **

If I quit the filter argument of the OnCreateStatusNodeListener(), the subscription listener works fine, but when I try to filter by nodeID, the subscription fail.

I have no idea why, but is obviously that the filtering is not apllying propertly in the template engine or something similar.

Can anyone help me with that? Tahnks!

Expected behavior

The expected behavoir is to subscribe to new events filtered by the field, in my cases the nodeID field.

Reproduction steps

  1. Run amplify init
  2. Choose Angular as frontend framework
  3. Create a "searchable" model with a hasMany related model:
    type StatusNode @model @searchable @auth(rules: [{allow: public}]) {
    id: ID!
    nodeID: ID! @index(name: "byNode")
    Value: String
    Time: String
    StatusTypeID: String
    }
type Node @model @auth(rules: [{allow: public}]) {
  id: ID!
  Name: String
...
  StatusNodes: [StatusNode] @hasMany(indexName: "byNode", fields: ["id"])
}
  1. Run amplify mock
  2. Subscribe to a new statusNodes being created filtered by the nodeID field:
/* subscribe to new status_nodes being created */
this.subscription_status_nodes = this.api.OnCreateStatusNodeListener({
    nodeID: {
        eq: 'xxxxxxxxxxxxxxx'
    }
}).subscribe(
    (event: any) => {
        console.log(event);
    }
);

Code Snippet

// Put your code below this line.

Log output

``` // Put your logs below this line ```

aws-exports.js

/* eslint-disable */
// WARNING: DO NOT EDIT. This file is automatically generated by AWS Amplify. It will be overwritten.

const awsmobile = {
    "aws_project_region": "us-east-1",
    "aws_appsync_graphqlEndpoint": "http://192.168.1.26:20002/graphql",
    "aws_appsync_region": "us-east-1",
    "aws_appsync_authenticationType": "API_KEY",
    "aws_appsync_apiKey": "da2-fakeApiId123456",
    "aws_appsync_dangerously_connect_to_http_endpoint_for_testing": true,
    "aws_cognito_identity_pool_id": "us-east-1:xxxxxxxxxxx",
    "aws_cognito_region": "us-east-1",
    "aws_user_pools_id": "us-east-1_xxxxxxxxxx",
    "aws_user_pools_web_client_id": "xxxxxxxxxxxxxxxxxx",
    "oauth": {},
    "aws_cognito_username_attributes": [
        "EMAIL"
    ],
    "aws_cognito_social_providers": [],
    "aws_cognito_signup_attributes": [
        "EMAIL"
    ],
    "aws_cognito_mfa_configuration": "OFF",
    "aws_cognito_mfa_types": [
        "SMS"
    ],
    "aws_cognito_password_protection_settings": {
        "passwordPolicyMinLength": 8,
        "passwordPolicyCharacters": []
    },
    "aws_cognito_verification_mechanisms": [
        "EMAIL"
    ]
};

export default awsmobile;

Manual configuration

No response

Additional configuration

No response

Mobile Device

No response

Mobile Operating System

No response

Mobile Browser

No response

Mobile Browser Version

No response

Additional information and screenshots

No response

chrisbonifacio commented 11 months ago

Hi @Phok7 👋 thanks for raising this issue.

Are you only observing this behavior in a mocked api or is it reproducible in a live api?

Phok7 commented 11 months ago

Hi @chrisbonifacio, in a live api is working fine, only occurs in a mocked api.

cwomack commented 11 months ago

@Phok7, thanks for the clarity. Since this is only happening when using the mock api, we'll transfer this issue the category-api repo for better assistance.

sundersc commented 11 months ago

Subscriptions runtime filtering is not supported in mock env. (I see that this isn't called out in docs, trying to get it added) Marking this as feature request.