yumeng hai 3 semanas
pai
achega
dcf30cd1d6

+ 1 - 1
nj_job-bytedance/src/main/java/cn/com/ctop/job/bytedance/data/mapper/AdminAdvertiserListMapper.java

@@ -10,7 +10,7 @@ import java.util.List;
 public interface AdminAdvertiserListMapper {
     void replaceBytedanceAdvertiserLists(@Param("adds") List<BytedanceAdvertiserList> advertiserLists);
 
-    void deleteNotInAdvertiserList(@Param("adminAdvertiserId") Long adminAdvertiserId, @Param("ids") List<Long> ids);
+    int deleteNotInAdvertiserList(@Param("adminAdvertiserId") Long adminAdvertiserId, @Param("ids") List<Long> ids);
 
     List<JSONObject> getAdvertiserInfos();
 

+ 33 - 4
nj_job-bytedance/src/main/java/cn/com/ctop/job/bytedance/data/service/impl/AdminAdvertiserListServiceImpl.java

@@ -28,6 +28,7 @@ public class AdminAdvertiserListServiceImpl implements IAdminAdvertiserListServi
 
     @Override
     public JSONObject bytedanceAdvertiserSync(Long adminAdvertiserId, String accessToken) {
+        long syncStart = System.currentTimeMillis();
         JSONObject returnJson = new JSONObject();
         // 1. 拉授权主体列表,确定要展开的组织集合(与字节授权回调同口径)
         JSONObject authResult = getBytedanceAuthAdvertisers(accessToken);
@@ -52,14 +53,16 @@ public class AdminAdvertiserListServiceImpl implements IAdminAdvertiserListServi
         List<Long> customerAccounts = authResult.getJSONArray("customerAccounts").toJavaList(Long.class);
         List<BytedanceAdvertiserList> normalAccounts = authResult.getJSONArray("normalAccounts")
                 .toJavaList(BytedanceAdvertiserList.class);
-        log.info("授权主体下纵横管家/操作员数:{},NORMAL投放主体数:{},adminAdvertiserId:{}",
-                customerAccounts.size(), normalAccounts.size(), adminAdvertiserId);
+        log.info("授权主体下纵横管家/操作员:{},NORMAL投放主体数:{},归属管家:{}",
+                customerAccounts, normalAccounts.size(), adminAdvertiserId);
 
         // 2. 串行拉各组织第 1 页确定总页数(每组织仅 1 次请求,代价可忽略)
         int pageSize = 100;
+        long phaseStart = System.currentTimeMillis();
         List<CcOrgFetchPlan> plans = new ArrayList<>();
         boolean allSuccess = true;
         for (Long ccAccountId : customerAccounts) {
+            long orgFirstPageStart = System.currentTimeMillis();
             CcPageResult firstPage = fetchCcAdvertiserPageWithRetry(adminAdvertiserId, ccAccountId, accessToken, 1, pageSize);
             if (firstPage == null) {
                 // 组织首页拉取失败时账户集合不完整,本次不做失效清理,避免误删
@@ -68,9 +71,13 @@ public class AdminAdvertiserListServiceImpl implements IAdminAdvertiserListServi
                 continue;
             }
             plans.add(new CcOrgFetchPlan(ccAccountId, Math.max(firstPage.getTotalPage(), 1), firstPage.getIds()));
+            log.info("字节任务-组织首页拉取耗时={}ms, ccAccountId={}, totalPage={}, 账户数={}",
+                    System.currentTimeMillis() - orgFirstPageStart, ccAccountId, firstPage.getTotalPage(), firstPage.getIds().size());
         }
+        log.info("字节任务-组织首页阶段总耗时={}ms, 组织数={}", System.currentTimeMillis() - phaseStart, plans.size());
 
         // 3. 全部组织的其余分页提交线程池并行拉取
+        phaseStart = System.currentTimeMillis();
         ExecutorService executor = Executors.newFixedThreadPool(10);
         List<Future<CcPageResult>> futures = new ArrayList<>();
         for (CcOrgFetchPlan plan : plans) {
@@ -80,32 +87,43 @@ public class AdminAdvertiserListServiceImpl implements IAdminAdvertiserListServi
             }
         }
         Map<Long, Map<Integer, List<Long>>> idsByOrgPage = new HashMap<>();
+        int successPages = 0;
+        int failedPages = 0;
         for (Future<CcPageResult> future : futures) {
             try {
                 CcPageResult result = future.get();
                 if (result == null || result.getIds() == null) {
                     allSuccess = false;
+                    failedPages++;
                     continue;
                 }
+                successPages++;
                 idsByOrgPage.computeIfAbsent(result.getCcAccountId(), key -> new HashMap<>()).put(result.getPageNumber(), result.getIds());
             } catch (InterruptedException | ExecutionException e) {
                 allSuccess = false;
+                failedPages++;
                 log.error("多线程请求字节纵横组织账户失败: {}", e.getMessage());
             }
         }
         executor.shutdown();
+        log.info("字节任务-并行分页阶段耗时={}ms, 提交页数={}, 成功页数={}, 失败页数={}",
+                System.currentTimeMillis() - phaseStart, futures.size(), successPages, failedPages);
 
         // 4. 按组织顺序、页序合并,多组织账户取并集
+        long mergeStart = System.currentTimeMillis();
         Set<Long> mergedIds = new LinkedHashSet<>();
         for (CcOrgFetchPlan plan : plans) {
+            int orgAccountCount = plan.getFirstPageIds().size();
             mergedIds.addAll(plan.getFirstPageIds());
             Map<Integer, List<Long>> orgPages = idsByOrgPage.getOrDefault(plan.getCcAccountId(), Collections.emptyMap());
             for (int page = 2; page <= plan.getTotalPage(); page++) {
                 List<Long> ids = orgPages.get(page);
                 if (ids != null) {
+                    orgAccountCount += ids.size();
                     mergedIds.addAll(ids);
                 }
             }
+            log.info("字节任务-组织账户合并:ccAccountId={}, 账户数={}", plan.getCcAccountId(), orgAccountCount);
         }
         // 授权主体自身的NORMAL投放账户并入(与字节授权回调同口径:自营企业号也是投放主体)
         for (BytedanceAdvertiserList normalAccount : normalAccounts) {
@@ -113,17 +131,25 @@ public class AdminAdvertiserListServiceImpl implements IAdminAdvertiserListServi
         }
         if (!normalAccounts.isEmpty()) {
             adminAdvertiserListMapper.replaceBytedanceAdvertiserLists(normalAccounts);
+            log.info("字节任务-NORMAL自营主体写入:{}条", normalAccounts.size());
         }
+        log.info("字节任务-分页结果合并耗时={}ms, 多组织并集账户数={}", System.currentTimeMillis() - mergeStart, mergedIds.size());
 
         // 5. 全量同步:所有组织分页均拉取成功才清理存量;任一分页失败则跳过,防止误删
+        int deletedCount = 0;
         if (allSuccess) {
+            long deleteStart = System.currentTimeMillis();
             if (mergedIds.isEmpty()) {
                 // 全部组织确认已无账户,按全量同步语义清空该管家存量账户
-                adminAdvertiserListMapper.deleteNotInAdvertiserList(adminAdvertiserId, null);
+                deletedCount = adminAdvertiserListMapper.deleteNotInAdvertiserList(adminAdvertiserId, null);
+                log.info("字节任务-全部组织已无账户,清空该管家存量账户:{}条, 耗时={}ms", deletedCount, System.currentTimeMillis() - deleteStart);
             } else {
-                adminAdvertiserListMapper.deleteNotInAdvertiserList(adminAdvertiserId, new ArrayList<>(mergedIds));
+                deletedCount = adminAdvertiserListMapper.deleteNotInAdvertiserList(adminAdvertiserId, new ArrayList<>(mergedIds));
+                log.info("字节任务-存量过期账户清理:{}条, 耗时={}ms", deletedCount, System.currentTimeMillis() - deleteStart);
             }
         }
+        log.info("字节任务-全量同步总耗时={}ms, adminAdvertiserId={}, 并集账户数={}, 清理过期账户数={}",
+                System.currentTimeMillis() - syncStart, adminAdvertiserId, mergedIds.size(), deletedCount);
         returnJson.put("code", allSuccess ? 200 : 500);
         returnJson.put("total", mergedIds.size());
         returnJson.put("message", allSuccess ? "全量同步成功,已同步删除过期账户" : "存在拉取失败分页,跳过本次存量账户清理");
@@ -213,6 +239,7 @@ public class AdminAdvertiserListServiceImpl implements IAdminAdvertiserListServi
      * 拉取纵横组织单页(account_source=AD,与字节授权回调同口径),成功分页结果入库并返回,失败返回 null
      */
     private CcPageResult fetchCcAdvertiserPage(Long adminAdvertiserId, Long ccAccountId, String accessToken, int page, int pageSize) {
+        long requestStart = System.currentTimeMillis();
         try {
             Thread.sleep(100L);
         } catch (InterruptedException e) {
@@ -258,6 +285,8 @@ public class AdminAdvertiserListServiceImpl implements IAdminAdvertiserListServi
         if (!advertiserLists.isEmpty()) {
             adminAdvertiserListMapper.replaceBytedanceAdvertiserLists(advertiserLists);
         }
+        log.info("字节任务-分页请求耗时={}ms, ccAccountId={}, page={}, 账户数={}",
+                System.currentTimeMillis() - requestStart, ccAccountId, page, advertiserLists.size());
         List<Long> ids = new ArrayList<>();
         for (BytedanceAdvertiserList advertiserList : advertiserLists) {
             ids.add(advertiserList.getAdvertiserId());