amplify-js: AppSync Subscriptions not working

Do you want to request a feature or report a bug? Bug

What is the current behavior? Simply cannot get AppSync Subscriptions to work. I’ve confirmed that the subscription works in the AWS console (by opening the query page in two windows, running the subscription in one, and queries in the other), however I cannot get it to work in my application.

Code subscription:

    const sub = API.graphql(graphqlOperation(subscriptions.onCreateLog)) as Observable<object>;
    sub.subscribe({
      next: (value: object) => {
        console.log(JSON.stringify(value));
      },
      error: (error: any) => {
        console.log(JSON.stringify(error));
      }
    });

The syntax for subscriptions in the docs, which doesn’t involve “as Observable<object>,” doesn’t work for me.

Per issue https://github.com/aws-amplify/amplify-js/issues/660, you must put your AppSync configuration at the root of your configuration, not under the API section. This lines up with the documentation. When I do this, however, I get:

{"data":{},"errors":[{"message":"No graphql endpoint provided."}]}

Per issue https://github.com/aws-amplify/amplify-js/issues/1302, this can be resolved by putting the appsync configuration in the API section of your configuration… In direct contradiction of https://github.com/aws-amplify/amplify-js/issues/660. This resolves the No graphql endpoint error, but still, my subscription doesn’t seem to work. I’ve tried putting the AppSync information both at the root of the config object and in the API section, however this doesn’t work either.

I’m at a bit of a loss, here. I’ve been at this for for quite awhile now, between this and the code in the docs not working.

Here is my network panel, if that helps

image

What is the expected behavior? Subscriptions should receive data changes from mutations.

Which versions of Amplify, and which browser / OS are affected by this issue? Did this work in previous versions? Version: aws-amplify@1.1.6 Browser: Chrome OS: Windows 10

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 26 (9 by maintainers)

Most upvoted comments

This is ridiculous, every single Amplify product I have tried has been a pain in the a** what a joke costs me so much time. Im about to give up on Amplify all together. Its always something takes me days to figure out out. I could have just built my own login at this point…

I hit this thread with a similar problem. I do not see an error in the browser console. My subscription code:

const sub = API.graphql(
    graphqlOperation(subscriptions.addBattlestar)
)
sub.subscribe({
    next: (data) => console.log('^^alldata=', data),
    complete: console.log,
    error: console.log
});

I have enabled amplify debug (Amplify.Logger.LOG_LEVEL = "DEBUG"), but it does not show any errors either

@krazykhris875 just to be crystal clear, when your Lambda function runs you are calling a GraphQL mutation in AppSync that is connected to a Subscription correct?

Correct, from the queries section in the AppSync AWS console.

I can open the queries window twice, run my subscription in one, and run my create queries in another, and the subscription works perfectly there in the console. The subscription in the console also receives events when I run a create mutation from my angular app.

I appreciate all of your guys’ help but I’m going to implement an alternative that doesn’t use AppSync, for now.

My subscription, stored in src/app/graphql/subscriptions.ts:

export const onCreateLog = `subscription OnCreateLog(
  $id: ID
  $filename: String
  $message: String
  $success: Boolean
  $failure: Boolean
) {
  onCreateLog(
    id: $id
    filename: $filename
    message: $message
    success: $success
    failure: $failure
  ) {
    id
    filename
    message
    success
    failure
    datetime
  }
}
`;

Which is subscribed to in a service I’ve injected into homescreen component for testing.

log.service.ts:

import { Injectable } from '@angular/core';
import Amplify, { API, graphqlOperation } from 'aws-amplify';
import * as subscriptions from '../graphql/subscriptions';
import * as Observable from 'zen-observable';

@Injectable({
  providedIn: 'root'
})
export default class LogService {

  constructor() {
    console.log("Should init");
    
    const sub = API.graphql(graphqlOperation(subscriptions.onCreateLog)) as Observable<object>;
    sub.subscribe({
      next: (value: object) => {
        console.log(JSON.stringify(value));
      },
      error: (error: any) => {
        console.log(JSON.stringify(error));
      }
    });
  }
}

home.component.ts:

import { Component, OnInit } from '@angular/core';
import { AuthService } from '../auth.service';
import { Subscription } from 'rxjs/Subscription';
import { API } from 'aws-amplify';
import LogService from '../log.service';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
  subscription: Subscription;
  public user;
  
  constructor(
    public auth: AuthService,
    public log: LogService
  ) { }

  ngOnInit() { 
    this.subscription = this.auth.loggedIn
      .subscribe(result => {
        this.user = result;
        //console.log(result);
      }); 
  }

  ngOnDestroy() {
    this.subscription.unsubscribe();
  }
}

This example makes no sense

What JS framework are you using here? Looks like based on zone.js is angular, is that correct? If so, which version?

If Angular, you should put your config in src/main.ts and configure each category independently, OR use the entire lib.

For example:

import API from '@aws-amplify/api';
import PubSub from '@aws-amplify/pubsub'; // this is needed for subscriptions IF using modular imports
import AWSConfig from './aws-exports';
API.configure(AWSConfig);
PubSub.configure(AWSConfig);

In angular, the Observable is from zen-observable so you need to import and cast that when creating a subscription on your own:

in your api.service.ts

import API from '@aws-amplify/api';
import * as Observable from "zen-observable";

OnCreateSomethingListener: Observable<OnCreateCreateSomethingSubscription> = API.graphql(
    graphqlOperation(
      `subscription onCreateSomething {
        onCreateSomething {
          __typename
          id
          name
        }
      }`
    )
  ) as Observable<OnCreateDomainSubscription>;

We are in the process of releasing some code generation for this that will automate this with the aws-amplify/cli very soon. Let me know if this helps/clears things up and thanks for the feedback we clearly need to update/clean up some documentation regarding this.