public void ack(long batchId) throws CanalClientException { waitClientRunning(); ClientAck ca = ClientAck.newBuilder() .setDestination(clientIdentity.getDestination()) .setClientId(String.valueOf(clientIdentity.getClientId())) .setBatchId(batchId) .build(); try { writeWithHeader( channel, Packet.newBuilder() .setType(PacketType.CLIENTACK) .setBody(ca.toByteString()) .build() .toByteArray()); } catch (IOException e) { throw new CanalClientException(e); } }
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { logger.info("message receives in session handler..."); ChannelBuffer buffer = (ChannelBuffer) e.getMessage(); Packet packet = Packet.parseFrom(buffer.readBytes(buffer.readableBytes()).array()); ClientIdentity clientIdentity = null; try { switch (packet.getType()) { case SUBSCRIPTION: Sub sub = Sub.parseFrom(packet.getBody()); if (StringUtils.isNotEmpty(sub.getDestination()) && StringUtils.isNotEmpty(sub.getClientId())) { clientIdentity = new ClientIdentity( sub.getDestination(), Short.valueOf(sub.getClientId()), sub.getFilter()); MDC.put("destination", clientIdentity.getDestination()); embededServer.subscribe(clientIdentity); // 尝试启动,如果已经启动,忽略 if (!embededServer.isStart(clientIdentity.getDestination())) { ServerRunningMonitor runningMonitor = ServerRunningMonitors.getRunningMonitor(clientIdentity.getDestination()); if (!runningMonitor.isStart()) { runningMonitor.start(); } } ctx.setAttachment(clientIdentity); // 设置状态数据 NettyUtils.ack(ctx.getChannel(), null); } else { NettyUtils.error( 401, MessageFormatter.format("destination or clientId is null", sub.toString()) .getMessage(), ctx.getChannel(), null); } break; case UNSUBSCRIPTION: Unsub unsub = Unsub.parseFrom(packet.getBody()); if (StringUtils.isNotEmpty(unsub.getDestination()) && StringUtils.isNotEmpty(unsub.getClientId())) { clientIdentity = new ClientIdentity( unsub.getDestination(), Short.valueOf(unsub.getClientId()), unsub.getFilter()); MDC.put("destination", clientIdentity.getDestination()); embededServer.unsubscribe(clientIdentity); stopCanalInstanceIfNecessary(clientIdentity); // 尝试关闭 NettyUtils.ack(ctx.getChannel(), null); } else { NettyUtils.error( 401, MessageFormatter.format("destination or clientId is null", unsub.toString()) .getMessage(), ctx.getChannel(), null); } break; case GET: Get get = CanalPacket.Get.parseFrom(packet.getBody()); if (StringUtils.isNotEmpty(get.getDestination()) && StringUtils.isNotEmpty(get.getClientId())) { clientIdentity = new ClientIdentity(get.getDestination(), Short.valueOf(get.getClientId())); MDC.put("destination", clientIdentity.getDestination()); Message message = embededServer.getWithoutAck(clientIdentity, get.getFetchSize()); Packet.Builder packetBuilder = CanalPacket.Packet.newBuilder(); packetBuilder.setType(PacketType.MESSAGES); Messages.Builder messageBuilder = CanalPacket.Messages.newBuilder(); messageBuilder.setBatchId(message.getId()); if (message.getId() != -1 && !CollectionUtils.isEmpty(message.getEntries())) { for (Entry entry : message.getEntries()) { messageBuilder.addMessages(entry.toByteString()); } } packetBuilder.setBody(messageBuilder.build().toByteString()); NettyUtils.write(ctx.getChannel(), packetBuilder.build().toByteArray(), null); // 输出数据 } else { NettyUtils.error( 401, MessageFormatter.format("destination or clientId is null", get.toString()) .getMessage(), ctx.getChannel(), null); } break; case CLIENTACK: ClientAck ack = CanalPacket.ClientAck.parseFrom(packet.getBody()); MDC.put("destination", ack.getDestination()); if (StringUtils.isNotEmpty(ack.getDestination()) && StringUtils.isNotEmpty(ack.getClientId())) { if (ack.getBatchId() == 0L) { NettyUtils.error( 402, MessageFormatter.format("batchId should assign value", ack.toString()) .getMessage(), ctx.getChannel(), null); } else if (ack.getBatchId() == -1L) { // -1代表上一次get没有数据,直接忽略之 // donothing } else { clientIdentity = new ClientIdentity(ack.getDestination(), Short.valueOf(ack.getClientId())); embededServer.ack(clientIdentity, ack.getBatchId()); } } else { NettyUtils.error( 401, MessageFormatter.format("destination or clientId is null", ack.toString()) .getMessage(), ctx.getChannel(), null); } break; case CLIENTROLLBACK: ClientRollback rollback = CanalPacket.ClientRollback.parseFrom(packet.getBody()); MDC.put("destination", rollback.getDestination()); if (StringUtils.isNotEmpty(rollback.getDestination()) && StringUtils.isNotEmpty(rollback.getClientId())) { clientIdentity = new ClientIdentity( rollback.getDestination(), Short.valueOf(rollback.getClientId())); if (rollback.getBatchId() == 0L) { embededServer.rollback(clientIdentity); // 回滚所有批次 } else { embededServer.rollback(clientIdentity, rollback.getBatchId()); // 只回滚单个批次 } } else { NettyUtils.error( 401, MessageFormatter.format("destination or clientId is null", rollback.toString()) .getMessage(), ctx.getChannel(), null); } break; default: NettyUtils.error( 400, MessageFormatter.format("packet type={} is NOT supported!", packet.getType()) .getMessage(), ctx.getChannel(), null); break; } } catch (Throwable exception) { NettyUtils.error( 400, MessageFormatter.format( "something goes wrong with channel:{}, exception={}", ctx.getChannel(), ExceptionUtils.getStackTrace(exception)) .getMessage(), ctx.getChannel(), null); } finally { MDC.remove("destination"); } }