@Override public void run() { try { LOG.info("Retry connecting to alpha at {}", messageSender.target()); messageSender.onDisconnected(); messageSender.onConnected(); senders.put(messageSender, 0L); connectedSenders.offer(messageSender); LOG.info("Retry connecting to alpha at {} is successful", messageSender.target()); } catch (Exception e) { LOG.error("Failed to reconnect to alpha at {}", messageSender.target(), e); pendingTasks.offer(this); } } }
@Override public void onConnected() { senders.keySet().forEach(sender -> { try { sender.onConnected(); } catch (Exception e) { LOG.error("Failed connecting to alpha at {}", sender.target(), e); } }); }
@Override public void onDisconnected() { senders.keySet().forEach(sender -> { try { sender.onDisconnected(); } catch (Exception e) { LOG.error("Failed disconnecting from alpha at {}", sender.target(), e); } }); }
@Override public AlphaResponse send(TxEvent event) { do { MessageSender messageSender = fastestSender(); try { long startTime = System.nanoTime(); AlphaResponse response = messageSender.send(event); senders.put(messageSender, System.nanoTime() - startTime); return response; } catch (OmegaException e) { throw e; } catch (Exception e) { LOG.error("Retry sending event {} due to failure", event, e); // very large latency on exception senders.put(messageSender, Long.MAX_VALUE); } } while (!Thread.currentThread().isInterrupted()); throw new OmegaException("Failed to send event " + event + " due to interruption"); }
@Override public void onError(String parentTxId, String compensationMethod, Throwable throwable) { String globalTxId = omegaContext.globalTxId(); sender.send(new TxAbortedEvent(globalTxId, globalTxId, null, compensationMethod, throwable)); } }
@Override public void onReceive(String globalTxId, String localTxId, String parentTxId, String compensationMethod, Object... payloads) { context.apply(globalTxId, localTxId, compensationMethod, payloads); sender.send(new TxCompensatedEvent(globalTxId, localTxId, parentTxId, compensationMethod)); } }
@Override public AlphaResponse send(TxEvent event) { if (event.type() == SagaStartedEvent) { throw new OmegaException("Failed to process subsequent requests because no alpha server is available"); } try { return availableMessageSenders.take().send(event); } catch (InterruptedException e) { throw new OmegaException("Failed to send event " + event + " due to interruption", e); } } }
@Override public void onError(String parentTxId, String compensationMethod, Throwable throwable) { sender.send( new TxAbortedEvent(context.globalTxId(), context.localTxId(), parentTxId, compensationMethod, throwable)); } }
@Override public AlphaResponse preIntercept(String parentTxId, String compensationMethod, int timeout, String retriesMethod, int retries, Object... message) { return sender.send(new TxStartedEvent(context.globalTxId(), context.localTxId(), parentTxId, compensationMethod, timeout, retriesMethod, retries, message)); }
@Override public void postIntercept(String parentTxId, String compensationMethod) { sender.send(new TxEndedEvent(context.globalTxId(), context.localTxId(), parentTxId, compensationMethod)); }
@Override public void postIntercept(String parentTxId, String compensationMethod) { AlphaResponse response = sender.send(new SagaEndedEvent(omegaContext.globalTxId(), omegaContext.localTxId())); if (response.aborted()) { throw new OmegaException("transaction " + parentTxId + " is aborted"); } }
@Override public AlphaResponse preIntercept(String parentTxId, String compensationMethod, int timeout, String retriesMethod, int retries, Object... message) { try { return sender.send(new SagaStartedEvent(omegaContext.globalTxId(), omegaContext.localTxId(), timeout)); } catch (OmegaException e) { throw new TransactionalException(e.getMessage(), e.getCause()); } }