Closed jitendra-koodo closed 4 years ago
@jitendra-koodo Can you clarify what you mean by the following, or provide a screenshot?
while for the same new created object, console subscription shows
{ "data": { "onCreateBank": { "id": "6abcc124-8e83-4192-a331-de187b660f96", "name": "8abcdef", "__typename": "Bank" } } }
If you've been following along with https://aws-amplify.github.io/docs/js/start?ref=amplify-rn-btn&platform=react-native, could you also provide amplify/backend/api/photoalbumse2e/schema.graphql
for us to reproduce with?
@ericclemmons : Please find details below.
type Bank @model { id: ID! name: String! logoUrl: AWSURL! popularityScore: Int! dirty: Boolean disabled: Boolean smsCodes: [SmsCode!]! @connection(name: "BankSmsCodes") }
type SmsCode @model { id: ID! code: String! shortCode: String! bank: Bank! @connection(name: "BankSmsCodes") disabled: Boolean }
Found the problem/solution with the help of AWS support engineer. In case someone needs help...
Subscription only works in app if returned fields in corresponding mutation match with corresponding returned fields in subscription definition. If this is not the case, subscription would only work on console but not in APIs.
Its not documented anywhere...
@jitendra-koodo I'm glad you got this resolved!
Oddly enough, I've been testing with a local app and had trouble reproducing, for other reasons:
updateAlbum
and onUpdateAlbum
originally had the same fields returned.onUpdateAlbum
(in src/graphql/subscriptions.js
still returned the full payload:export const onUpdateAlbum = `subscription OnUpdateAlbum($owner: String!) {
onUpdateAlbum(owner: $owner) {
# As long as this is valid, it returns the full shape
id
}
}
`;
useEffect(() => {
const subscription = API.graphql({
authMode: owner ? 'AMAZON_COGNITO_USER_POOLS' : 'AWS_IAM',
query: onUpdateAlbum,
variables: { owner }
}).subscribe({
next(payload) {
console.log(JSON.stringify(payload.value.data.onUpdateAlbum, null, 2));
setAlbum(payload.value.data.onUpdateAlbum);
}
});
return () => subscription.unsubscribe();
}, [id, owner]);
{
"id": "5c010de4-d1b9-4cfd-9e6e-96119cb700f7",
"name": "Logos3",
"version": 13,
"owner": "Google_110029493523186990292",
"photos": {
"items": [
{
"id": "3dc395fd-e6b8-49e7-b75e-217849de9828",
"bucket": "photo-albums-e2e3b4b5dc769004b0c88c0195ee05bf4e3-cypress",
"labels": [
"triangle",
"text",
"label"
],
"description": "Vue Color@2x",
"version": 7,
"owner": "Google_110029493523186990292",
"__typename": "Photo"
},
{
"id": "f93cfa3b-9f66-42f1-ac5a-df0a34d207da",
"bucket": "photo-albums-e2e3b4b5dc769004b0c88c0195ee05bf4e3-cypress",
"labels": [
"trademark",
"logo",
"symbol",
"bomb",
"weapon",
"weaponry",
"dynamite",
"label",
"text"
],
"description": "aws_logo",
"version": 1,
"owner": "Google_110029493523186990292",
"__typename": "Photo"
},
{
"id": "e1df4619-ad39-4a25-a1e9-b8d4f0b2ee96",
"bucket": "photo-albums-e2e3b4b5dc769004b0c88c0195ee05bf4e3-cypress",
"labels": [
"text",
"number",
"symbol",
"trademark",
"logo",
"moon",
"outdoors",
"outer space",
"night",
"space",
"nature",
"universe",
"astronomy"
],
"description": "Ionic Color@2x",
"version": 1,
"owner": "Google_110029493523186990292",
"__typename": "Photo"
},
{
"id": "277dc646-3d24-49a1-b5ba-a1e4c77228a2",
"bucket": "photo-albums-e2e3b4b5dc769004b0c88c0195ee05bf4e3-cypress",
"labels": [
"symbol",
"sign"
],
"description": "Angular Color@2x",
"version": 1,
"owner": "Google_110029493523186990292",
"__typename": "Photo"
},
{
"id": "a21dd9d0-b805-495a-bace-12949a17d58d",
"bucket": "photo-albums-e2e3b4b5dc769004b0c88c0195ee05bf4e3-cypress",
"labels": [
"symbol",
"sign"
],
"description": "Angular Color@2x",
"version": 1,
"owner": "Google_110029493523186990292",
"__typename": "Photo"
},
{
"id": "40ba044b-4e77-4269-a8c1-abcfdb83801f",
"bucket": "photo-albums-e2e3b4b5dc769004b0c88c0195ee05bf4e3-cypress",
"labels": [
"label",
"text",
"sticker",
"silhouette",
"astronomy",
"outer space",
"space",
"moon",
"night",
"outdoors",
"nature",
"universe"
],
"description": "GitHub-Mark-120px-plus",
"version": 1,
"owner": "Google_110029493523186990292",
"__typename": "Photo"
},
{
"id": "39c55697-4c83-45fe-a415-6511dbd7a222",
"bucket": "photo-albums-e2e3b4b5dc769004b0c88c0195ee05bf4e3-cypress",
"labels": [
"logo",
"trademark",
"symbol"
],
"description": "React Color@2x",
"version": 1,
"owner": "Google_110029493523186990292",
"__typename": "Photo"
}
],
"nextToken": null,
"__typename": "ModelPhotoConnection"
},
"__typename": "Album"
}
From the looks of it, because the schema.graphql
is compiled down into schema.json
and src/graphql/*
, your app will always return the mutated model.
{
"name": "onUpdateAlbum",
"description": null,
"args": [
{
"name": "owner",
"description": null,
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
},
"defaultValue": null
}
],
"type": {
"kind": "OBJECT",
"name": "Album",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
Why it's null
in your logging, I still cannot say...
@jitendra-koodo I'm glad you got this resolved!
Oddly enough, I've been testing with a local app and had trouble reproducing, for other reasons:
updateAlbum
andonUpdateAlbum
originally had the same fields returned.- Removing fields from
onUpdateAlbum
(insrc/graphql/subscriptions.js
still returned the full payload:export const onUpdateAlbum = `subscription OnUpdateAlbum($owner: String!) { onUpdateAlbum(owner: $owner) { # As long as this is valid, it returns the full shape id } } `;
useEffect(() => { const subscription = API.graphql({ authMode: owner ? 'AMAZON_COGNITO_USER_POOLS' : 'AWS_IAM', query: onUpdateAlbum, variables: { owner } }).subscribe({ next(payload) { console.log(JSON.stringify(payload.value.data.onUpdateAlbum, null, 2)); setAlbum(payload.value.data.onUpdateAlbum); } }); return () => subscription.unsubscribe(); }, [id, owner]);
{ "id": "5c010de4-d1b9-4cfd-9e6e-96119cb700f7", "name": "Logos3", "version": 13, "owner": "Google_110029493523186990292", "photos": { "items": [ { "id": "3dc395fd-e6b8-49e7-b75e-217849de9828", "bucket": "photo-albums-e2e3b4b5dc769004b0c88c0195ee05bf4e3-cypress", "labels": [ "triangle", "text", "label" ], "description": "Vue Color@2x", "version": 7, "owner": "Google_110029493523186990292", "__typename": "Photo" }, { "id": "f93cfa3b-9f66-42f1-ac5a-df0a34d207da", "bucket": "photo-albums-e2e3b4b5dc769004b0c88c0195ee05bf4e3-cypress", "labels": [ "trademark", "logo", "symbol", "bomb", "weapon", "weaponry", "dynamite", "label", "text" ], "description": "aws_logo", "version": 1, "owner": "Google_110029493523186990292", "__typename": "Photo" }, { "id": "e1df4619-ad39-4a25-a1e9-b8d4f0b2ee96", "bucket": "photo-albums-e2e3b4b5dc769004b0c88c0195ee05bf4e3-cypress", "labels": [ "text", "number", "symbol", "trademark", "logo", "moon", "outdoors", "outer space", "night", "space", "nature", "universe", "astronomy" ], "description": "Ionic Color@2x", "version": 1, "owner": "Google_110029493523186990292", "__typename": "Photo" }, { "id": "277dc646-3d24-49a1-b5ba-a1e4c77228a2", "bucket": "photo-albums-e2e3b4b5dc769004b0c88c0195ee05bf4e3-cypress", "labels": [ "symbol", "sign" ], "description": "Angular Color@2x", "version": 1, "owner": "Google_110029493523186990292", "__typename": "Photo" }, { "id": "a21dd9d0-b805-495a-bace-12949a17d58d", "bucket": "photo-albums-e2e3b4b5dc769004b0c88c0195ee05bf4e3-cypress", "labels": [ "symbol", "sign" ], "description": "Angular Color@2x", "version": 1, "owner": "Google_110029493523186990292", "__typename": "Photo" }, { "id": "40ba044b-4e77-4269-a8c1-abcfdb83801f", "bucket": "photo-albums-e2e3b4b5dc769004b0c88c0195ee05bf4e3-cypress", "labels": [ "label", "text", "sticker", "silhouette", "astronomy", "outer space", "space", "moon", "night", "outdoors", "nature", "universe" ], "description": "GitHub-Mark-120px-plus", "version": 1, "owner": "Google_110029493523186990292", "__typename": "Photo" }, { "id": "39c55697-4c83-45fe-a415-6511dbd7a222", "bucket": "photo-albums-e2e3b4b5dc769004b0c88c0195ee05bf4e3-cypress", "labels": [ "logo", "trademark", "symbol" ], "description": "React Color@2x", "version": 1, "owner": "Google_110029493523186990292", "__typename": "Photo" } ], "nextToken": null, "__typename": "ModelPhotoConnection" }, "__typename": "Album" }
From the looks of it, because the
schema.graphql
is compiled down intoschema.json
andsrc/graphql/*
, your app will always return the mutated model.{ "name": "onUpdateAlbum", "description": null, "args": [ { "name": "owner", "description": null, "type": { "kind": "NON_NULL", "name": null, "ofType": { "kind": "SCALAR", "name": "String", "ofType": null } }, "defaultValue": null } ], "type": { "kind": "OBJECT", "name": "Album", "ofType": null }, "isDeprecated": false, "deprecationReason": null },
Why it's
null
in your logging, I still cannot say...
@ericclemmons Try removing any non-nullable field.
I had version
(as I'm using @versioned
) removed in the above test. This is tricky... 🤔
Facing the same issue in a react web app . @jitendra-koodo had pointed that we need to have the same structure for subscriptions and respective mutations . However it still returns null .
@slatemates Can you share your schema, the query for your subscription, and the code that you're using for making the call (e.g. API.graphql(...)
)?
I was unable to reproduce this (https://github.com/aws-amplify/amplify-js/issues/4832#issuecomment-582111032) and was still getting the full response back rather than null
(even with required fields removed).
This is the code that we are using on the client App.
import React, { useState, useEffect } from "react"; import {listTeachers} from './graphql/queries' import {onCreateTeacher} from './graphql/subscriptions' import {onCreateWallet} from './graphql/subscriptions' import {mutations, updateTeacher} from './graphql/mutations' import {subscriptions} from './graphql/subscriptions' import awsconfig from './aws-exports'; import Amplify, { API, graphqlOperation } from 'aws-amplify'; import Teacher from './Teacher'
Amplify.configure(awsconfig);
function TeacherList () { const [teachers, setTeachers] = useState([]); useEffect(() => { const getTeachersList = async () => { const result = await API.graphql(graphqlOperation(listTeachers)); setTeachers( result.data.listTeachers.items ); };
getTeachersList();
}, []);
useEffect(() => {
const teacherSubscription = API.graphql(
graphqlOperation(onCreateTeacher)
).subscribe({
next: data => {
// const { value: { data: {onCreateTeacher} }} = data
console.log(JSON.stringify(data.value.data.onCreateTeacher));
}
})
const walletSubscription = API.graphql(
graphqlOperation(onCreateWallet)
).subscribe({
next: dataWallet => {
// const { value: { data: {onCreateTeacher} }} = data
console.log(JSON.stringify(dataWallet.value.data.onCreateWallet));
}
})
return () => {
teacherSubscription.unsubscribe();
walletSubscription.unsubscribe();
}
}, [teachers])
return(
<div>
Teacher List
<h1>
{
teachers.map(teacher =>(
<Teacher key = {teacher.id} {...teacher} ></Teacher>
))
}
</h1>
</div>
);
}
export default TeacherList
Schema.graphql
type Wallet @model { id: ID! amount: Float createdAt: String updatedAt: String }
type Teacher @model { id: ID! name: String! teacherUserName: String!
}
Subscriptions..:
export const onCreateWallet = / GraphQL / subscription OnCreateWallet { onCreateWallet { id amount createdAt updatedAt } }
;
export const onCreateTeacher = / GraphQL / ` subscription OnCreateTeacher { onCreateTeacher { id name teacherUserName
}
} `;
We have tested by pushing an entirely new api with the above schema . Amplify CLI Version (4.13.4) and aws-amplify(2.2.5) . We are getting null for the "teacherSubscription" whereas we are getting just the "id" for the "wallet subscription ".
Output :
null
{"amount":null,"createdAt":null,"id":"41689a23-2318-4df0-b06d-39372c4f6451","updatedAt":null}
Also I forgot to mention, that we dont have any @auth transformers mentioned on the graphql schema . The subscription seems to work on appsync console, where "id" and "_type" are returned
The problem seems to be resolved presently. We are able to get the data on the client web app. There was no change in front end code, schema . However, now on the app console the subscription is returning the complete data instead of just the "id" and the "_type" fields as reported earlier
The appsync/amplify subscription appears to be inconsistent . Sometimes we are able to get data on the frontend , at other times we simply get a null object.
It seems to working though in case the mutation returns the same structure as is expected in the subscription else the fields are returned null
I don't like this solution, although it works. What if you make updates to fields as an admin and would like only some of the updated information propagated to real time users? This could be a security risk as a nefarious user would simply inspect their network tab to find compromising information if the data updated is not their own. Amplify needs to document this and change it, it's not the GraphQL way.
Remove the non-nullable field and then try to fetch it will work
My Code
function App() {
//brought from src/graphql/subscriptions.js | Copy & Paste then Remove the fields one by one then test
const onCreateUser = /* GraphQL */ `
subscription OnCreateUser {
onCreateUser {
name
}
}
`;
async function fetchUsers(){
try{
const subscription = API.graphql(graphqlOperation(onCreateUser)
).subscribe({
next: (todoData) => {setUsersOnline(...todoData.value.data.onCreateUser.name)}
});
}
catch(err){console.log(err)}
}
return (
<div>
Messages : {messages.length} Users: {usersOnline}
</div>
);
}
export default App;
Is there a fix for this? I had to just hack a refresh for now. Always comes back null.
idk :(
This issue has been automatically locked since there hasn't been any recent activity after it was closed. Please open a new issue for related bugs.
Looking for a help forum? We recommend joining the Amplify Community Discord server *-help
channels or Discussions for those types of questions.
Describe the bug
Log always shows
new{"onCreateBank":null}
while for the same new created object, console subscription shows
{ "data": { "onCreateBank": { "id": "6abcc124-8e83-4192-a331-de187b660f96", "name": "8abcdef", "__typename": "Bank" } } }
To Reproduce https://aws-amplify.github.io/docs/js/start?ref=amplify-rn-btn&platform=react-native
*Additional context Add any other context about the problem here. Windows 10
"dependencies": { "aws-amplify": "^2.2.2", "aws-amplify-react-native": "^3.2.0", "react": "16.9.0", "react-native": "0.61.5" },