从 DynamoDB 更改中反应应用程序更新数据

Posted

技术标签:

【中文标题】从 DynamoDB 更改中反应应用程序更新数据【英文标题】:React Application Update Data from DynamoDB Change 【发布时间】:2020-03-05 13:34:00 【问题描述】:

我正在使用 AWS AppSync 和 DynamoDB 构建一个带有 GraphQL 的 React 应用程序。我的用例是我有一个从 DynamoDB 表中提取并使用 GraphQL 显示给用户的数据表。我有一些字段正在通过在 AWS 上运行的步进函数进行更新。我需要为用户自动更新这些字段,就像从 GraphQL 订阅一样,但我发现订阅与突变相关联,因此从步进函数更新数据库不会触发前端的订阅更新。为了解决这个问题,我使用以下方法:

useEffect(() => 
  setTimeout(getSubmissions, 5 * 1000)
)

显然,这是很多过度获取,并且可能会产生不必要的费用。我一直在寻找更好的解决方案并遇到了 DynamoDB 流,但如果 DynamoDB 流无法触发前端来刷新组件,它们将无法帮助我。必须有比我想出的更好的解决方案。

谢谢!

【问题讨论】:

谢谢!这是我的确切用例! 【参考方案1】:

假设您使用 Cognito 作为 AppSync 应用程序的身份验证,您可以在 dynamo 表上设置一个 lambda 触发器,该触发器生成一个 cognito 令牌,并使用它向您的突变端点发出授权请求。注意:在您的 cognito userpool>app clients 页面中,您需要选中 Enable username password auth for admin APIs for authentication (ALLOW_ADMIN_USER_PASSWORD_AUTH) 框以生成客户端密码。

const AWS = require('aws-sdk');
const crypto = require('crypto');
var jwt = require('jsonwebtoken');


const secrets = require('./secrets.js');
var cognitoidentityserviceprovider = new AWS.CognitoIdentityServiceProvider();
var config;





const adminAuth = () => new Promise((res, rej) => 

        const digest = crypto.createHmac('SHA256', config.SecretHash)
          .update(config.userName + config.ClientId)
          .digest('base64');

        var params = 
          AuthFlow: "ADMIN_NO_SRP_AUTH",
          ClientId: config.ClientId, /* required */
          UserPoolId: config.UserPoolId, /* required */
          AuthParameters: 
            'USERNAME': config.userName,
            'PASSWORD': config.password,
            "SECRET_HASH":digest
          ,
        ;
        cognitoidentityserviceprovider.adminInitiateAuth(params, function(err, data) 
          if (err) 
              console.log(err.stack);
              rej(err);
          
          else 

              data.AuthenticationResult ? res(data.AuthenticationResult) : rej("Challenge requested, to verify, login to app using admin credentials");
          
        ); 
);

const decode = auth => new Promise( res => 
    const decoded = jwt.decode(auth.AccessToken);
    auth.decoded = decoded
    res(auth);
);


//example gql query

 const testGql = auth =>  
     const url = config.gqlEndpoint;

     const payload  = 
         query: `
           query ListMembers 
             listMembers 
               items
                 firstName
                 lastName
               
             
           
         ` 
     ;


     console.log(payload);      
     const options = 
         headers: 
           "Authorization": auth.AccessToken
         ,
     ;

     console.log(options);
     return axios.post(url, payload, options).then(data =>  data.data)
     .catch(e => console.log(e.response.data));
 ;






exports.handler = async (event, context, callback) => 
   await secrets() //some promise that returns your keys object (i use secrets manager)
   .then( keys => 
       #keys=ClientId:YOUR_COGNITO_CLIENT, 
       #      UserPoolId:YOUR_USERPOOL_ID,
       #      SecretHash:(obtained from cognito>userpool>app clients>app client secret),
       #      gqlEndpoint:YOUR_GRAPHQL_ENDPOINT,
       #      userName:YOUR_COGNITO_USER,
       #      password:YOUR_COGNITO_USER_PASSWORD,
       #      

       config = keys
       return adminAuth()
   )
   .then(auth => 
       return decode(auth)
   )
   .then(auth => 
       return testGql(auth)
   )
   .then( data => 
       console.log(data)
       callback(null, data)
   )
   .catch( e => 
       callback(e)
   )
;

【讨论】:

【参考方案2】:

您是正确的,在 AWS AppSync 中,要触发订阅发布,您必须触发 GraphQL 突变。

但我发现订阅与突变相关联,因此 从步进函数更新数据库不会触发 前端订阅更新。

如果您直接通过步进函数或通过 DynamoDB 流更新您的 DynamoDB 表,则 AppSync 无法知道刷新的数据。 为什么不让你的步进函数使用 AppSync 突变而不是直接更新你的表?这样,您可以将订阅链接到突变,并让您感兴趣的客户在数据刷新时获得推送更新。

【讨论】:

我没有想到这个!我已经把它发给了做后端的人,看看我们能不能把它搞定。谢谢! 我什至不认为我会为我的确切用例找到一个 SO。成为开发人员的好时机!

以上是关于从 DynamoDB 更改中反应应用程序更新数据的主要内容,如果未能解决你的问题,请参考以下文章

我在反应本机应用程序中使用 redux 来获取和显示数据,但它没有更新来自后端的数据更改

闪亮:更新输入而不触发反应?

更新反应脚本后如何修复主页上的重大更改(创建反应应用程序)

如何使用 ConditionExpression 更新一个属性值而不影响其他属性 - DynamoDB

对路由器更改做出反应重新安装

Amazon dynamoDB 计数器更新和获取项目