Explorar o código

Merge remote-tracking branch 'origin/package' into package

zhangxianyu hai 1 mes
pai
achega
f4649d6107

+ 1 - 1
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/GameBackApplication.java

@@ -18,7 +18,7 @@ public class GameBackApplication {
 
     public static void main(String[] args) {
         SpringApplication.run(GameBackApplication.class, args);
-        System.out.println("腾讯广告新增监测链接注册回传(小游戏用户注册信息保存callBackUrl) (´・・)ノ(._.`)  \n" +
+        System.out.println("腾讯广告新增监测链接注册回传(监测链接接口优化-02) (´・・)ノ(._.`)  \n" +
                 " ______  __     __     \n" +
                 "/_____/\\/__/\\ /__/\\    \n" +
                 "\\:::__\\/\\ \\::\\\\:.\\ \\   \n" +

+ 5 - 0
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/controller/TencentMiniGameLogController.java

@@ -29,12 +29,16 @@ import java.util.List;
 @RequestMapping("/tencentMiniGame")
 @Api("腾讯小游戏回传")
 public class TencentMiniGameLogController {
+
     @Autowired
     private IGameTencentMiniGameUserService gameTencentMiniGameUserService;
+
     @Autowired
     private IGameTencentMiniGameOrderService gameTencentMiniGameOrderService;
+
     @Autowired
     private IGameTencentMiniGameOrderSplitLogService gameTencentMiniGameOrderSplitLogService;
+
     @Autowired
     private IGameTencentMiniGameRoleRegisterService gameTencentMiniGameRoleRegisterService;
 
@@ -111,4 +115,5 @@ public class TencentMiniGameLogController {
     public ResultVO<Boolean> tencentRoleReport(@PathVariable("ids") List<Long> ids) {
         return ResultVO.ok(gameTencentMiniGameRoleRegisterService.doReport(ids));
     }
+
 }

+ 5 - 3
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/controller/api/TencentCallbackApi.java

@@ -1,7 +1,6 @@
 package com.zanxiang.game.back.serve.controller.api;
 
 import com.zanxiang.game.back.serve.pojo.dto.GameTencentAppCallbackDTO;
-import com.zanxiang.game.back.serve.pojo.dto.GameTencentCallbackDTO;
 import com.zanxiang.game.back.serve.service.IGameTencentAppCallbackService;
 import com.zanxiang.game.back.serve.service.IGameTencentMiniGameCallbackService;
 import com.zanxiang.module.util.pojo.ResultVO;
@@ -9,8 +8,11 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
+import java.util.Map;
+
 /**
  * 腾讯监测链接
  */
@@ -44,7 +46,7 @@ public class TencentCallbackApi {
     // &processTime=__PROCESS_TIME__&requestId=__REQUEST_ID__&impressionId=__IMPRESSION_ID__&ip=__IP__&userAgent=__USER_AGENT__
     // &callback=__CALLBACK__&encryptedPositionId=__ENCRYPTED_POSITION_ID__&ipv6=__IPV6__&ipMd5=__IP_MD5__&ipv6Md5=__IPV6_MD5__
     @GetMapping("/miniGame/callback")
-    public ResultVO<Boolean> miniGameCallback(GameTencentCallbackDTO dto) {
-        return ResultVO.ok(gameTencentMiniGameCallbackService.callback(dto));
+    public ResultVO<Boolean> miniGameCallback(@RequestParam Map<String, Object> paramMap) {
+        return ResultVO.ok(gameTencentMiniGameCallbackService.callback(paramMap));
     }
 }

+ 2 - 1
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/rpc/impl/TencentMiniGameBackRpcImpl.java

@@ -235,7 +235,8 @@ public class TencentMiniGameBackRpcImpl implements ITencentMiniGameBackRpc {
                 .backType(BackTypeEnum.BACK_API.getBackType())
                 .build();
         //匹配回传URL
-        String callBackUrl = gameTencentMiniGameCallbackService.getCallBackUrl(dto.getWechatOpenid(), dto.getClickId());
+        String callBackUrl = gameTencentMiniGameCallbackService.getCallBackUrl(dto.getGameId(), dto.getWechatOpenid(),
+                dto.getClickId(), dto.getRegisterTime(), true);
         if (Strings.isNotBlank(callBackUrl)) {
             userLog.setCallBackUrl(callBackUrl);
         }

+ 6 - 1
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/IGameTencentMiniGameCallbackService.java

@@ -4,9 +4,14 @@ import com.baomidou.mybatisplus.extension.service.IService;
 import com.zanxiang.game.back.serve.pojo.dto.GameTencentCallbackDTO;
 import com.zanxiang.game.back.serve.pojo.entity.GameTencentMiniGameCallback;
 
+import java.time.LocalDateTime;
+import java.util.Map;
+
 public interface IGameTencentMiniGameCallbackService extends IService<GameTencentMiniGameCallback> {
 
     boolean callback(GameTencentCallbackDTO dto);
 
-    String getCallBackUrl(String wechatOpenid, String clickId);
+    boolean callback(Map<String, Object> paramMap);
+
+    String getCallBackUrl(Long gameId, String wechatOpenid, String clickId, LocalDateTime registerTime, boolean matchTime);
 }

+ 28 - 34
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameTencentMiniGameBackLogServiceImpl.java

@@ -1,12 +1,14 @@
 package com.zanxiang.game.back.serve.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.github.sd4324530.jtuple.Tuple2;
 import com.zanxiang.game.back.base.pojo.enums.OrderStatusEnum;
 import com.zanxiang.game.back.serve.dao.mapper.GameTencentMiniGameBackLogMapper;
-import com.zanxiang.game.back.serve.pojo.entity.*;
+import com.zanxiang.game.back.serve.pojo.entity.GameTencentMiniGameBackLog;
+import com.zanxiang.game.back.serve.pojo.entity.GameTencentMiniGameOrder;
+import com.zanxiang.game.back.serve.pojo.entity.GameTencentMiniGameRoleRegister;
+import com.zanxiang.game.back.serve.pojo.entity.GameTencentMiniGameUser;
 import com.zanxiang.game.back.serve.pojo.enums.ActionTypeEnum;
 import com.zanxiang.game.back.serve.pojo.enums.BackStatusEnum;
 import com.zanxiang.game.back.serve.pojo.enums.BackTypeEnum;
@@ -15,7 +17,6 @@ import com.zanxiang.game.back.serve.service.IGameTencentMiniGameCallbackService;
 import com.zanxiang.game.back.serve.service.IGameTencentMiniGameUserService;
 import com.zanxiang.module.util.DateUtil;
 import com.zanxiang.module.util.JsonUtil;
-import com.zanxiang.module.util.URIUtil;
 import lombok.AllArgsConstructor;
 import lombok.Builder;
 import lombok.Data;
@@ -179,7 +180,11 @@ public class GameTencentMiniGameBackLogServiceImpl extends ServiceImpl<GameTence
                 .build();
         try {
             log.error("腾讯小游戏回传参数:{}", JsonUtil.toString(request));
-            ResponseEntity<Map> response = restTemplate.postForEntity(this.getCallBackUrl(backLog), request, Map.class);
+            String callBackUrl = this.getCallBackUrl(backLog);
+            if (Strings.isBlank(callBackUrl)) {
+                return Tuple2.with(BackStatusEnum.FAILED, "监测链接未匹配到callBackUrl");
+            }
+            ResponseEntity<Map> response = restTemplate.postForEntity(callBackUrl, request, Map.class);
             log.error("腾讯小游戏回传完成:{}", JsonUtil.toString(response.getBody()));
             if (response.getStatusCode().is2xxSuccessful()) {
                 if (Objects.equals(response.getBody().get("code").toString(), "0")) {
@@ -194,40 +199,29 @@ public class GameTencentMiniGameBackLogServiceImpl extends ServiceImpl<GameTence
     }
 
     private String getCallBackUrl(GameTencentMiniGameBackLog backLog) {
-        GameTencentMiniGameUser user = gameTencentMiniGameUserService.getOne(new LambdaQueryWrapper<GameTencentMiniGameUser>()
-                .eq(GameTencentMiniGameUser::getGameId, backLog.getGameId())
-                .eq(GameTencentMiniGameUser::getWechatAppId, backLog.getWechatAppId())
-                .eq(GameTencentMiniGameUser::getWechatOpenid, backLog.getWechatOpenid())
-                .eq(GameTencentMiniGameUser::getAdAccountId, backLog.getAdAccountId())
-                .eq(GameTencentMiniGameUser::getBackType, BackTypeEnum.BACK_API.getBackType())
-                .orderByDesc(GameTencentMiniGameUser::getCreateTime)
-                .last("limit 1"));
-        String callBackUrl = Optional.ofNullable(user)
+        GameTencentMiniGameUser gameTencentMiniGameUser = gameTencentMiniGameUserService.getOne(
+                new LambdaQueryWrapper<GameTencentMiniGameUser>()
+                        .eq(GameTencentMiniGameUser::getGameId, backLog.getGameId())
+                        .eq(GameTencentMiniGameUser::getWechatAppId, backLog.getWechatAppId())
+                        .eq(GameTencentMiniGameUser::getWechatOpenid, backLog.getWechatOpenid())
+                        .eq(GameTencentMiniGameUser::getAdAccountId, backLog.getAdAccountId())
+                        .eq(GameTencentMiniGameUser::getBackType, BackTypeEnum.BACK_API.getBackType())
+                        .orderByDesc(GameTencentMiniGameUser::getCreateTime)
+                        .last("limit 1"));
+        String callBackUrl = Optional.ofNullable(gameTencentMiniGameUser)
                 .map(GameTencentMiniGameUser::getCallBackUrl)
                 .orElse(null);
-        if (Strings.isNotBlank(callBackUrl)) {
+        if (Strings.isNotBlank(callBackUrl) || gameTencentMiniGameUser == null) {
             return callBackUrl;
         }
-        GameTencentMiniGameCallback tencentMiniGameCallback = gameTencentMiniGameCallbackService.getOne(
-                new LambdaQueryWrapper<GameTencentMiniGameCallback>()
-                        .eq(GameTencentMiniGameCallback::getWechatOpenid, backLog.getWechatOpenid())
-                        .and(qw -> qw.eq(GameTencentMiniGameCallback::getImpressionId, backLog.getClickId())
-                                .or().eq(GameTencentMiniGameCallback::getRequestId, backLog.getClickId())
-                        )
-                        .orderByDesc(GameTencentMiniGameCallback::getClickTime)
-                        .last("limit 1"));
-        String callBack = Optional.ofNullable(tencentMiniGameCallback)
-                .map(GameTencentMiniGameCallback::getCallback)
-                .orElse(null);
-        if (Strings.isBlank(callBack)) {
-            return "http://tracking.e.qq.com/conv";
-        }
-        callBackUrl = URIUtil.decodeURIComponent(callBack);
-        if (user != null) {
-            gameTencentMiniGameUserService.update(new LambdaUpdateWrapper<GameTencentMiniGameUser>()
-                    .set(GameTencentMiniGameUser::getCallBackUrl, callBackUrl)
-                    .eq(GameTencentMiniGameUser::getId, user.getId())
-            );
+        //再次查询回传URL, 抛开时间限制条件, 腾讯坑爹监测数据有可能延迟
+        callBackUrl = gameTencentMiniGameCallbackService.getCallBackUrl(gameTencentMiniGameUser.getGameId(),
+                gameTencentMiniGameUser.getWechatOpenid(), gameTencentMiniGameUser.getClickId(),
+                gameTencentMiniGameUser.getRegisterTime(), false);
+        //回传url更新到用户信息中
+        if (Strings.isNotBlank(callBackUrl)) {
+            gameTencentMiniGameUser.setCallBackUrl(callBackUrl);
+            gameTencentMiniGameUserService.updateById(gameTencentMiniGameUser);
         }
         return callBackUrl;
     }

+ 65 - 5
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameTencentMiniGameCallbackServiceImpl.java

@@ -2,6 +2,8 @@ package com.zanxiang.game.back.serve.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zanxiang.erp.base.ErpServer;
+import com.zanxiang.erp.base.rpc.IDingTalkMsgRpc;
 import com.zanxiang.game.back.serve.dao.mapper.GameTencentMiniGameCallbackMapper;
 import com.zanxiang.game.back.serve.pojo.dto.GameTencentCallbackDTO;
 import com.zanxiang.game.back.serve.pojo.entity.GameTencentMiniGameCallback;
@@ -23,6 +25,8 @@ import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 
 import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.Map;
 import java.util.Optional;
 
 @Slf4j
@@ -36,6 +40,9 @@ public class GameTencentMiniGameCallbackServiceImpl extends ServiceImpl<GameTenc
     @DubboReference(providedBy = ServerInfo.SERVER_DUBBO_NAME)
     private IAgentRpc agentRpc;
 
+    @DubboReference(providedBy = ErpServer.SERVER_DUBBO_NAME)
+    private IDingTalkMsgRpc dingTalkMsgRpc;
+
     @Autowired
     private KafkaProducer<String, String> kafkaProducer;
 
@@ -66,28 +73,81 @@ public class GameTencentMiniGameCallbackServiceImpl extends ServiceImpl<GameTenc
     }
 
     @Override
-    public String getCallBackUrl(String wechatOpenid, String clickId) {
+    public boolean callback(Map<String, Object> paramMap) {
+        GameTencentMiniGameCallback callback = null;
         try {
+            callback = JsonUtil.toObj(JsonUtil.toString(paramMap), GameTencentMiniGameCallback.class);
+            AgentRpcVO agent = agentRpc.getByTencentAccountId(callback.getAccountId()).getData();
+            if (agent != null) {
+                callback.setAgentKey(agent.getAgentKey());
+                callback.setGameId(agent.getGameId());
+                callback.setWechatAppId(agent.getAppId());
+            } else {
+                callback.setAgentKey("-");
+                callback.setGameId(-1L);
+                log.error("腾讯检测链接数据找不到渠道, callback :{}, paramMap : {}", JsonUtil.toString(callback), JsonUtil.toString(paramMap));
+            }
+            callback.setDay(callback.getClickTime() == null || callback.getClickTime() < 1000 ? LocalDate.now() : DateUtil.secondToLocalDate(callback.getClickTime()));
+            save(callback);
+        } catch (Exception e) {
+            log.error("接收到腾讯监测链接数据保存异常, paramMap : {}, errorMsg : {}", JsonUtil.toString(paramMap), e.getMessage(), e);
+            //发送钉钉消息通知开发
+            dingTalkMsgRpc.sendByUserId(220L, DateUtil.formatLocalDateTime(LocalDateTime.now()) + " : 腾讯小游戏监测链接数据入库异常");
+        }
+        if (callback != null) {
+            try {
+                kafkaProducer.send(new ProducerRecord<>(tencentCallbackTopic, callback.getAccountId().toString(), JsonUtil.toString(callback)));
+            } catch (Exception e) {
+                log.error(e.getMessage(), e);
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public String getCallBackUrl(Long gameId, String wechatOpenid, String clickId, LocalDateTime registerTime, boolean matchTime) {
+        try {
+            //1. 精准匹配, openId 必须匹配, requestId, clickId, impressionId, 有一个匹配上即可
             GameTencentMiniGameCallback tencentMiniGameCallback = super.getOne(
                     new LambdaQueryWrapper<GameTencentMiniGameCallback>()
+                            .eq(GameTencentMiniGameCallback::getGameId, gameId)
                             .eq(GameTencentMiniGameCallback::getWechatOpenid, wechatOpenid)
                             .and(qw -> qw.eq(GameTencentMiniGameCallback::getImpressionId, clickId)
                                     .or().eq(GameTencentMiniGameCallback::getRequestId, clickId)
-                                    .or().eq(GameTencentMiniGameCallback::getClickId, clickId)
-                            )
+                                    .or().eq(GameTencentMiniGameCallback::getClickId, clickId))
                             .orderByDesc(GameTencentMiniGameCallback::getClickTime)
                             .last("limit 1"));
+            //2. 模糊匹配, 分别使用 requestId, clickId, impressionId 匹配, 有一个匹配上即可, 加上注册时间距离最近条件
+            if (tencentMiniGameCallback == null) {
+                tencentMiniGameCallback = super.getOne(new LambdaQueryWrapper<GameTencentMiniGameCallback>()
+                        .eq(GameTencentMiniGameCallback::getGameId, gameId)
+                        .and(qw -> qw.eq(GameTencentMiniGameCallback::getImpressionId, clickId)
+                                .or().eq(GameTencentMiniGameCallback::getRequestId, clickId)
+                                .or().eq(GameTencentMiniGameCallback::getClickId, clickId))
+                        .le(matchTime, GameTencentMiniGameCallback::getClickTime, DateUtil.localDateTimeToSecond(registerTime))
+                        .orderByDesc(GameTencentMiniGameCallback::getClickTime)
+                        .last("limit 1"));
+            }
+            //3. 兜底逻辑, 只用openId匹配
+            if (tencentMiniGameCallback == null) {
+                tencentMiniGameCallback = super.getOne(new LambdaQueryWrapper<GameTencentMiniGameCallback>()
+                        .eq(GameTencentMiniGameCallback::getGameId, gameId)
+                        .eq(GameTencentMiniGameCallback::getWechatOpenid, wechatOpenid)
+                        .orderByDesc(GameTencentMiniGameCallback::getClickTime)
+                        .last("limit 1"));
+            }
+            //判断监测链接数据
             String callBack = Optional.ofNullable(tencentMiniGameCallback)
                     .map(GameTencentMiniGameCallback::getCallback)
                     .orElse(null);
             if (Strings.isBlank(callBack)) {
-                log.error("匹配监测链接为空, wechatOpenid : {}, clickId : {}", wechatOpenid, clickId);
+                log.error("匹配监测链接为空, gameId : {}, wechatOpenid : {}, clickId : {}", gameId, wechatOpenid, clickId);
                 return null;
             }
             //返回匹配回传地址
             return URIUtil.decodeURIComponent(callBack);
         } catch (Exception e) {
-            log.error("匹配监测链接异常, wechatOpenid : {}, clickId : {}", wechatOpenid, clickId);
+            log.error("匹配监测链接异常, gameId : {}, wechatOpenid : {}, clickId : {}", gameId, wechatOpenid, clickId);
         }
         return null;
     }

+ 20 - 12
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameTencentMiniGameRoleRegisterServiceImpl.java

@@ -159,16 +159,8 @@ public class GameTencentMiniGameRoleRegisterServiceImpl extends ServiceImpl<Game
         GameBackPolicy gameBackPolicy = roleRegisterLog.getBackPolicyId() == null ? null
                 : gameBackPolicyService.getById(roleRegisterLog.getBackPolicyId());
 
-        //判断创角是否回传
-        if (gameTencentMiniGameBackLogService.count(new LambdaQueryWrapper<GameTencentMiniGameBackLog>()
-                .eq(GameTencentMiniGameBackLog::getGameId, roleRegisterLog.getGameId())
-                .eq(GameTencentMiniGameBackLog::getWechatAppId, roleRegisterLog.getWechatAppId())
-                .eq(GameTencentMiniGameBackLog::getWechatOpenid, roleRegisterLog.getWechatOpenid())
-                .eq(GameTencentMiniGameBackLog::getAdAccountId, roleRegisterLog.getAdAccountId())
-                .eq(GameTencentMiniGameBackLog::getActionType, ActionTypeEnum.CREATE_ROLE.getActionType())
-                .eq(GameTencentMiniGameBackLog::getBackStatus, BackStatusEnum.SUCCESS.getBackStatus())
-                .eq(GameTencentMiniGameBackLog::getBackType, BackTypeEnum.BACK_API.getBackType())
-        ) > 0) {
+        //判断创角是否已成功回传
+        if (this.roleBackCheck(roleRegisterLog)) {
             //新手引导回传
             this.tutorialFinishBack(roleRegisterLog, gameBackPolicy);
             //创角已回传
@@ -181,16 +173,32 @@ public class GameTencentMiniGameRoleRegisterServiceImpl extends ServiceImpl<Game
             return Tuple2.with(BackStatusEnum.NO, "等级小于回传策略等级 " + gameBackPolicy.getRoleLevelMin() + "。不回传");
         }
 
-        //判断注册是否回传
-        if (user != null && Objects.equals(BackStatusEnum.NO.getBackStatus(), user.getBackStatus())) {
+        //判断注册是否成功回传
+        if (user != null && !Objects.equals(BackStatusEnum.SUCCESS.getBackStatus(), user.getBackStatus())) {
             //执行注册回传
             gameTencentMiniGameUserService.userBack(user);
+            //判断注册回传的时候是否合并了创角回传, 如果已经回传成功, 则不再回传
+            if (this.roleBackCheck(roleRegisterLog)) {
+                return Tuple2.with(BackStatusEnum.SUCCESS, "注册回传同步回传创角成功");
+            }
         }
 
         //创角回传
         return gameTencentMiniGameBackLogService.roleRegisterBack(roleRegisterLog);
     }
 
+    private boolean roleBackCheck(GameTencentMiniGameRoleRegister roleRegisterLog) {
+        return gameTencentMiniGameBackLogService.count(new LambdaQueryWrapper<GameTencentMiniGameBackLog>()
+                .eq(GameTencentMiniGameBackLog::getGameId, roleRegisterLog.getGameId())
+                .eq(GameTencentMiniGameBackLog::getWechatAppId, roleRegisterLog.getWechatAppId())
+                .eq(GameTencentMiniGameBackLog::getWechatOpenid, roleRegisterLog.getWechatOpenid())
+                .eq(GameTencentMiniGameBackLog::getAdAccountId, roleRegisterLog.getAdAccountId())
+                .eq(GameTencentMiniGameBackLog::getActionType, ActionTypeEnum.CREATE_ROLE.getActionType())
+                .eq(GameTencentMiniGameBackLog::getBackStatus, BackStatusEnum.SUCCESS.getBackStatus())
+                .eq(GameTencentMiniGameBackLog::getBackType, BackTypeEnum.BACK_API.getBackType())
+        ) > 0;
+    }
+
     @Override
     public void tutorialFinishBack(GameTencentMiniGameRoleRegister roleRegisterLog, GameBackPolicy gameBackPolicy) {
         //角色判断完成新手引导回传

+ 5 - 4
game-back/game-back-serve/src/main/java/com/zanxiang/game/back/serve/service/impl/GameTencentMiniGameUserServiceImpl.java

@@ -45,16 +45,17 @@ import java.util.stream.Collectors;
 public class GameTencentMiniGameUserServiceImpl extends ServiceImpl<GameTencentMiniGameUserMapper, GameTencentMiniGameUser>
         implements IGameTencentMiniGameUserService {
 
+    @DubboReference(providedBy = ServerInfo.SERVER_DUBBO_NAME)
+    private IAgentRpc agentRpc;
+
     @DubboReference(providedBy = AdvertisingTencentServer.SERVER_DUBBO_NAME)
     private IUserActionSetRpc userActionSetRpc;
+
     @Autowired
     private IGameTencentMiniGameBackLogService gameTencentMiniGameBackLogService;
-    @Autowired
-    private IDistributedLockComponent distributedLockComponent;
+
     @Autowired
     private IGameBackPolicyService gameBackPolicyService;
-    @DubboReference(providedBy = ServerInfo.SERVER_DUBBO_NAME)
-    private IAgentRpc agentRpc;
 
     @Override
     @Transactional(rollbackFor = Exception.class)