我将使用记录的
Google My Business Business Information API
检索所有帐户的所有位置 Google Business Profile APIs。
我尝试编写下面的代码的简化版本:
假设 mybusinessaccountLocations
变量是以下函数的返回类型,并负责身份验证和初始化 API。
我的业务业务信息 mybusinessaccountLocations = 初始化我的业务(主机);
我定义了一个名为 accountRecord 和 locationRecord 的类来管理数据库中的相关表。
ExecutorService ex = Executors.newFixedThreadPool(10);
for (accountRecord rec : accountsList) {
List<locationRecord> LocationsList = Collections.synchronizedList(new ArrayList<>());
ex.execute(new Runnable() {
@Override
public void run() {
String readMask = "storeCode,regularHours,name,languageCode,title,phoneNumbers,categories,storefrontAddress,websiteUri,regularHours,specialHours,serviceArea,labels,adWordsLocationExtensions,latlng,openInfo,metadata,profile,relationshipData,moreHours";
List<Location> locations = Collections.synchronizedList(new ArrayList<>());
String accountName = rec.getName();
try {
MyBusinessBusinessInformation.Accounts.Locations.List locationsList = mybusinessaccountLocations
.accounts().locations().list(accountName).setReadMask(readMask);
ListLocationsResponse Response = locationsList.execute();
locations = Response.getLocations();
System.out.println("Response Size ="+ Response.size());
while (Response.getNextPageToken() != null && Response != null && !Response.isEmpty()) {
locationsList.setPageToken(Response.getNextPageToken());
Response = locationsList.execute();
if (Response != null && Response.getLocations() != null) {
locations.addAll(Response.getLocations());
}
}
}
catch (Throwable t) {
throw new RuntimeException("\n\n Throwable occurred: " + t.getMessage(), t);
}
if (locations != null && !locations.isEmpty()) {
// processing the locations and saving in DB
.
.
.
}
}
});
}
ex.shutdown();
while (!ex.isTerminated()) {
}
由于我使用的是
ExecutorService
,有时会超出google定义的time_limit(Quota),或者存在服务器端错误,例如
{
"code" : 503,
"errors" : [ {
"domain" : "global",
"message" : "The service is currently unavailable.",
"reason" : "backendError"
} ],
"message" : "The service is currently unavailable.",
"status" : "UNAVAILABLE"
}
我需要代码等待几毫秒,直到不再出现此类错误,然后重试确切的请求,而不跳过任何分页或帐户。 我尝试使用
AtomicInteger
synchronized(i) {
if( i.getAndIncrement() >= 50 ) {
Thread.sleep(20000);
i.set(0);
}
}
但是,这不是一个非常有效的方法,我听说指数退避会更有效,但我不知道如何实现。我将不胜感激任何帮助。
已经存在 RateLimiter 实现 (https://guava.dev/releases/19.0/api/docs/index.html?com/google/common/util/concurrent/RateLimiter.html)。 至于重试/退避逻辑,如果您可以重用现有的实现,可能取决于您的框架(例如https://www.baeldung.com/spring-retry)。