use of co.cask.cdap.common.service.RetryStrategy in project cdap by caskdata.
the class MessagingNotificationService method subscribe.
@Override
public <N> Cancellable subscribe(NotificationFeedId feed, NotificationHandler<N> handler, Executor executor) throws NotificationFeedNotFoundException, NotificationFeedException {
Cancellable subscribeCancellable = super.subscribe(feed, handler, executor);
// If already has a thread fetching, just return the cancellable.
if (!needFetch.compareAndSet(false, true)) {
return subscribeCancellable;
}
// Start fetching
subscribeExecutor.execute(new Runnable() {
private final long startTime = System.currentTimeMillis();
private final RetryStrategy scheduleStrategy = RetryStrategies.exponentialDelay(100, 3000, TimeUnit.MILLISECONDS);
private byte[] messageId;
private int emptyFetchCount;
@Override
public void run() {
try {
MessageFetcher fetcher = messagingService.prepareFetch(notificationTopic);
if (messageId == null) {
fetcher.setStartTime(startTime);
} else {
fetcher.setStartMessage(messageId, false);
}
emptyFetchCount++;
try (CloseableIterator<RawMessage> iterator = fetcher.fetch()) {
while (iterator.hasNext()) {
emptyFetchCount = 0;
RawMessage rawMessage = iterator.next();
NotificationMessage message = GSON.fromJson(new String(rawMessage.getPayload(), StandardCharsets.UTF_8), NotificationMessage.class);
try {
LOG.trace("Decoded notification: {}", message);
notificationReceived(message.getFeedId(), message.getNotificationJson());
} catch (Throwable t) {
LOG.warn("Error while processing notification {} with handler {}", message, t);
}
messageId = rawMessage.getId();
}
}
} catch (Exception e) {
LOG.error("Failed to get notification", e);
}
// Back-off if it was empty fetch.
if (emptyFetchCount > 0) {
// Schedule the next fetch. Exponential strategy doesn't use the time component,
// so doesn't matter what we passed in
subscribeExecutor.schedule(this, scheduleStrategy.nextRetry(emptyFetchCount, startTime), TimeUnit.MILLISECONDS);
} else {
subscribeExecutor.execute(this);
}
}
});
return subscribeCancellable;
}
use of co.cask.cdap.common.service.RetryStrategy in project cdap by caskdata.
the class ServiceProgramRunner method run.
@Override
public ProgramController run(Program program, ProgramOptions options) {
int instanceId = Integer.parseInt(options.getArguments().getOption(ProgramOptionConstants.INSTANCE_ID, "-1"));
Preconditions.checkArgument(instanceId >= 0, "Missing instance Id");
int instanceCount = Integer.parseInt(options.getArguments().getOption(ProgramOptionConstants.INSTANCES, "0"));
Preconditions.checkArgument(instanceCount > 0, "Invalid or missing instance count");
RunId runId = ProgramRunners.getRunId(options);
ApplicationSpecification appSpec = program.getApplicationSpecification();
Preconditions.checkNotNull(appSpec, "Missing application specification.");
ProgramType programType = program.getType();
Preconditions.checkNotNull(programType, "Missing processor type.");
Preconditions.checkArgument(programType == ProgramType.SERVICE, "Only Service process type is supported.");
ServiceSpecification spec = appSpec.getServices().get(program.getName());
String host = options.getArguments().getOption(ProgramOptionConstants.HOST);
Preconditions.checkArgument(host != null, "No hostname is provided");
// Setup dataset framework context, if required
if (datasetFramework instanceof ProgramContextAware) {
ProgramId programId = program.getId();
((ProgramContextAware) datasetFramework).setContext(new BasicProgramContext(programId.run(runId)));
}
final PluginInstantiator pluginInstantiator = createPluginInstantiator(options, program.getClassLoader());
try {
RetryStrategy retryStrategy = SystemArguments.getRetryStrategy(options.getUserArguments().asMap(), program.getType(), cConf);
ArtifactManager artifactManager = artifactManagerFactory.create(program.getId().getNamespaceId(), retryStrategy);
ServiceHttpServer component = new ServiceHttpServer(host, program, options, cConf, spec, instanceId, instanceCount, serviceAnnouncer, metricsCollectionService, datasetFramework, txClient, discoveryServiceClient, pluginInstantiator, secureStore, secureStoreManager, messagingService, artifactManager);
// Add a service listener to make sure the plugin instantiator is closed when the http server is finished.
component.addListener(createRuntimeServiceListener(Collections.singleton((Closeable) pluginInstantiator)), Threads.SAME_THREAD_EXECUTOR);
ProgramController controller = new ServiceProgramControllerAdapter(component, program.getId().run(runId), spec.getName() + "-" + instanceId);
component.start();
return controller;
} catch (Throwable t) {
Closeables.closeQuietly(pluginInstantiator);
throw t;
}
}
use of co.cask.cdap.common.service.RetryStrategy in project cdap by caskdata.
the class SystemArgumentsTest method testRetryStrategies.
@Test
public void testRetryStrategies() throws InterruptedException {
CConfiguration cConf = CConfiguration.create();
Map<String, String> args = Collections.emptyMap();
// Get default, expect exponential back-off behavior, until the max delay
RetryStrategy strategy = SystemArguments.getRetryStrategy(args, ProgramType.CUSTOM_ACTION, cConf);
long startTime = System.currentTimeMillis();
Assert.assertEquals(1000L, strategy.nextRetry(1, startTime));
Assert.assertEquals(2000L, strategy.nextRetry(2, startTime));
Assert.assertEquals(4000L, strategy.nextRetry(3, startTime));
Assert.assertEquals(8000L, strategy.nextRetry(4, startTime));
Assert.assertEquals(16000L, strategy.nextRetry(5, startTime));
Assert.assertEquals(30000L, strategy.nextRetry(6, startTime));
Assert.assertEquals(30000L, strategy.nextRetry(7, startTime));
// It should give up (returning -1) when exceeding the max retries
Assert.assertEquals(-1L, strategy.nextRetry(1001, startTime));
// Override the strategy type and max retry time
args = ImmutableMap.of("system." + Constants.Retry.TYPE, RetryStrategyType.FIXED_DELAY.toString(), "system." + Constants.Retry.MAX_TIME_SECS, "5");
strategy = SystemArguments.getRetryStrategy(args, ProgramType.CUSTOM_ACTION, cConf);
startTime = System.currentTimeMillis();
// Expects the delay doesn't change
Assert.assertEquals(1000L, strategy.nextRetry(1, startTime));
Assert.assertEquals(1000L, strategy.nextRetry(2, startTime));
Assert.assertEquals(1000L, strategy.nextRetry(3, startTime));
Assert.assertEquals(1000L, strategy.nextRetry(4, startTime));
// Should give up (returning -1) after passing the max retry time
Assert.assertEquals(-1L, strategy.nextRetry(1, startTime - 6000));
}
use of co.cask.cdap.common.service.RetryStrategy in project cdap by caskdata.
the class DistributedLogFramework method createService.
@Override
protected Service createService(Set<Integer> partitions) {
Map<String, LogPipelineSpecification<AppenderContext>> specs = new LogPipelineLoader(cConf).load(contextProvider);
int pipelineCount = specs.size();
// Create one KafkaLogProcessorPipeline per spec
final List<Service> pipelines = new ArrayList<>();
for (final LogPipelineSpecification<AppenderContext> pipelineSpec : specs.values()) {
final CConfiguration cConf = pipelineSpec.getConf();
final AppenderContext context = pipelineSpec.getContext();
long bufferSize = getBufferSize(pipelineCount, cConf, partitions.size());
final String topic = cConf.get(Constants.Logging.KAFKA_TOPIC);
final KafkaPipelineConfig config = new KafkaPipelineConfig(topic, partitions, bufferSize, cConf.getLong(Constants.Logging.PIPELINE_EVENT_DELAY_MS), cConf.getInt(Constants.Logging.PIPELINE_KAFKA_FETCH_SIZE), cConf.getLong(Constants.Logging.PIPELINE_CHECKPOINT_INTERVAL_MS));
RetryStrategy retryStrategy = RetryStrategies.fromConfiguration(cConf, "system.log.process.");
pipelines.add(new RetryOnStartFailureService(new Supplier<Service>() {
@Override
public Service get() {
return new KafkaLogProcessorPipeline(new LogProcessorPipelineContext(cConf, context.getName(), context, context.getMetricsContext(), context.getInstanceId()), checkpointManagerFactory.create(topic, pipelineSpec.getCheckpointPrefix()), brokerService, config);
}
}, retryStrategy));
}
// Returns a Service that start/stop all pipelines.
return new AbstractIdleService() {
@Override
protected void startUp() throws Exception {
// Starts all pipeline
validateAllFutures(Iterables.transform(pipelines, new Function<Service, ListenableFuture<State>>() {
@Override
public ListenableFuture<State> apply(Service service) {
return service.start();
}
}));
}
@Override
protected void shutDown() throws Exception {
// Stops all pipeline
validateAllFutures(Iterables.transform(pipelines, new Function<Service, ListenableFuture<State>>() {
@Override
public ListenableFuture<State> apply(Service service) {
return service.stop();
}
}));
}
};
}
use of co.cask.cdap.common.service.RetryStrategy in project cdap by caskdata.
the class MainOutputCommitter method setupJob.
@Override
public void setupJob(JobContext jobContext) throws IOException {
Configuration configuration = jobContext.getConfiguration();
MapReduceClassLoader classLoader = MapReduceClassLoader.getFromConfiguration(configuration);
MapReduceTaskContextProvider taskContextProvider = classLoader.getTaskContextProvider();
Injector injector = taskContextProvider.getInjector();
cConf = injector.getInstance(CConfiguration.class);
MapReduceContextConfig contextConfig = new MapReduceContextConfig(jobContext.getConfiguration());
ProgramId programId = contextConfig.getProgramId();
LOG.info("Setting up for MapReduce job: namespaceId={}, applicationId={}, program={}, runid={}", programId.getNamespace(), programId.getApplication(), programId.getProgram(), ProgramRunners.getRunId(contextConfig.getProgramOptions()));
RetryStrategy retryStrategy = SystemArguments.getRetryStrategy(contextConfig.getProgramOptions().getUserArguments().asMap(), contextConfig.getProgramId().getType(), cConf);
this.txClient = new RetryingLongTransactionSystemClient(injector.getInstance(TransactionSystemClient.class), retryStrategy);
// We start long-running tx to be used by mapreduce job tasks.
this.transaction = txClient.startLong();
// Write the tx somewhere, so that we can re-use it in mapreduce tasks
Path txFile = getTxFile(configuration, jobContext.getJobID());
FileSystem fs = txFile.getFileSystem(configuration);
try (FSDataOutputStream fsDataOutputStream = fs.create(txFile, false)) {
fsDataOutputStream.write(new TransactionCodec().encode(transaction));
}
// we can instantiate the TaskContext after we set the tx above. It's used by the operations below
taskContext = taskContextProvider.get(taskAttemptContext);
this.outputs = Outputs.transform(contextConfig.getOutputs(), taskContext);
super.setupJob(jobContext);
}
Aggregations