如何使Spring控制器的JSON响应等待Firebase查询结束?

huangapple go评论110阅读模式
英文:

How to make spring controller json response wait until firebase query ends?

问题

I'm using an ajax call to spring controller to start a firebase query, save the result to the local database and return items saved in the local database (including the results saved from the current and previous firebase queries too). The problem is that since the firebase query runs async, the results from the local database query are returned before the firebase query finishes.

  1. @PostMapping("/firebase-download")
  2. @ResponseBody
  3. public List<FirebaseTransactionRecord> firebaseDownload() {
  4. firebaseService.downloadAndSaveFirebaseTransactions();
  5. // wait for the query to end
  6. return firebaseTransactionRecordRepository.findBySentFalse();
  7. }
  1. @Override
  2. @Transactional
  3. public void downloadAndSaveFirebaseTransactions() {
  4. final List<FirebaseTransactionRecord> firebaseTransactions = new ArrayList<>();
  5. firebaseDb.child(StringValueConstant.DB_CHILD_TEMPORARY_TRANSACTIONS)
  6. .addValueEventListener(new ValueEventListener() {
  7. @Override
  8. public void onDataChange(DataSnapshot snapshot) {
  9. for (DataSnapshot userSnapshot : snapshot.getChildren()) {
  10. userSnapshot.getChildren().forEach(transactionSnapshot -> {
  11. FirebaseTransactionRecord record = firebaseTransactionMapper
  12. .toFirebaseTransactionRecord(transactionSnapshot);
  13. firebaseTransactions.add(record);
  14. });
  15. }
  16. saveFirebaseTransactionRecords(firebaseTransactions);
  17. }
  18. @Override
  19. public void onCancelled(DatabaseError error) {
  20. log.error("Error reading Firebase data:", error);
  21. }
  22. });
  23. }
  1. @Override
  2. @Transactional
  3. public void saveFirebaseTransactionRecords(List<FirebaseTransactionRecord> firebaseTransactions) {
  4. firebaseTransactions.forEach(firebaseTransaction -> {
  5. if (!firebaseTransactionRecordRepository.existsByReferralNumber(firebaseTransaction.getReferralNumber())) {
  6. firebaseTransactionRecordRepository.save(firebaseTransaction);
  7. }
  8. });
  9. }
英文:

I'm using an ajax call to spring controller to start a firebase query, save the result to local database and return items saved in the local database (including the results saved from the current and previous firebase queries too). The problem is that since the firebase query runs async, the results from the local database query are returned before the firebase query finishes.
How can I make the returned local database query wait until the firebase query finished?

  1. @PostMapping(&quot;/firebase-download&quot;)
  2. @ResponseBody
  3. public List&lt;FirebaseTransactionRecord&gt; firebaseDownload() {
  4. firebaseService.downloadAndSaveFirebaseTransactions();
  5. // wait for the query to end
  6. return firebaseTransactionRecordRepository.findBySentFalse();
  7. }
  1. @Override
  2. @Transactional
  3. public void downloadAndSaveFirebaseTransactions() {
  4. final List&lt;FirebaseTransactionRecord&gt; firebaseTransactions = new ArrayList&lt;&gt;();
  5. firebaseDb.child(StringValueConstant.DB_CHILD_TEMPORARY_TRANSACTIONS)
  6. .addValueEventListener(new ValueEventListener() {
  7. @Override
  8. public void onDataChange(DataSnapshot snapshot) {
  9. for (DataSnapshot userSnapshot : snapshot.getChildren()) {
  10. userSnapshot.getChildren().forEach(transactionSnapshot -&gt; {
  11. FirebaseTransactionRecord record = firebaseTransactionMapper
  12. .toFirebaseTransactionRecord(transactionSnapshot);
  13. firebaseTransactions.add(record);
  14. });
  15. }
  16. saveFirebaseTransactionRecords(firebaseTransactions);
  17. }
  18. @Override
  19. public void onCancelled(DatabaseError error) {
  20. log.error(&quot;Error reading Firebase data:&quot;, error);
  21. }
  22. });
  23. }
  1. @Override
  2. @Transactional
  3. public void saveFirebaseTransactionRecords(List&lt;FirebaseTransactionRecord&gt; firebaseTransactions) {
  4. firebaseTransactions.forEach(firebaseTransaction -&gt; {
  5. if (!firebaseTransactionRecordRepository.existsByReferralNumber(firebaseTransaction.getReferralNumber())) {
  6. firebaseTransactionRecordRepository.save(firebaseTransaction);
  7. }
  8. });
  9. }

答案1

得分: 1

使用 CountdownLatch 应该可以解决问题。

将初始的门闩计数器设置为1(用于主监听器),然后在 onDataChange 中将其设置为子节点的数量。接下来将门闩传递给 saveFirebaseTransactionRecords,并在每个事务完成时减少计数。一旦门闩计数达到0,就可以退出 downloadAndSaveFirebaseTransactions

英文:

Something with a CountdownLatch should do the trick.

Set the initial latch counter to 1 (for the main listener), then set it to the number of child nodes in onDataChange. Next pass the latch to saveFirebaseTransactionRecords and decrease it when each transaction completes. Once the latch reaches 0, you can exit out of downloadAndSaveFirebaseTransactions

huangapple
  • 本文由 发表于 2020年8月3日 04:06:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/63220525.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定