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

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

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.

@PostMapping("/firebase-download")
@ResponseBody
public List<FirebaseTransactionRecord> firebaseDownload() {
    
    firebaseService.downloadAndSaveFirebaseTransactions();
    // wait for the query to end
    return firebaseTransactionRecordRepository.findBySentFalse();
}    
@Override
@Transactional
public void downloadAndSaveFirebaseTransactions() {

    final List<FirebaseTransactionRecord> firebaseTransactions = new ArrayList<>();

    firebaseDb.child(StringValueConstant.DB_CHILD_TEMPORARY_TRANSACTIONS)
            .addValueEventListener(new ValueEventListener() {

                @Override
                public void onDataChange(DataSnapshot snapshot) {

                    for (DataSnapshot userSnapshot : snapshot.getChildren()) {
                        userSnapshot.getChildren().forEach(transactionSnapshot -> {
                            FirebaseTransactionRecord record = firebaseTransactionMapper
                                    .toFirebaseTransactionRecord(transactionSnapshot);
                            firebaseTransactions.add(record);
                        });
                    }

                    saveFirebaseTransactionRecords(firebaseTransactions);
                }

                @Override
                public void onCancelled(DatabaseError error) {
                    log.error("Error reading Firebase data:", error);
                }
            });
}
@Override
@Transactional
public void saveFirebaseTransactionRecords(List<FirebaseTransactionRecord> firebaseTransactions) {
    firebaseTransactions.forEach(firebaseTransaction -> {
        if (!firebaseTransactionRecordRepository.existsByReferralNumber(firebaseTransaction.getReferralNumber())) {
            firebaseTransactionRecordRepository.save(firebaseTransaction);
        }
    });        
}    
英文:

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?

	@PostMapping(&quot;/firebase-download&quot;)
	@ResponseBody
	public List&lt;FirebaseTransactionRecord&gt; firebaseDownload() {
		
		firebaseService.downloadAndSaveFirebaseTransactions();
        // wait for the query to end
		return firebaseTransactionRecordRepository.findBySentFalse();
	}	
	@Override
	@Transactional
	public void downloadAndSaveFirebaseTransactions() {

			final List&lt;FirebaseTransactionRecord&gt; firebaseTransactions = new ArrayList&lt;&gt;();

			firebaseDb.child(StringValueConstant.DB_CHILD_TEMPORARY_TRANSACTIONS)
					.addValueEventListener(new ValueEventListener() {

						@Override
						public void onDataChange(DataSnapshot snapshot) {

							for (DataSnapshot userSnapshot : snapshot.getChildren()) {
								userSnapshot.getChildren().forEach(transactionSnapshot -&gt; {
									FirebaseTransactionRecord record = firebaseTransactionMapper
											.toFirebaseTransactionRecord(transactionSnapshot);
									firebaseTransactions.add(record);
								});
							}

							saveFirebaseTransactionRecords(firebaseTransactions);
						}

						@Override
						public void onCancelled(DatabaseError error) {
							log.error(&quot;Error reading Firebase data:&quot;, error);
						}
					});
	}
	@Override
	@Transactional
	public void saveFirebaseTransactionRecords(List&lt;FirebaseTransactionRecord&gt; firebaseTransactions) {
		firebaseTransactions.forEach(firebaseTransaction -&gt; {
			if (!firebaseTransactionRecordRepository.existsByReferralNumber(firebaseTransaction.getReferralNumber())) {
				firebaseTransactionRecordRepository.save(firebaseTransaction);
			}
		});		
	}	

答案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:

确定