如何稳定关联Cognito用户与DynamoDB用户并实现可靠查询?
问题分析与最优实现方案
首次查询DynamoDB用户失败的核心原因,通常是Post Confirmation Lambda触发器的执行延迟,或是Amplify DataStore的本地缓存未及时同步云端最新数据:用户完成认证跳转首页时,Lambda可能还没完成DynamoDB用户记录的写入,或是DataStore本地缓存还没拉取到新创建的用户数据,导致查询为空。
解决方案
1. 增加查询重试机制
给Lambda触发器预留足够的执行时间,查询失败时进行有限次数的重试:
import { Auth } from "aws-amplify"; import { DataStore} from '@aws-amplify/datastore'; import { User } from "../src/models"; const [user , setUser] = useState<User | null>(null); const [ready, setReady] = useState(false); const getUser = async () => { try{ const userData = await Auth.currentAuthenticatedUser(); const currentUserPhone = userData.attributes.phone_number if(!currentUserPhone){ setReady(false); return; } // 最多重试3次,每次间隔1秒 let retryCount = 0; let userRecord = []; while(retryCount < 3){ userRecord = await DataStore.query(User, d => d.Phonenumb("eq", currentUserPhone)); if(userRecord.length > 0) break; retryCount++; await new Promise(resolve => setTimeout(resolve, 1000)); } if(userRecord.length > 0){ setUser(userRecord[0]); setReady(true); } else { setReady(false); console.log("重试3次后仍未查询到用户记录"); } } catch(e){ setReady(false); console.log(e) } } useEffect(() => { getUser(); }, []); return( <View> {ready === true && (<Text>Hello {user?.name}</Text>)} {ready === false && (<Text>No user</Text>)} </View> )
2. 强制DataStore同步云端数据
DataStore默认优先读取本地缓存,查询前先触发全量同步,确保获取最新数据:
const getUser = async () => { try{ const userData = await Auth.currentAuthenticatedUser(); const currentUserPhone = userData.attributes.phone_number if(!currentUserPhone){ setReady(false); return; } // 先同步云端数据到本地缓存 await DataStore.sync(); const userRecord = await DataStore.query(User, d => d.Phonenumb("eq", currentUserPhone)); if(userRecord.length > 0){ setUser(userRecord[0]); setReady(true); } else { setReady(false); } } catch(e){ setReady(false); console.log(e) } }
3. 优化关联查询的唯一性
改用Cognito用户的sub(全局唯一ID)作为DynamoDB用户记录的索引字段,替代手机号:
- 修改Lambda触发器,将Cognito用户的
sub写入DynamoDB的CognitoSub字段 - 查询时使用
sub作为条件:
const currentUserSub = userData.attributes.sub; const userRecord = await DataStore.query(User, d => d.CognitoSub("eq", currentUserSub));
4. 监听Auth状态变化触发查询
避免组件挂载时Auth状态未稳定的问题,通过监听认证状态变化来触发查询:
useEffect(() => { const unsubscribe = Auth.subscribe({ next: (data) => { // 用户登录成功时触发查询 if(data.payload.event === 'signIn'){ getUser(); } } }); return () => unsubscribe(); }, []);
5. 增强Lambda触发器可靠性
- 给Lambda配置死信队列(DLQ),避免写入DynamoDB失败时丢失用户记录
- 在Lambda中增加写入确认逻辑,确保数据成功写入后再返回:
// Lambda示例代码片段 const putParams = { TableName: 'UserTable', Item: { CognitoSub: event.request.userAttributes.sub, Phonenumb: event.request.userAttributes.phone_number, // 其他字段 }, ReturnValues: 'ALL_OLD' }; await dynamodb.put(putParams).promise();
内容的提问来源于stack exchange,提问作者sama
相关产品推荐
相关产品推荐

