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
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
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: [email protected]
Browser: Chrome
OS: Windows 10
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.
Sorry about that, didn't mean to leave out vital details. I really appreciate your help.
I am using angular and configuring the whole lib, making use of Cognito auth, an S3 bucket, and (currently) two lambda functions, configured like so:
import Amplify from 'aws-amplify';
let amplifyConfig = {
Auth: {
identityPoolId: 'xxx',
region: 'xxx',
userPoolId: 'xxx',
userPoolWebClientId: 'xxx'
},
Storage: {
bucket: 'xxx',
region: 'xxx'
},
API: {
endpoints: [
{
name: "xxx",
endpoint: "xxx",
service: "lambda",
region: "xxx"
},
{
name: "xxx",
endpoint: "xxx",
service: "lambda",
region: "xxx"
}
],
"aws_project_region": "xxx",
"aws_appsync_graphqlEndpoint": "xxx",
"aws_appsync_region": "xxx",
"aws_appsync_authenticationType": "xxx",
"aws_appsync_apiKey": "xxx"
}
};
Amplify.configure(amplifyConfig);
Configured with the graphql information under the Auth object, I don't get any errors, the subscription just never seems to receive any events. If I put it under the root object rather than Auth, I get the no graphql endpoint error.
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();
}
}
What are you using for Authentication type on your appsync api API key, IAM, or User Pools?
API Key just for development, but ultimately it will be User Pools
Just tried with User Pool and can confirm that isn't working either. Same situation, no errors on subscribe but I never receive the events
Hm, can you try changing your subscription code to:
// make sure you are importing zen-observable above
const sub = API.graphql(graphqlOperation(subscriptions.onCreateLog)) as Observable<object>;
sub.subscribe(
(data: any) => {
console.log('data from subscription: ', data);
}
);
Also, can you add, just before your Amplify.configure
statement:
Amplify.Logger.LOG_LEVEL = "DEBUG";
if you add that log statement, it will give you a large amount of logging to perhaps see if something is getting swallowed.
Added the debugging and your subscription code.
Unfortunately no change. There is debugging output for the subscription being created, but nothing after or when events should be fired
Which version of Angular are you using?
@krazykhris875 are you able to run a mutation and/or a query from the client successfully?
@mlabieniec v6.1.0
Here is my package.json, if that helps at all:
"@angular/animations": "^6.1.0",
"@angular/common": "^6.1.0",
"@angular/compiler": "^6.1.0",
"@angular/core": "^6.1.0",
"@angular/forms": "^6.1.0",
"@angular/http": "^6.1.0",
"@angular/platform-browser": "^6.1.0",
"@angular/platform-browser-dynamic": "^6.1.0",
"@angular/router": "^6.1.0",
"aws-amplify": "^1.1.6",
"zen-observable": "^0.8.0",
"core-js": "^2.5.4",
"rxjs": "^6.2.2",
"rxjs-compat": "6.2.2",
"zone.js": "~0.8.26"
I'll try out the mutation
@undefobj Just tested: mutation works. I can see my inserted data in my data source in the AWS console, and in fact if I keep the subscription running in the AWS AppSync console, it receives the event for the mutation called from my app. May app, however, doesn't.
home.component.html:
<button (click)="testMutationClicked()" class="button">Test Create Mutation</button>
home.component.ts:
testMutationClicked() {
console.log("Clicked.");
this.log.testMutation();
}
log.service.ts:
async testMutation() {
console.log("Will test");
const log = {
xxx: "xxx"
};
const newLog = await API.graphql(graphqlOperation(mutations.createLog, {input: log}));
console.log(newLog);
}
~Just tested, turns out it works in Microsoft Edge, but not Chrome, and only when the mutation comes from my app, not from the AppSync console.~
~Working in both Edge and Chrome but only when the mutation comes from my app and not the AppSync console. Perhaps that's intended?~
Sorry, ignore all that, I'm an absolute moron and thought it was working but it was just the output from the mutation... Still not working
So if the mutation isn't working that probably means you're not connected properly, hence why subs aren't working either. What does the HTTP response say when you run a mutation?
Sorry to be unclear, the mutation is working perfectly, just for a moment I thought the subscription was working, too, but it's not.
What I'm trying to do is log output from lambda functions to the user in a web browser. The way I'm trying to do that is with AppSync, using a subscription on the create event for a DynamoDB table, so that I can log from my Lambda's using the mutation, and receive the result with the subscription.
Since the subscription looks like it isn't going to work, do you have any better suggestions? From what I can tell, PubSub is more for IoT, SNS can only be done through the browser with service workers, which aren't supported in IE, and I haven't been able to find any reference to using DynamoDB Streams with Amplify.
Your use case is fine, honestly not sure what the issue is based on what you've explained. If you create a mutation in the AppSync console and it's triggering a subscription you're saying the client can run a query to see that data but subscription messages are never received?
@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? Meaning you're not just making changes in DynamoDB or somewhere else and expecting them to trigger a subscription. You have to actually call a Mutation in AppSync that is hooked up to a Subscription with the @aws_subscribe
directive in your schema: https://docs.aws.amazon.com/appsync/latest/devguide/real-time-data.html
@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.
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
Ignore my comment above. I created a new project, fresh graphql schema, amplify project and I got subscription working
Though I have to say, debugging subscription is a pain
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
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.....
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.....
Inline with the above thread:
One of my API graphqlOperation issues was with the Lambda function serving the GraphQL dat set operations was silently failing/hanging. The confusion I had was with the Lambda and API dashboard that was showing 100% success rate, however I suspect something in the pipeline between the Lambda function and GraphQL fails or hangs w/o any obvious errors.
To trouble shoot I:
1) Turned on Cloud watch logs for the API to verify that the Lambda was in fact fetching data and pushing it to GraphQL ( saw a ton of {"duration":617325162,"logType":"Tracing"} entries
2) Reduced Data Set size ( in my case I had a query interacting with MSSQL database, reduced result to the bare minimum fields)
and all issues went away.
I was able to reproduce this by adding back all of the columns/data
Have to look into a pagination solution.
Hope this helps some one.
Most helpful comment
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.....