├── .github ├── scripts │ ├── build.sh │ └── publish.sh └── workflows │ ├── build.yml │ └── publish.yml ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── build.gradle ├── gradle.properties ├── gradle ├── jfrog.gradle ├── publications.gradle ├── versioning.gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── images ├── sum-lengths-graphviz-example.png └── sum-lengths-waterfall-example.png ├── scripts ├── help-text │ ├── local-release.txt │ └── release.txt ├── local-release └── release ├── settings.gradle └── subprojects ├── parseq-all └── build.gradle ├── parseq-batching ├── README.md ├── build.gradle ├── images │ ├── createExtendedSummary.png │ ├── createExtendedSummaryPar2.png │ ├── createExtendedSummaryPar2Batching.png │ └── createExtendedSummaryPar2BatchingSystemHidden.png └── src │ ├── main │ └── java │ │ └── com │ │ └── linkedin │ │ └── parseq │ │ └── batching │ │ ├── Batch.java │ │ ├── BatchAggregationTimeMetric.java │ │ ├── BatchImpl.java │ │ ├── BatchSizeMetric.java │ │ ├── BatchingStrategy.java │ │ ├── BatchingSupport.java │ │ ├── SimpleBatchingStrategy.java │ │ ├── SimpleTaskBatchingStrategy.java │ │ └── TaskBatchingStrategy.java │ └── test │ └── java │ └── com │ └── linkedin │ └── parseq │ └── batching │ ├── RecordingStrategy.java │ ├── RecordingTaskStrategy.java │ ├── TestBatch.java │ ├── TestBatchingSupport.java │ ├── TestSimpleBatchingStrategy.java │ ├── TestTaskBatchingStrategy.java │ ├── TestTaskSimpleBatchingStrategy.java │ └── TestTaskSimpleBatchingStrategyBlocking.java ├── parseq-benchmark ├── README.md ├── RESULTS.md ├── build.gradle └── src │ └── main │ └── java │ ├── com │ └── linkedin │ │ └── parseq │ │ ├── AbstractBenchmark.java │ │ ├── EventsArrival.java │ │ ├── HistogramSerializer.java │ │ ├── PerfLarge.java │ │ ├── PerfSmall.java │ │ ├── PoissonEventsArrival.java │ │ └── UniformEventsArrival.java │ └── org │ └── HdrHistogram │ └── Base64CompressedHistogramSerializer.java ├── parseq-examples ├── build.gradle └── src │ └── main │ └── java │ └── com │ └── linkedin │ └── parseq │ └── example │ ├── batching │ ├── BatchingClientExample.java │ └── TaskBatchingClientExample.java │ ├── common │ ├── AbstractExample.java │ ├── BatchableMockService.java │ ├── ErrorMockRequest.java │ ├── ExampleUtil.java │ ├── MockRequest.java │ ├── MockRequestWithKey.java │ ├── MockService.java │ ├── MockServiceBatchingStrategy.java │ └── SimpleMockRequest.java │ ├── composite │ ├── MergeSortExample.java │ ├── TimeBoundSearchExample.java │ ├── TwoStageFanoutExample.java │ └── classifier │ │ ├── Classification.java │ │ ├── Classifier.java │ │ ├── ClassifierDriver.java │ │ ├── ClassifierPlanFactory.java │ │ ├── ConnectedClassifier.java │ │ ├── DefaultClassifier.java │ │ ├── Network.java │ │ ├── NetworkClassifier.java │ │ ├── SelfClassifier.java │ │ ├── TruthMapClassifier.java │ │ └── client │ │ ├── Client.java │ │ ├── Request.java │ │ └── impl │ │ ├── AbstractRequest.java │ │ ├── ClientImpl.java │ │ ├── GetNetworkRequest.java │ │ └── TruthMapRequest.java │ ├── domain │ ├── AbstractDomainExample.java │ ├── AsyncPersonClient.java │ ├── Company.java │ ├── DB.java │ ├── Examples.java │ ├── Message.java │ ├── ParSeqPersonClient.java │ └── Person.java │ ├── introduction │ └── IntroductoryExample.java │ ├── javadoc │ └── JavadocExamples.java │ └── simple │ ├── BranchExecutedExample.java │ ├── BranchSkippedExample.java │ ├── CancellationExample.java │ ├── DegradedExperienceExample.java │ ├── ErrorPropagationExample.java │ ├── ErrorRecoveryExample.java │ ├── FanInExample.java │ ├── FanOutExample.java │ └── TimeoutWithErrorExample.java ├── parseq-exec ├── build.gradle └── src │ └── main │ └── java │ └── com │ └── linkedin │ └── parseq │ └── exec │ └── Exec.java ├── parseq-guava-interop ├── build.gradle └── src │ ├── main │ └── java │ │ └── com │ │ └── linkedin │ │ └── parseq │ │ └── guava │ │ └── ListenableFutureUtil.java │ └── test │ └── java │ └── com │ └── linkedin │ └── parseq │ └── guava │ └── ListenableFutureUtilTest.java ├── parseq-http-client ├── build.gradle └── src │ └── main │ └── java │ └── com │ └── linkedin │ └── parseq │ └── httpclient │ ├── HttpClient.java │ └── WrappedRequestBuilder.java ├── parseq-lambda-names ├── README.md ├── build.gradle ├── setjdk_osx ├── src │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── linkedin │ │ │ │ └── parseq │ │ │ │ ├── TaskDescriptor.java │ │ │ │ └── lambda │ │ │ │ ├── ASMBasedTaskDescriptor.java │ │ │ │ ├── FindMethodCallAnalyzer.java │ │ │ │ ├── InferredOperation.java │ │ │ │ ├── LambdaClassDescription.java │ │ │ │ ├── LambdaClassLocator.java │ │ │ │ ├── LambdaMethodVisitor.java │ │ │ │ ├── SourcePointer.java │ │ │ │ ├── SyntheticLambdaAnalyzer.java │ │ │ │ └── Util.java │ │ └── resources │ │ │ └── META-INF │ │ │ └── services │ │ │ └── com.linkedin.parseq.TaskDescriptor │ └── test │ │ └── java │ │ └── com │ │ └── linkedin │ │ └── parseq │ │ └── lambda │ │ ├── BaseTest.java │ │ ├── TestInterface.java │ │ ├── TestMethodInv.java │ │ ├── TestMethodRef.java │ │ ├── TestStaticMethodInv.java │ │ ├── TestStaticMethodRef.java │ │ ├── TestUnrecognizedLambda.java │ │ └── TestUtil.java ├── supported_jvms └── test_supported_jvms ├── parseq-legacy-examples ├── build.gradle └── src │ └── main │ └── java │ └── com │ └── linkedin │ └── parseq │ └── example │ ├── common │ ├── AbstractExample.java │ ├── ErrorMockRequest.java │ ├── ExampleUtil.java │ ├── MockRequest.java │ ├── MockService.java │ └── SimpleMockRequest.java │ ├── composite │ ├── MergeSortExample.java │ ├── TimeBoundSearchExample.java │ ├── TwoStageFanoutExample.java │ └── classifier │ │ ├── Classification.java │ │ ├── Classifier.java │ │ ├── ClassifierDriver.java │ │ ├── ClassifierPlanFactory.java │ │ ├── ConnectedClassifier.java │ │ ├── DefaultClassifier.java │ │ ├── Network.java │ │ ├── NetworkClassifier.java │ │ ├── SelfClassifier.java │ │ ├── TruthMapClassifier.java │ │ └── client │ │ ├── Client.java │ │ ├── Request.java │ │ └── impl │ │ ├── AbstractRequest.java │ │ ├── ClientImpl.java │ │ ├── GetNetworkRequest.java │ │ └── TruthMapRequest.java │ └── simple │ ├── BranchExecutedExample.java │ ├── BranchSkippedExample.java │ ├── ErrorPropagationExample.java │ ├── ErrorRecoveryExample.java │ ├── FanInExample.java │ ├── FanOutExample.java │ └── TimeoutWithErrorExample.java ├── parseq-restli-client ├── README.md ├── build.gradle └── src │ ├── main │ ├── antlr4 │ │ └── com │ │ │ └── linkedin │ │ │ └── restli │ │ │ └── client │ │ │ └── config │ │ │ └── RequestConfigKey.g4 │ └── java │ │ ├── RequestConfigKey.tokens │ │ ├── RequestConfigKeyLexer.tokens │ │ └── com │ │ └── linkedin │ │ └── restli │ │ └── client │ │ ├── DirectExecutor.java │ │ ├── GetRequestGroup.java │ │ ├── InboundRequestContext.java │ │ ├── InboundRequestContextBuilder.java │ │ ├── InboundRequestContextFinder.java │ │ ├── InboundRequestContextImpl.java │ │ ├── MultipleRequestConfigProvider.java │ │ ├── ParSeqRestClient.java │ │ ├── ParSeqRestliClient.java │ │ ├── ParSeqRestliClientBuilder.java │ │ ├── ParSeqRestliClientConfig.java │ │ ├── ParSeqRestliClientConfigBuilder.java │ │ ├── ParSeqRestliClientConfigChooser.java │ │ ├── ParSeqRestliClientConfigImpl.java │ │ ├── RequestGroup.java │ │ ├── RestRequestBatchKey.java │ │ ├── config │ │ ├── ConfigValue.java │ │ ├── ConfigValueCoercers.java │ │ ├── RequestConfig.java │ │ ├── RequestConfigBuilder.java │ │ ├── RequestConfigCacheKey.java │ │ ├── RequestConfigElement.java │ │ ├── RequestConfigImpl.java │ │ ├── RequestConfigKeyBaseListener.java │ │ ├── RequestConfigKeyLexer.java │ │ ├── RequestConfigKeyListener.java │ │ ├── RequestConfigKeyParser.java │ │ ├── RequestConfigKeyParsingErrorListener.java │ │ ├── RequestConfigKeyParsingException.java │ │ ├── RequestConfigOverrides.java │ │ ├── RequestConfigOverridesBuilder.java │ │ ├── RequestConfigOverridesImpl.java │ │ ├── RequestConfigProvider.java │ │ ├── RequestConfigProviderBuilder.java │ │ ├── RequestConfigProviderImpl.java │ │ └── RequestConfigTree.java │ │ └── metrics │ │ ├── BatchingMetrics.java │ │ └── Metrics.java │ └── test │ └── java │ └── com │ └── linkedin │ └── restli │ └── client │ ├── CapturingRestClient.java │ ├── ParSeqRestClientBatchingIntegrationTest.java │ ├── ParSeqRestClientIntegrationTest.java │ ├── TestInboundRequestContextBuilder.java │ ├── TestParSeqRestClient.java │ ├── TestParSeqRestClientBatching.java │ ├── TestParSeqRestClientBatchingOverride.java │ ├── TestParSeqRestClientClientException.java │ ├── TestParSeqRestClientNoBatching.java │ ├── TestParSeqRestClientNoBatchingOverrides.java │ ├── TestParSeqRestClientWithD2Timeout.java │ ├── TestRequest404WithBatching.java │ ├── TestRequestContextProvider.java │ └── config │ ├── TestRequestConfigElement.java │ └── TestRequestConfigProvider.java ├── parseq-test-api ├── build.gradle └── src │ └── main │ └── java │ └── com │ └── linkedin │ └── parseq │ ├── AbstractBaseEngineTest.java │ ├── BaseEngineParTest.java │ ├── BaseEngineTest.java │ ├── ListLogger.java │ ├── ListLoggerFactory.java │ ├── ParSeqUnitTestHelper.java │ └── junitjupiter │ ├── BaseEngineJUnitJupiterTest.java │ └── BaseEngineParJunitJupiterTest.java ├── parseq-tracevis-server ├── Dockerfile ├── README.md ├── assembly-descriptor.xml ├── build.gradle ├── config.properties └── src │ └── main │ ├── java │ └── com │ │ └── linkedin │ │ └── parseq │ │ ├── Constants.java │ │ ├── DotHandler.java │ │ ├── GraphvizEngine.java │ │ ├── HashManager.java │ │ ├── HealthCheckHandler.java │ │ ├── HttpResponse.java │ │ ├── JhatHandler.java │ │ ├── TracePostHandler.java │ │ ├── TracevisHttpsServer.java │ │ ├── TracevisServer.java │ │ ├── TracevisServerJarMain.java │ │ └── TracevisServerMain.java │ └── resources │ ├── RecoverParSeqTracesFromHeapDump.js │ └── heapster │ ├── heapster.html │ ├── img │ └── icon.png │ └── js │ ├── jquery-2.2.3.min.js │ ├── jquery.spin.js │ └── spin.min.js ├── parseq-tracevis ├── .gitignore ├── .jshintrc ├── .npmignore ├── Makefile ├── README.md ├── bootstrap │ ├── css │ │ ├── bootstrap.css │ │ └── bootstrap.min.css │ ├── img │ │ ├── glyphicons-halflings-white.png │ │ └── glyphicons-halflings.png │ └── js │ │ ├── bootstrap.js │ │ └── bootstrap.min.js ├── browser.js ├── build.gradle ├── css │ ├── d3.slider.css │ ├── table.css │ └── waterfall.css ├── img │ └── icon.png ├── index.js ├── js │ ├── d3.slider.js │ └── d3.v3.min.js ├── lib │ ├── render │ │ ├── graphviz.js │ │ ├── table.js │ │ └── waterfall.js │ └── trace │ │ ├── criticalPath.js │ │ ├── d3Treeify.js │ │ ├── dotify.js │ │ ├── exclude.js │ │ ├── parse.js │ │ └── util.js ├── package-lock.json ├── package.json ├── test │ ├── int │ │ └── int-test.mjs │ └── unit │ │ ├── assert.js │ │ ├── criticalPath-test.js │ │ ├── d3Treeify-test.js │ │ ├── dotify-test.js │ │ ├── exclude-test.js │ │ └── parse-test.js └── trace.html ├── parseq-zk-client ├── build.gradle └── src │ ├── main │ └── java │ │ └── com │ │ └── linkedin │ │ └── parseq │ │ └── zk │ │ ├── client │ │ ├── PlanLocal.java │ │ ├── Reaper.java │ │ ├── WatchableTask.java │ │ ├── ZKClient.java │ │ ├── ZKClientBuilder.java │ │ ├── ZKClientImpl.java │ │ ├── ZKData.java │ │ └── ZKUtil.java │ │ └── recipes │ │ ├── LockUtil.java │ │ ├── MultiLocks.java │ │ ├── Synchronizable.java │ │ └── ZKLock.java │ └── test │ ├── java │ └── com │ │ └── linkedin │ │ └── parseq │ │ └── zk │ │ ├── client │ │ ├── TestReaper.java │ │ └── TestZKClient.java │ │ ├── recipes │ │ └── TestZKLock.java │ │ └── server │ │ └── ZKServer.java │ └── resources │ └── log4j.properties └── parseq ├── build.gradle └── src ├── main ├── codegen │ ├── config.fmpp │ ├── data │ │ └── fmpp.tdd │ └── templates │ │ ├── com │ │ └── linkedin │ │ │ └── parseq │ │ │ ├── ParNTask.java.ftl │ │ │ ├── TupleNTask.java.ftl │ │ │ ├── TupleNTaskDelegate.java.ftl │ │ │ └── function │ │ │ ├── ConsumerN.java.ftl │ │ │ ├── FunctionN.java.ftl │ │ │ ├── TupleN.java.ftl │ │ │ └── Tuples.java.ftl │ │ └── macros │ │ └── macros.ftl └── java │ └── com │ └── linkedin │ └── parseq │ ├── ActionTask.java │ ├── After.java │ ├── AsyncCallableTask.java │ ├── BaseTask.java │ ├── CallableTask.java │ ├── Cancellable.java │ ├── CancellationException.java │ ├── Context.java │ ├── DelayedExecutor.java │ ├── DelayedExecutorAdapter.java │ ├── EarlyFinishException.java │ ├── Engine.java │ ├── EngineBuilder.java │ ├── EngineShutdownException.java │ ├── Exceptions.java │ ├── FusionTask.java │ ├── FusionTraceContext.java │ ├── IndirectDelayedExecutor.java │ ├── MultiException.java │ ├── Par10Task.java │ ├── Par11Task.java │ ├── Par12Task.java │ ├── Par13Task.java │ ├── Par14Task.java │ ├── Par15Task.java │ ├── Par2Task.java │ ├── Par3Task.java │ ├── Par4Task.java │ ├── Par5Task.java │ ├── Par6Task.java │ ├── Par7Task.java │ ├── Par8Task.java │ ├── Par9Task.java │ ├── ParSeqGlobalConfiguration.java │ ├── ParTask.java │ ├── ParTaskImpl.java │ ├── Priority.java │ ├── SeqTask.java │ ├── Task.java │ ├── TaskDescriptor.java │ ├── TaskDescriptorFactory.java │ ├── TaskQueueFactory.java │ ├── TaskType.java │ ├── Tasks.java │ ├── ThrowableCallable.java │ ├── Tuple10Task.java │ ├── Tuple10TaskDelegate.java │ ├── Tuple11Task.java │ ├── Tuple11TaskDelegate.java │ ├── Tuple12Task.java │ ├── Tuple12TaskDelegate.java │ ├── Tuple13Task.java │ ├── Tuple13TaskDelegate.java │ ├── Tuple14Task.java │ ├── Tuple14TaskDelegate.java │ ├── Tuple15Task.java │ ├── Tuple15TaskDelegate.java │ ├── Tuple2Task.java │ ├── Tuple2TaskDelegate.java │ ├── Tuple3Task.java │ ├── Tuple3TaskDelegate.java │ ├── Tuple4Task.java │ ├── Tuple4TaskDelegate.java │ ├── Tuple5Task.java │ ├── Tuple5TaskDelegate.java │ ├── Tuple6Task.java │ ├── Tuple6TaskDelegate.java │ ├── Tuple7Task.java │ ├── Tuple7TaskDelegate.java │ ├── Tuple8Task.java │ ├── Tuple8TaskDelegate.java │ ├── Tuple9Task.java │ ├── Tuple9TaskDelegate.java │ ├── doc-files │ ├── andThen-1.png │ ├── andThen-2.png │ ├── andThen-3.png │ ├── andThen-4.png │ ├── flatMap-1.png │ ├── flatMap-2.png │ ├── map-1.png │ ├── map-2.png │ ├── onFailure-1.png │ ├── onFailure-2.png │ ├── recover-1.png │ ├── recoverWith-1.png │ ├── shareable-1.png │ ├── shareable-2.png │ ├── toTry-1.png │ ├── toTry-2.png │ ├── transform-1.png │ ├── transformWith-1.png │ ├── withSideEffect-1.png │ └── withTimeout-1.png │ ├── function │ ├── Action.java │ ├── Consumer1.java │ ├── Consumer10.java │ ├── Consumer11.java │ ├── Consumer12.java │ ├── Consumer13.java │ ├── Consumer14.java │ ├── Consumer15.java │ ├── Consumer2.java │ ├── Consumer3.java │ ├── Consumer4.java │ ├── Consumer5.java │ ├── Consumer6.java │ ├── Consumer7.java │ ├── Consumer8.java │ ├── Consumer9.java │ ├── Failure.java │ ├── Function1.java │ ├── Function10.java │ ├── Function11.java │ ├── Function12.java │ ├── Function13.java │ ├── Function14.java │ ├── Function15.java │ ├── Function2.java │ ├── Function3.java │ ├── Function4.java │ ├── Function5.java │ ├── Function6.java │ ├── Function7.java │ ├── Function8.java │ ├── Function9.java │ ├── Success.java │ ├── Try.java │ ├── Tuple.java │ ├── Tuple10.java │ ├── Tuple11.java │ ├── Tuple12.java │ ├── Tuple13.java │ ├── Tuple14.java │ ├── Tuple15.java │ ├── Tuple2.java │ ├── Tuple3.java │ ├── Tuple4.java │ ├── Tuple5.java │ ├── Tuple6.java │ ├── Tuple7.java │ ├── Tuple8.java │ ├── Tuple9.java │ └── Tuples.java │ ├── internal │ ├── ArgumentUtil.java │ ├── CachedLoggerFactory.java │ ├── CancellableScheduledFuture.java │ ├── Clock.java │ ├── ContextImpl.java │ ├── Continuations.java │ ├── DefaultPlanBasedRateLimiter.java │ ├── ExecutionMonitor.java │ ├── FIFOPriorityQueue.java │ ├── IdGenerator.java │ ├── InternalUtil.java │ ├── LIFOBiPriorityQueue.java │ ├── PlanBasedRateLimiter.java │ ├── PlanCompletionListener.java │ ├── PlanContext.java │ ├── PlanDeactivationListener.java │ ├── PlatformClock.java │ ├── Prioritizable.java │ ├── PrioritizableRunnable.java │ ├── SerialExecutionException.java │ ├── SerialExecutor.java │ ├── SystemHiddenTask.java │ ├── TaskLogger.java │ ├── ThreadDumper.java │ ├── TimeUnitHelper.java │ └── UncaughtExceptionHandler.java │ ├── package-info.java │ ├── promise │ ├── CountDownPromiseListener.java │ ├── DelegatingPromise.java │ ├── FastFailCountDownPromiseListener.java │ ├── Promise.java │ ├── PromiseException.java │ ├── PromiseListener.java │ ├── PromisePropagator.java │ ├── PromiseResolvedException.java │ ├── PromiseTransformer.java │ ├── PromiseUnresolvedException.java │ ├── Promises.java │ ├── ResolvedError.java │ ├── ResolvedValue.java │ ├── Settable.java │ ├── SettablePromise.java │ ├── SettablePromiseImpl.java │ ├── TransformingPromiseListener.java │ └── package-info.java │ ├── retry │ ├── ErrorClassification.java │ ├── RetriableTask.java │ ├── RetryPolicy.java │ ├── RetryPolicyBuilder.java │ ├── RetryPolicyImpl.java │ ├── backoff │ │ ├── BackoffPolicy.java │ │ ├── ConstantBackoff.java │ │ ├── ExponentialBackoff.java │ │ ├── FibonacciBackoff.java │ │ ├── LinearBackoff.java │ │ ├── RandomizedBackoff.java │ │ └── SelectedBackoff.java │ └── termination │ │ ├── GuavaRateLimiter.java │ │ ├── LimitAttempts.java │ │ ├── LimitDuration.java │ │ ├── LimitRate.java │ │ ├── RateLimiter.java │ │ ├── RequireAny.java │ │ ├── RequireBoth.java │ │ ├── RequireEither.java │ │ └── TerminationPolicy.java │ └── trace │ ├── Relationship.java │ ├── ResultType.java │ ├── ShallowTrace.java │ ├── ShallowTraceBuilder.java │ ├── ShallowTraceImp.java │ ├── Trace.java │ ├── TraceBuilder.java │ ├── TraceRelationship.java │ ├── TraceUtil.java │ ├── codec │ ├── TraceCodec.java │ ├── json │ │ ├── JsonTraceCodec.java │ │ ├── JsonTraceDeserializer.java │ │ ├── JsonTraceSerializer.java │ │ └── package-info.java │ └── package-info.java │ └── package-info.java └── test └── java ├── com └── linkedin │ └── parseq │ ├── AbstractTaskTest.java │ ├── ParSeqUnitTestHelperTest.java │ ├── TestAsyncCallableTask.java │ ├── TestCancellingPlanExceptionHandler.java │ ├── TestContext.java │ ├── TestEngine.java │ ├── TestEngineConcurrentPlans.java │ ├── TestEnginePlanBasedRateLimit.java │ ├── TestFusionTask.java │ ├── TestIndirectDelayedExecutor.java │ ├── TestParTask.java │ ├── TestSeqTask.java │ ├── TestTask.java │ ├── TestTaskCancellation.java │ ├── TestTaskFactoryMethods.java │ ├── TestTaskLogging.java │ ├── TestTaskReuse.java │ ├── TestTaskStates.java │ ├── TestTaskType.java │ ├── TestTasks.java │ ├── TestUtil.java │ ├── TestWithTry.java │ ├── TestingExecutorService.java │ ├── ThrowingRunnable.java │ ├── internal │ ├── TestArgumentUtil.java │ ├── TestCachedLoggerFactory.java │ ├── TestClock.java │ ├── TestContinuations.java │ ├── TestExecutionMonitor.java │ ├── TestFIFOPriorityQueue.java │ ├── TestLIFOBiPriorityQueue.java │ ├── TestLogAppender.java │ ├── TestPlanCompletionListener.java │ └── TestSerialExecutor.java │ ├── promise │ ├── TestDelegatingPromise.java │ ├── TestPromises.java │ └── TestSettablePromise.java │ ├── retry │ ├── TestBackoffPolicy.java │ ├── TestRetriableTask.java │ ├── TestRetryPolicy.java │ └── TestTerminationPolicy.java │ └── trace │ ├── TestFusionTaskTrace.java │ ├── TestShallowTraceBuilder.java │ ├── TestTaskToTrace.java │ ├── TestTraceBuilder.java │ └── codec │ └── json │ └── TestJsonTraceCodec.java └── log4j.properties /.github/scripts/build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Ensure that this is being run in CI by GitHub Actions 4 | if [ "$CI" != "true" ] || [ "$GITHUB_ACTIONS" != "true" ]; then 5 | echo "This script should only be run in CI by GitHub Actions." 6 | exit 2 7 | fi 8 | 9 | # Ensure that the script is being run from the root project directory 10 | PROPERTIES_FILE='gradle.properties' 11 | if [ ! -f "$PROPERTIES_FILE" ]; then 12 | echo "Could not find $PROPERTIES_FILE, are you sure this is being run from the root project directory?" 13 | echo "PWD: ${PWD}" 14 | exit 1 15 | fi 16 | 17 | # Determine the current version 18 | VERSION=$(awk 'BEGIN { FS = "=" }; $1 == "version" { print $2 }' $PROPERTIES_FILE | awk '{ print $1 }') 19 | if [ -z "$VERSION" ]; then 20 | echo "Could not read the version from $PROPERTIES_FILE, please fix it and try again." 21 | exit 1 22 | fi 23 | 24 | # Run the actual build 25 | ./gradlew -Prelease build 26 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build and Test 2 | on: 3 | pull_request: 4 | branches: [master] 5 | push: 6 | branches: [master] 7 | jobs: 8 | build: 9 | runs-on: ${{ matrix.os }} 10 | strategy: 11 | fail-fast: false 12 | matrix: 13 | os: [ubuntu-latest] 14 | java: [8.0.312+7] 15 | name: Java ${{ matrix.java }} on ${{ matrix.os }} 16 | steps: 17 | - uses: actions/checkout@v2 18 | with: 19 | # Need to fetch 2 commits for the PR (base commit and head merge commit) so we can compute the diff 20 | fetch-depth: 2 21 | - uses: actions/setup-java@v2 22 | with: 23 | distribution: zulu 24 | java-version: ${{ matrix.java }} 25 | cache: gradle 26 | - run: ./.github/scripts/build.sh 27 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Build and Publish 2 | on: 3 | push: 4 | tags: 5 | # On standard release tags (e.g. "v29.0.12") 6 | - v[0-9]+.[0-9]+.[0-9]+ 7 | # On release-candidate tags (e.g. "v1.2.3-rc.1") 8 | - v[0-9]+.[0-9]+.[0-9]+-rc.[0-9]+ 9 | jobs: 10 | publish: 11 | environment: jfrog-publish 12 | runs-on: ubuntu-latest 13 | strategy: 14 | fail-fast: false 15 | matrix: 16 | java: [8.0.312+7] 17 | name: Java ${{ matrix.java }} 18 | steps: 19 | - uses: actions/checkout@v2 20 | - uses: actions/setup-java@v2 21 | with: 22 | distribution: zulu 23 | java-version: ${{ matrix.java }} 24 | # Do NOT use caching, since we want to ensure published artifacts are fresh 25 | - run: ./.github/scripts/publish.sh 26 | env: 27 | JFROG_USER: ${{ secrets.JFROG_USER }} 28 | JFROG_KEY: ${{ secrets.JFROG_KEY }} 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .classpath 3 | .project 4 | .idea 5 | *.iml 6 | *.ipr 7 | *.iws 8 | build 9 | dist 10 | out 11 | node_modules 12 | target 13 | .DS_Store 14 | .gradle 15 | /.gradle 16 | .settings 17 | subprojects/parseq-lambda-names/bin/ 18 | subprojects/parseq-tracevis/npm-debug.log -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | version=5.1.20 2 | group=com.linkedin.parseq 3 | org.gradle.parallel=true 4 | -------------------------------------------------------------------------------- /gradle/versioning.gradle: -------------------------------------------------------------------------------- 1 | if (!project.hasProperty('release') && !project.version.endsWith("-SNAPSHOT")) { 2 | project.version += "-SNAPSHOT" 3 | } 4 | 5 | logger.lifecycle "Building version $version" -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkedin/parseq/3a580be06c5c9f6af2bb13a788de968a6123b3e3/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /images/sum-lengths-graphviz-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkedin/parseq/3a580be06c5c9f6af2bb13a788de968a6123b3e3/images/sum-lengths-graphviz-example.png -------------------------------------------------------------------------------- /images/sum-lengths-waterfall-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkedin/parseq/3a580be06c5c9f6af2bb13a788de968a6123b3e3/images/sum-lengths-waterfall-example.png -------------------------------------------------------------------------------- /scripts/help-text/local-release.txt: -------------------------------------------------------------------------------- 1 | Usage: ./scripts/local-release [OPTION]... 2 | Publishes ParSeq's Maven artifacts to ~/local-repo. 3 | This script must be run from the root project directory. 4 | 5 | Options: 6 | -h, --help print this help text and exit 7 | -s, --snapshot release a snapshot version 8 | 9 | Examples: 10 | ./scripts/local-release publish x.y.z artifacts to ~/local-repo 11 | ./scripts/local-release -s publish x.y.z-SNAPSHOT artifacts to ~/local-repo 12 | -------------------------------------------------------------------------------- /scripts/help-text/release.txt: -------------------------------------------------------------------------------- 1 | Usage: ./scripts/release [OPTION]... [TARGET_COMMIT] 2 | Releases a new version of ParSeq by creating and pushing a tag at TARGET_COMMIT (defaults to HEAD). 3 | This script must be run from the root project directory. 4 | 5 | Options: 6 | -h, --help print this help text and exit 7 | 8 | Examples: 9 | ./scripts/release create and push a release tag at HEAD 10 | ./scripts/release 0a1b2c3 create and push a release tag at commit 0a1b2c3 11 | ./scripts/release master^^ create and push a release tag at two commits before the head of master 12 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'parseq' 2 | 3 | def modules = [ /* the name of the modules to use */ 4 | 'parseq', // core parseq code 5 | 'parseq-all', // meta-project containing the entire dependency tree 6 | 'parseq-batching', 7 | 'parseq-benchmark', 8 | 'parseq-examples', 9 | 'parseq-exec', 10 | 'parseq-guava-interop', 11 | 'parseq-http-client', 12 | 'parseq-lambda-names', // shadow jar 13 | 'parseq-legacy-examples', 14 | 'parseq-restli-client', 15 | 'parseq-test-api', // unit/integration test utils 16 | 'parseq-tracevis', // trace visualization tools 17 | 'parseq-tracevis-server', 18 | 'parseq-zk-client' 19 | ] 20 | 21 | 22 | modules.each { module -> 23 | include "${module}" 24 | project(":${module}").projectDir = file("subprojects/${module}") 25 | } 26 | -------------------------------------------------------------------------------- /subprojects/parseq-all/build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | This is a meta-project that programmatically depends on all other consumer-facing modules. 3 | The purpose of this module is to act as an entry point for systems to compute the entire dependency tree of ParSeq. 4 | It is not intended to be directly consumed like a normal module, since it'll bloat the consumer's dependencies. 5 | */ 6 | ext { 7 | description = '''Meta-project containing the entire dependency tree of parseq; should not be consumed directly.''' 8 | } 9 | 10 | dependencies { 11 | rootProject.subprojects.forEach { 12 | if (it != project && !it.name.endsWith('examples')) { 13 | compile it 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /subprojects/parseq-batching/build.gradle: -------------------------------------------------------------------------------- 1 | ext { 2 | description = """Provides a convenient API for creating automatically batched tasks""" 3 | } 4 | 5 | 6 | dependencies { 7 | compile group: 'org.hdrhistogram', name: 'HdrHistogram', version:'2.1.8' 8 | 9 | testCompile project(':parseq-test-api') 10 | testCompile group: 'org.testng', name: 'testng', version:'6.9.9' 11 | testCompile group: 'org.slf4j', name: 'slf4j-simple', version:'1.7.12' 12 | } 13 | -------------------------------------------------------------------------------- /subprojects/parseq-batching/images/createExtendedSummary.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkedin/parseq/3a580be06c5c9f6af2bb13a788de968a6123b3e3/subprojects/parseq-batching/images/createExtendedSummary.png -------------------------------------------------------------------------------- /subprojects/parseq-batching/images/createExtendedSummaryPar2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkedin/parseq/3a580be06c5c9f6af2bb13a788de968a6123b3e3/subprojects/parseq-batching/images/createExtendedSummaryPar2.png -------------------------------------------------------------------------------- /subprojects/parseq-batching/images/createExtendedSummaryPar2Batching.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkedin/parseq/3a580be06c5c9f6af2bb13a788de968a6123b3e3/subprojects/parseq-batching/images/createExtendedSummaryPar2Batching.png -------------------------------------------------------------------------------- /subprojects/parseq-batching/images/createExtendedSummaryPar2BatchingSystemHidden.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkedin/parseq/3a580be06c5c9f6af2bb13a788de968a6123b3e3/subprojects/parseq-batching/images/createExtendedSummaryPar2BatchingSystemHidden.png -------------------------------------------------------------------------------- /subprojects/parseq-batching/src/main/java/com/linkedin/parseq/batching/BatchingSupport.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.batching; 2 | 3 | import java.util.List; 4 | import java.util.concurrent.CopyOnWriteArrayList; 5 | 6 | import com.linkedin.parseq.EngineBuilder; 7 | import com.linkedin.parseq.internal.PlanContext; 8 | import com.linkedin.parseq.internal.PlanDeactivationListener; 9 | 10 | /** 11 | * This class allows registering instances of {@link BatchingStrategy}. 12 | *

13 | * Please note that BatchingSupport must be registered with an {@link EngineBuilder} e.g. 14 | *

15 |  *  BatchingSupport batchingSupport = new BatchingSupport();
16 |  *  engineBuilder.setPlanDeactivationListener(batchingSupport);
17 |  *  (...)
18 |  *  batchingSupport.registerStrategy(batchingStrategy);
19 |  * 
20 | * 21 | * @author Jaroslaw Odzga (jodzga@linkedin.com) 22 | */ 23 | public class BatchingSupport implements PlanDeactivationListener { 24 | 25 | private final List> _strategies = 26 | new CopyOnWriteArrayList<>(); 27 | 28 | /** 29 | * Register an instance of {@link BatchingStrategy}. 30 | * @param strategy strategy to be registered 31 | */ 32 | public void registerStrategy(BatchingStrategy strategy) { 33 | _strategies.add(strategy); 34 | } 35 | 36 | @Override 37 | public void onPlanDeactivated(final PlanContext planContext) { 38 | _strategies.forEach(strategy -> strategy.handleBatch(planContext)); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /subprojects/parseq-benchmark/README.md: -------------------------------------------------------------------------------- 1 | Benchmarks are based on [Oracle Java Microbenchmark Harness](http://openjdk.java.net/projects/code-tools/jmh/). 2 | 3 | ### Results interpretation 4 | 5 | Be cautious with conclusions based on microbenchmarking as there are plenty possible pitfalls for goals, test compositions, input data, an environment and the analyze itself. 6 | 7 | ### Command line launching 8 | 9 | Execute all benchmark methods with 4 worker threads: 10 | 11 | ./gradlew clean build 12 | java -jar build/libs/benchmarks.jar ".*" -t 4 13 | 14 | or specify a filter for benchmark methods and the number of forks and warmup/measurements iterations, e.g.: 15 | 16 | java -jar build/libs/benchmarks.jar -t 4 -f 3 -i 10 -wi 5 ".*IdGeneratorBenchmark.*" 17 | java -jar build/libs/benchmarks.jar -t 4 -f 3 -i 10 -wi 5 ".*LongIdGeneratorBenchmark.*" 18 | 19 | ### Command line options 20 | 21 | The whole list of command line options is available by: 22 | 23 | java -jar build/libs/benchmarks.jar -h 24 | -------------------------------------------------------------------------------- /subprojects/parseq-benchmark/RESULTS.md: -------------------------------------------------------------------------------- 1 | ### Id Generation 2 | 3 | commnand: 4 | ``` 5 | mvn clean install 6 | java -jar target/benchmarks.jar ".*" -t 4 7 | ``` 8 | 9 | result: 10 | ``` 11 | (...) 12 | 13 | Result "getNextId": 14 | 46790699.050 ±(99.9%) 407080.865 ops/s [Average] 15 | (min, avg, max) = (40626145.225, 46790699.050, 51498108.670), stdev = 1723605.871 16 | CI (99.9%): [46383618.186, 47197779.915] (assumes normal distribution) 17 | 18 | 19 | Run complete. Total time: 00:13:27 20 | 21 | Benchmark Mode Cnt Score Error Units 22 | IdGeneratorBenchmark.getNextId thrpt 200 331533289.736 ± 3360147.670 ops/s 23 | LongIdGeneratorBenchmark.getNextId thrpt 200 46790699.050 ± 407080.865 ops/s 24 | ``` -------------------------------------------------------------------------------- /subprojects/parseq-benchmark/build.gradle: -------------------------------------------------------------------------------- 1 | ext { 2 | description = """Set of benchmarks for ParSeq""" 3 | } 4 | 5 | dependencies { 6 | compile project(':parseq-batching') 7 | compile group: 'org.hdrhistogram', name: 'HdrHistogram', version:'2.1.8' 8 | compile group: 'org.slf4j', name: 'slf4j-simple', version:'1.7.12' 9 | } 10 | 11 | task fatJar(type: Jar) { 12 | mustRunAfter ':parseq:jar' // for some reason, gradle can't figure out this transitive dependency 13 | classifier = 'jar-with-dependencies' 14 | from { configurations.compile.collect { it.isDirectory()? it : zipTree(it) } } 15 | with jar 16 | manifest { 17 | attributes("Created-By": "Gradle", 18 | "Version": version, 19 | "Build-JDK": JavaVersion.current()) 20 | attributes 'Main-Class': 'com.linkedin.parseq.PerfLarge' 21 | } 22 | } 23 | 24 | task executeJava(type: JavaExec) { 25 | main = "com.linkedin.parseq.PerfLarge" 26 | classpath = sourceSets.main.runtimeClasspath 27 | } 28 | 29 | artifacts { 30 | archives fatJar 31 | } 32 | -------------------------------------------------------------------------------- /subprojects/parseq-benchmark/src/main/java/com/linkedin/parseq/EventsArrival.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | /** 6 | * This interface represents an arrival process. It contains one method that returns number of nanoseconds 7 | * until next arrival. 8 | * 9 | * @author Jaroslaw Odzga (jodzga@linkedin.com) 10 | */ 11 | public interface EventsArrival { 12 | 13 | /** 14 | * @return The number of nanoseconds until next arrival. 15 | */ 16 | long nanosToNextEvent(); 17 | 18 | static EventsArrival fromName(final String name, final double events, final TimeUnit perUnit) { 19 | switch (name) { 20 | case "poisson": 21 | return new PoissonEventsArrival(events, perUnit); 22 | case "uniform": 23 | return new UniformEventsArrival(events, perUnit); 24 | } 25 | throw new IllegalArgumentException("unsupported events arrival type: " + name); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /subprojects/parseq-benchmark/src/main/java/com/linkedin/parseq/HistogramSerializer.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq; 2 | 3 | import org.HdrHistogram.Histogram; 4 | 5 | public interface HistogramSerializer { 6 | 7 | String serialize(Histogram histogram); 8 | 9 | Histogram deserialize(String serialized); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /subprojects/parseq-benchmark/src/main/java/com/linkedin/parseq/PerfLarge.java: -------------------------------------------------------------------------------- 1 | /* $Id$ */ 2 | package com.linkedin.parseq; 3 | 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | import com.linkedin.parseq.Task; 8 | import com.linkedin.parseq.Tasks; 9 | 10 | 11 | /** 12 | * @author Jaroslaw Odzga (jodzga@linkedin.com) 13 | */ 14 | public class PerfLarge extends AbstractBenchmark { 15 | 16 | public static void main(String[] args) throws Exception { 17 | // FullLoadBenchmarkConfig cfg = new FullLoadBenchmarkConfig(); 18 | ConstantThroughputBenchmarkConfig cfg = new ConstantThroughputBenchmarkConfig(); 19 | cfg.CONCURRENCY_LEVEL = Integer.MAX_VALUE; 20 | cfg.events = 1000; 21 | new PerfLarge().runExample(cfg); 22 | } 23 | 24 | @Override 25 | Task createPlan() { 26 | List> l = new ArrayList<>(); 27 | for (int i = 0; i < 20; i++) { 28 | l.add(task()); 29 | } 30 | return Tasks.par(l); 31 | } 32 | 33 | private Task task() { 34 | return Task.value("kldfjlajflskjflsjfslkajflkasj").map("length", s -> s.length()).map("+1", s -> s + 1) 35 | .map("+2", s -> s + 2).map("+3", s -> s + 3).shareable().recoverWith(t -> Task.value(0)) 36 | .flatMap(x -> Task.value(x * 40)).map(x -> x -10); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /subprojects/parseq-benchmark/src/main/java/com/linkedin/parseq/PerfSmall.java: -------------------------------------------------------------------------------- 1 | /* $Id$ */ 2 | package com.linkedin.parseq; 3 | 4 | /** 5 | * @author Jaroslaw Odzga (jodzga@linkedin.com) 6 | */ 7 | public class PerfSmall extends AbstractBenchmark { 8 | 9 | public static void main(String[] args) throws Exception { 10 | FullLoadBenchmarkConfig cfg = new FullLoadBenchmarkConfig(); 11 | cfg.N = 10000000; 12 | cfg.WARMUP_ROUNDS = 100000; 13 | new PerfSmall().runExample(cfg); 14 | } 15 | 16 | @Override 17 | Task createPlan() { 18 | return Task.value("kldfjlajflskjflsjfslkajflkasj").map("length", s -> s.length()).map("+1", s -> s + 1) 19 | .map("+2", s -> s + 2).map("+3", s -> s + 3); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /subprojects/parseq-benchmark/src/main/java/com/linkedin/parseq/PoissonEventsArrival.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq; 2 | 3 | import java.util.Random; 4 | import java.util.concurrent.TimeUnit; 5 | 6 | public class PoissonEventsArrival implements EventsArrival { 7 | 8 | private final Random _rand = new Random(System.nanoTime()); 9 | private final double _nanosToNextEventMean; 10 | 11 | public PoissonEventsArrival(double events, TimeUnit perUnit) { 12 | if (events <= 0) { 13 | throw new IllegalArgumentException("events must be a positive number"); 14 | } 15 | _nanosToNextEventMean = perUnit.toNanos(1) / events; 16 | } 17 | 18 | @Override 19 | public long nanosToNextEvent() { 20 | //rand is uniformly distributed form 0.0d inclusive up to 1.0d exclusive 21 | double rand = _rand.nextDouble(); 22 | return (long)(-_nanosToNextEventMean * Math.log(1 - rand)); 23 | } 24 | 25 | @Override 26 | public String toString() { 27 | return "PoissonEventsArrival [nanosToNextEventMean=" + _nanosToNextEventMean + "]"; 28 | } 29 | 30 | 31 | } 32 | -------------------------------------------------------------------------------- /subprojects/parseq-benchmark/src/main/java/com/linkedin/parseq/UniformEventsArrival.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | public class UniformEventsArrival implements EventsArrival { 6 | private final double _nanosToNextEvent; 7 | 8 | public UniformEventsArrival(double events, TimeUnit perUnit) { 9 | _nanosToNextEvent = perUnit.toNanos(1) / events; 10 | } 11 | 12 | @Override 13 | public long nanosToNextEvent() { 14 | return (long)_nanosToNextEvent; 15 | } 16 | 17 | @Override 18 | public String toString() { 19 | return "UniformEventsArrival [nanosToNextEvent=" + _nanosToNextEvent + "]"; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /subprojects/parseq-examples/build.gradle: -------------------------------------------------------------------------------- 1 | ext { 2 | description = """parseq-examples illustrates how to use the ParSeq API""" 3 | } 4 | 5 | 6 | dependencies { 7 | compile project(":parseq-http-client") 8 | compile project(":parseq-batching") 9 | compile project(":parseq-lambda-names") 10 | } 11 | 12 | //Since some classes at times use deprecated apis we are ignoring the deprecation warning here. 13 | compileJava.options.compilerArgs += '-Xlint:-deprecation' 14 | -------------------------------------------------------------------------------- /subprojects/parseq-examples/src/main/java/com/linkedin/parseq/example/common/BatchableMockService.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.example.common; 2 | 3 | import java.util.concurrent.ScheduledExecutorService; 4 | 5 | import com.linkedin.parseq.Task; 6 | 7 | public class BatchableMockService extends MockService { 8 | 9 | private final MockServiceBatchingStrategy _strategy; 10 | 11 | public BatchableMockService(ScheduledExecutorService scheduler) { 12 | super(scheduler); 13 | _strategy = new MockServiceBatchingStrategy<>(scheduler); 14 | } 15 | 16 | public MockServiceBatchingStrategy getStrategy() { 17 | return _strategy; 18 | } 19 | 20 | Task task(String desc, MockRequest request) { 21 | return _strategy.batchable(desc, request); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /subprojects/parseq-examples/src/main/java/com/linkedin/parseq/example/common/ErrorMockRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq.example.common; 18 | 19 | /** 20 | * @author Chris Pettitt (cpettitt@linkedin.com) 21 | */ 22 | public class ErrorMockRequest implements MockRequest { 23 | private final long _latency; 24 | private final Exception _error; 25 | 26 | public ErrorMockRequest(final long latency, final Exception error) { 27 | _latency = latency; 28 | _error = error; 29 | } 30 | 31 | public long getLatency() { 32 | return _latency; 33 | } 34 | 35 | @Override 36 | public T getResult() throws Exception { 37 | throw _error; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /subprojects/parseq-examples/src/main/java/com/linkedin/parseq/example/common/MockRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq.example.common; 18 | 19 | /** 20 | * @author Chris Pettitt (cpettitt@linkedin.com) 21 | */ 22 | public interface MockRequest { 23 | long getLatency(); 24 | 25 | RES getResult() throws Exception; 26 | } 27 | -------------------------------------------------------------------------------- /subprojects/parseq-examples/src/main/java/com/linkedin/parseq/example/common/MockRequestWithKey.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.example.common; 2 | 3 | public class MockRequestWithKey implements MockRequest { 4 | 5 | private final MockRequest _request; 6 | private final K _key; 7 | 8 | public MockRequestWithKey(K key, MockRequest request) { 9 | _key = key; 10 | _request = request; 11 | } 12 | 13 | @Override 14 | public long getLatency() { 15 | return _request.getLatency(); 16 | } 17 | 18 | @Override 19 | public RES getResult() throws Exception { 20 | return _request.getResult(); 21 | } 22 | 23 | public K getKey() { 24 | return _key; 25 | } 26 | 27 | @Override 28 | public int hashCode() { 29 | final int prime = 31; 30 | int result = 1; 31 | result = prime * result + ((_key == null) ? 0 : _key.hashCode()); 32 | return result; 33 | } 34 | 35 | @Override 36 | public boolean equals(Object obj) { 37 | if (this == obj) 38 | return true; 39 | if (obj == null) 40 | return false; 41 | if (getClass() != obj.getClass()) 42 | return false; 43 | MockRequestWithKey other = (MockRequestWithKey) obj; 44 | if (_key == null) { 45 | if (other._key != null) 46 | return false; 47 | } else if (!_key.equals(other._key)) 48 | return false; 49 | return true; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /subprojects/parseq-examples/src/main/java/com/linkedin/parseq/example/common/MockServiceBatchingStrategy.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.example.common; 2 | 3 | import java.util.concurrent.ScheduledExecutorService; 4 | import java.util.concurrent.TimeUnit; 5 | 6 | import com.linkedin.parseq.batching.Batch; 7 | import com.linkedin.parseq.batching.BatchImpl.BatchEntry; 8 | import com.linkedin.parseq.batching.BatchingStrategy; 9 | 10 | public class MockServiceBatchingStrategy extends BatchingStrategy, RES> { 11 | 12 | protected final ScheduledExecutorService _scheduler; 13 | 14 | public MockServiceBatchingStrategy(ScheduledExecutorService scheduler) { 15 | _scheduler = scheduler; 16 | } 17 | 18 | @Override 19 | public void executeBatch(Integer group, Batch, RES> batch) { 20 | long maxLatency = batch.keys().stream().mapToLong(MockRequest::getLatency).max().getAsLong(); 21 | _scheduler.schedule(() -> { 22 | try { 23 | batch.foreach((req, promise) -> { 24 | try { 25 | promise.done(req.getResult()); 26 | } catch (Exception e) { 27 | promise.fail(e); 28 | } 29 | }); 30 | } catch (Exception e) { 31 | batch.failAll(e); 32 | } 33 | }, maxLatency, TimeUnit.MILLISECONDS); 34 | } 35 | 36 | @Override 37 | public Integer classify(MockRequest key) { 38 | return 0; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /subprojects/parseq-examples/src/main/java/com/linkedin/parseq/example/common/SimpleMockRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq.example.common; 18 | 19 | /** 20 | * @author Chris Pettitt (cpettitt@linkedin.com) 21 | */ 22 | public class SimpleMockRequest implements MockRequest { 23 | private final long _latency; 24 | private final RES _result; 25 | 26 | public SimpleMockRequest(final long latency, final RES result) { 27 | _latency = latency; 28 | _result = result; 29 | } 30 | 31 | public long getLatency() { 32 | return _latency; 33 | } 34 | 35 | public RES getResult() { 36 | return _result; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /subprojects/parseq-examples/src/main/java/com/linkedin/parseq/example/composite/classifier/Classification.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq.example.composite.classifier; 18 | 19 | /** 20 | * @author Chris Pettitt (cpettitt@linkedin.com) 21 | */ 22 | public enum Classification { 23 | FULL_VISIBILITY, 24 | PARTIAL_VISIBILITY, 25 | NO_VISIBILITY 26 | } 27 | -------------------------------------------------------------------------------- /subprojects/parseq-examples/src/main/java/com/linkedin/parseq/example/composite/classifier/Classifier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq.example.composite.classifier; 18 | 19 | /** 20 | * @author Chris Pettitt 21 | */ 22 | public interface Classifier { 23 | Classification classify(long vieweeId); 24 | } 25 | -------------------------------------------------------------------------------- /subprojects/parseq-examples/src/main/java/com/linkedin/parseq/example/composite/classifier/ConnectedClassifier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq.example.composite.classifier; 18 | 19 | /** 20 | * @author Chris Pettitt (cpettitt@linkedin.com) 21 | */ 22 | public class ConnectedClassifier implements Classifier { 23 | private final Network _subnet; 24 | 25 | public ConnectedClassifier(final Network subnet) { 26 | _subnet = subnet; 27 | } 28 | 29 | @Override 30 | public Classification classify(final long vieweeId) { 31 | return _subnet != null && Network.Distance.D1.equals(_subnet.getDistance(vieweeId)) ? Classification.FULL_VISIBILITY 32 | : null; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /subprojects/parseq-examples/src/main/java/com/linkedin/parseq/example/composite/classifier/DefaultClassifier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq.example.composite.classifier; 18 | 19 | /** 20 | * @author Chris Pettitt (cpettitt@linkedin.com) 21 | */ 22 | public class DefaultClassifier implements Classifier { 23 | private static DefaultClassifier INSTANCE = new DefaultClassifier(); 24 | 25 | public static DefaultClassifier instance() { 26 | return INSTANCE; 27 | } 28 | 29 | @Override 30 | public Classification classify(final long vieweeId) { 31 | return Classification.NO_VISIBILITY; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /subprojects/parseq-examples/src/main/java/com/linkedin/parseq/example/composite/classifier/NetworkClassifier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq.example.composite.classifier; 18 | 19 | /** 20 | * @author Chris Pettitt (cpettitt@linkedin.com) 21 | */ 22 | public class NetworkClassifier implements Classifier { 23 | private final Network _subnet; 24 | 25 | public NetworkClassifier(final Network subnet) { 26 | _subnet = subnet; 27 | } 28 | 29 | @Override 30 | public Classification classify(final long vieweeId) { 31 | final Network.Distance distance = _subnet.getDistance(vieweeId); 32 | 33 | return Network.Distance.D2.equals(distance) || Network.Distance.D3.equals(distance) 34 | ? Classification.PARTIAL_VISIBILITY : null; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /subprojects/parseq-examples/src/main/java/com/linkedin/parseq/example/composite/classifier/SelfClassifier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq.example.composite.classifier; 18 | 19 | /** 20 | * @author Chris Pettitt (cpettitt@linkedin.com) 21 | */ 22 | public class SelfClassifier implements Classifier { 23 | private final long viewerId; 24 | 25 | public SelfClassifier(final long viewerId) { 26 | this.viewerId = viewerId; 27 | } 28 | 29 | @Override 30 | public Classification classify(final long vieweeId) { 31 | return vieweeId == viewerId ? Classification.FULL_VISIBILITY : null; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /subprojects/parseq-examples/src/main/java/com/linkedin/parseq/example/composite/classifier/TruthMapClassifier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq.example.composite.classifier; 18 | 19 | import java.util.Map; 20 | 21 | 22 | /** 23 | * @author Chris Pettitt (cpettitt@linkedin.com) 24 | */ 25 | public class TruthMapClassifier implements Classifier { 26 | private final Classification _classification; 27 | private final Map _truthMap; 28 | 29 | public TruthMapClassifier(Classification classification, Map truthMap) { 30 | _classification = classification; 31 | _truthMap = truthMap; 32 | } 33 | 34 | @Override 35 | public Classification classify(final long vieweeId) { 36 | final Boolean b = _truthMap.get(vieweeId); 37 | return b != null && b ? _classification : null; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /subprojects/parseq-examples/src/main/java/com/linkedin/parseq/example/composite/classifier/client/Client.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq.example.composite.classifier.client; 18 | 19 | import com.linkedin.parseq.promise.Promise; 20 | 21 | 22 | /** 23 | * @author Chris Pettitt (cpettitt@linkedin.com) 24 | */ 25 | public interface Client { 26 | Promise sendRequest(final Request request); 27 | } 28 | -------------------------------------------------------------------------------- /subprojects/parseq-examples/src/main/java/com/linkedin/parseq/example/composite/classifier/client/Request.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq.example.composite.classifier.client; 18 | 19 | /** 20 | * @author Chris Pettitt (cpettitt@linkedin.com) 21 | */ 22 | public interface Request { 23 | T getResponse(); 24 | 25 | int getLatencyMean(); 26 | 27 | int getLatencyStdDev(); 28 | 29 | String getName(); 30 | } 31 | -------------------------------------------------------------------------------- /subprojects/parseq-examples/src/main/java/com/linkedin/parseq/example/composite/classifier/client/impl/AbstractRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq.example.composite.classifier.client.impl; 18 | 19 | import com.linkedin.parseq.example.composite.classifier.client.Request; 20 | 21 | 22 | /** 23 | * @author Chris Pettitt (cpettitt@linkedin.com) 24 | */ 25 | public abstract class AbstractRequest implements Request { 26 | private static final int DEFAULT_LATENCY_MEAN = 100; 27 | private static final int DEFAULT_LATENCY_STDDEV = 50; 28 | 29 | @Override 30 | public int getLatencyMean() { 31 | return DEFAULT_LATENCY_MEAN; 32 | } 33 | 34 | @Override 35 | public int getLatencyStdDev() { 36 | return DEFAULT_LATENCY_STDDEV; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /subprojects/parseq-examples/src/main/java/com/linkedin/parseq/example/composite/classifier/client/impl/GetNetworkRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq.example.composite.classifier.client.impl; 18 | 19 | import com.linkedin.parseq.example.composite.classifier.Network; 20 | 21 | 22 | /** 23 | * @author Chris Pettitt (cpettitt@linkedin.com) 24 | */ 25 | public class GetNetworkRequest extends AbstractRequest { 26 | private final long _memberId; 27 | 28 | public GetNetworkRequest(final long memberId) { 29 | _memberId = memberId; 30 | } 31 | 32 | @Override 33 | public Network getResponse() { 34 | return new Network(_memberId); 35 | } 36 | 37 | @Override 38 | public String getName() { 39 | return "getNetwork"; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /subprojects/parseq-examples/src/main/java/com/linkedin/parseq/example/domain/AsyncPersonClient.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.example.domain; 2 | 3 | import java.util.Collection; 4 | import java.util.Map; 5 | import java.util.concurrent.CompletableFuture; 6 | 7 | public interface AsyncPersonClient { 8 | CompletableFuture get(Long id); 9 | CompletableFuture> batchGet(Collection ids); 10 | } 11 | -------------------------------------------------------------------------------- /subprojects/parseq-examples/src/main/java/com/linkedin/parseq/example/domain/Company.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.example.domain; 2 | 3 | public class Company { 4 | final String _name; 5 | 6 | public Company(String name) { 7 | _name = name; 8 | } 9 | 10 | public String getName() { 11 | return _name; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /subprojects/parseq-examples/src/main/java/com/linkedin/parseq/example/domain/Message.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.example.domain; 2 | 3 | public class Message { 4 | final int _fromId; 5 | final int _toId; 6 | final String _title; 7 | final String _contents; 8 | 9 | public Message(int fromId, int toId, String title, String contents) { 10 | _fromId = fromId; 11 | _toId = toId; 12 | _title = title; 13 | _contents = contents; 14 | } 15 | 16 | public int getFromId() { 17 | return _fromId; 18 | } 19 | 20 | public int getToId() { 21 | return _toId; 22 | } 23 | 24 | public String getTitle() { 25 | return _title; 26 | } 27 | 28 | public String getContents() { 29 | return _contents; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /subprojects/parseq-examples/src/main/java/com/linkedin/parseq/example/domain/ParSeqPersonClient.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.example.domain; 2 | 3 | import com.linkedin.parseq.Task; 4 | import com.linkedin.parseq.batching.Batch; 5 | import com.linkedin.parseq.batching.SimpleBatchingStrategy; 6 | 7 | public class ParSeqPersonClient extends SimpleBatchingStrategy { 8 | 9 | private final AsyncPersonClient _client; 10 | 11 | public ParSeqPersonClient(AsyncPersonClient client) { 12 | _client = client; 13 | } 14 | 15 | public Task get(Long id) { 16 | return batchable("fetch Person " + id, id); 17 | } 18 | 19 | @Override 20 | public void executeBatch(Batch batch) { 21 | _client.batchGet(batch.keys()).whenComplete((results, exception) -> { 22 | if (exception != null) { 23 | // batch operation failed so we need to fail all promises 24 | batch.failAll(exception); 25 | } else { 26 | // complete promises with values from results 27 | batch.foreach((key, promise) -> promise.done(results.get(key))); 28 | } 29 | }); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /subprojects/parseq-examples/src/main/java/com/linkedin/parseq/example/domain/Person.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.example.domain; 2 | 3 | import java.util.List; 4 | 5 | 6 | public class Person { 7 | 8 | final int _id; 9 | final String _firstName; 10 | final String _lastName; 11 | final int _companyId; 12 | final List _connections; 13 | 14 | public Person(int id, String firstName, String lastName, int companyId, List connections) { 15 | _firstName = firstName; 16 | _lastName = lastName; 17 | _companyId = companyId; 18 | _connections = connections; 19 | _id = id; 20 | } 21 | 22 | public String getFirstName() { 23 | return _firstName; 24 | } 25 | 26 | public String getLastName() { 27 | return _lastName; 28 | } 29 | 30 | public int getCompanyId() { 31 | return _companyId; 32 | } 33 | 34 | public List getConnections() { 35 | return _connections; 36 | } 37 | 38 | public int getId() { 39 | return _id; 40 | } 41 | 42 | @Override 43 | public String toString() { 44 | return "Person [_id=" + _id + ", _firstName=" + _firstName + ", _lastName=" + _lastName + ", _companyId=" 45 | + _companyId + ", _connections=" + _connections + "]"; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /subprojects/parseq-examples/src/main/java/com/linkedin/parseq/example/simple/DegradedExperienceExample.java: -------------------------------------------------------------------------------- 1 | /* $Id$ */ 2 | package com.linkedin.parseq.example.simple; 3 | 4 | import static com.linkedin.parseq.example.common.ExampleUtil.fetchUrl; 5 | 6 | import java.util.concurrent.TimeUnit; 7 | 8 | import com.linkedin.parseq.Engine; 9 | import com.linkedin.parseq.Task; 10 | import com.linkedin.parseq.example.common.AbstractExample; 11 | import com.linkedin.parseq.example.common.ExampleUtil; 12 | import com.linkedin.parseq.example.common.MockService; 13 | 14 | 15 | /** 16 | * @author Jaroslaw Odzga (jodzga@linkedin.com) 17 | */ 18 | public class DegradedExperienceExample extends AbstractExample { 19 | public static void main(String[] args) throws Exception { 20 | new DegradedExperienceExample().runExample(); 21 | } 22 | 23 | @Override 24 | protected void doRunExample(final Engine engine) throws Exception { 25 | final MockService httpClient = getService(); 26 | 27 | final Task fetchAndLength = 28 | fetchUrl(httpClient, "http://www.google.com", 100) 29 | .withTimeout(50, TimeUnit.MILLISECONDS) 30 | .recover("default", t -> "") 31 | .map("length", s -> s.length()); 32 | 33 | engine.run(fetchAndLength); 34 | 35 | fetchAndLength.await(); 36 | 37 | System.out.println("Response length: " + fetchAndLength.get()); 38 | 39 | ExampleUtil.printTracingResults(fetchAndLength); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /subprojects/parseq-examples/src/main/java/com/linkedin/parseq/example/simple/ErrorPropagationExample.java: -------------------------------------------------------------------------------- 1 | /* $Id$ */ 2 | package com.linkedin.parseq.example.simple; 3 | 4 | import static com.linkedin.parseq.example.common.ExampleUtil.fetch404Url; 5 | 6 | import com.linkedin.parseq.Engine; 7 | import com.linkedin.parseq.Task; 8 | import com.linkedin.parseq.example.common.AbstractExample; 9 | import com.linkedin.parseq.example.common.ExampleUtil; 10 | import com.linkedin.parseq.example.common.MockService; 11 | 12 | 13 | /** 14 | * @author Chris Pettitt (cpettitt@linkedin.com) 15 | * @author Jaroslaw Odzga (jodzga@linkedin.com) 16 | */ 17 | public class ErrorPropagationExample extends AbstractExample { 18 | public static void main(String[] args) throws Exception { 19 | new ErrorPropagationExample().runExample(); 20 | } 21 | 22 | @Override 23 | protected void doRunExample(final Engine engine) throws Exception { 24 | final MockService httpClient = getService(); 25 | 26 | final Task fetchAndLength = 27 | fetch404Url(httpClient, "http://www.google.com") 28 | .map("length", x -> x.length()); 29 | 30 | engine.run(fetchAndLength); 31 | 32 | fetchAndLength.await(); 33 | 34 | System.out.println("Error while fetching url: " + fetchAndLength.getError()); 35 | 36 | ExampleUtil.printTracingResults(fetchAndLength); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /subprojects/parseq-examples/src/main/java/com/linkedin/parseq/example/simple/ErrorRecoveryExample.java: -------------------------------------------------------------------------------- 1 | /* $Id$ */ 2 | package com.linkedin.parseq.example.simple; 3 | 4 | import static com.linkedin.parseq.example.common.ExampleUtil.fetch404Url; 5 | 6 | import com.linkedin.parseq.Engine; 7 | import com.linkedin.parseq.Task; 8 | import com.linkedin.parseq.example.common.AbstractExample; 9 | import com.linkedin.parseq.example.common.ExampleUtil; 10 | import com.linkedin.parseq.example.common.MockService; 11 | 12 | 13 | /** 14 | * @author Chris Pettitt (cpettitt@linkedin.com) 15 | * @author Jaroslaw Odzga (jodzga@linkedin.com) 16 | */ 17 | public class ErrorRecoveryExample extends AbstractExample { 18 | public static void main(String[] args) throws Exception { 19 | new ErrorRecoveryExample().runExample(); 20 | } 21 | 22 | @Override 23 | protected void doRunExample(final Engine engine) throws Exception { 24 | final MockService httpClient = getService(); 25 | 26 | final Task fetchAndLength = 27 | fetch404Url(httpClient, "http://www.google.com") 28 | .recover("default", t -> "") 29 | .map("length", s -> s.length()); 30 | 31 | engine.run(fetchAndLength); 32 | 33 | fetchAndLength.await(); 34 | 35 | System.out.println("Response length: " + fetchAndLength.get()); 36 | 37 | ExampleUtil.printTracingResults(fetchAndLength); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /subprojects/parseq-examples/src/main/java/com/linkedin/parseq/example/simple/TimeoutWithErrorExample.java: -------------------------------------------------------------------------------- 1 | /* $Id$ */ 2 | package com.linkedin.parseq.example.simple; 3 | 4 | import static com.linkedin.parseq.example.common.ExampleUtil.fetchUrl; 5 | 6 | import java.util.concurrent.TimeUnit; 7 | 8 | import com.linkedin.parseq.Engine; 9 | import com.linkedin.parseq.Task; 10 | import com.linkedin.parseq.example.common.AbstractExample; 11 | import com.linkedin.parseq.example.common.ExampleUtil; 12 | import com.linkedin.parseq.example.common.MockService; 13 | 14 | 15 | /** 16 | * @author Chris Pettitt (cpettitt@linkedin.com) 17 | * @author Jaroslaw Odzga (jodzga@linkedin.com) 18 | */ 19 | public class TimeoutWithErrorExample extends AbstractExample { 20 | public static void main(String[] args) throws Exception { 21 | new TimeoutWithErrorExample().runExample(); 22 | } 23 | 24 | @Override 25 | protected void doRunExample(final Engine engine) throws Exception { 26 | final MockService httpClient = getService(); 27 | 28 | final Task fetchWithTimeout = 29 | fetchUrl(httpClient, "http://www.google.com") 30 | .withTimeout(50, TimeUnit.MILLISECONDS); 31 | 32 | engine.run(fetchWithTimeout); 33 | 34 | fetchWithTimeout.await(); 35 | 36 | System.out.println(!fetchWithTimeout.isFailed() ? "Received result: " + fetchWithTimeout.get() 37 | : "Error: " + fetchWithTimeout.getError()); 38 | 39 | ExampleUtil.printTracingResults(fetchWithTimeout); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /subprojects/parseq-exec/build.gradle: -------------------------------------------------------------------------------- 1 | ext { 2 | description = """Integrates ParSeq with the Java Process API""" 3 | } 4 | -------------------------------------------------------------------------------- /subprojects/parseq-guava-interop/build.gradle: -------------------------------------------------------------------------------- 1 | ext { 2 | description = """Interop with Guava's ListenableFuture""" 3 | } 4 | 5 | dependencies { 6 | compile project(":parseq") 7 | compile "com.google.guava:guava:30.1.1-jre" 8 | 9 | testCompile project(':parseq-test-api') 10 | testCompile "org.testng:testng:6.9.9" 11 | } -------------------------------------------------------------------------------- /subprojects/parseq-http-client/build.gradle: -------------------------------------------------------------------------------- 1 | ext { 2 | description = """Integrates ParSeq with the Async Http Client library""" 3 | } 4 | 5 | dependencies { 6 | compile group: 'com.ning', name: 'async-http-client', version:'1.9.21' 7 | } 8 | -------------------------------------------------------------------------------- /subprojects/parseq-lambda-names/build.gradle: -------------------------------------------------------------------------------- 1 | ext { 2 | description = """Finds source code locations and infers operations for lambda expressions""" 3 | } 4 | 5 | apply plugin: 'com.github.johnrengelman.shadow' 6 | 7 | 8 | configurations { 9 | testRuntime.extendsFrom shadow 10 | } 11 | 12 | dependencies { 13 | shadow group: 'net.bytebuddy', name: 'byte-buddy-agent', version: '1.14.13' 14 | shadow group: 'net.bytebuddy', name: 'byte-buddy-dep', version: '1.14.13' 15 | shadow group: 'org.ow2.asm', name: 'asm-tree', version: '9.6' 16 | shadow group: 'org.ow2.asm', name: 'asm', version: '9.6' 17 | shadow group: 'org.ow2.asm', name: 'asm-analysis', version: '9.6' 18 | testCompile group: 'org.testng', name: 'testng', version: '7.3.0' 19 | } 20 | 21 | sourceSets.main.compileClasspath += configurations.shadow + sourceSets.main.compileClasspath 22 | 23 | javadoc.classpath += configurations.shadow + sourceSets.main.compileClasspath 24 | 25 | shadowJar { 26 | configurations += [project.configurations.shadow] 27 | classifier = null 28 | relocate 'org.objectweb', 'parseq.org.objectweb' 29 | relocate 'net.bytebuddy', 'parseq.net.bytebuddy' 30 | } 31 | 32 | jar { 33 | finalizedBy shadowJar // The shadowJar task basically overwrites the output of the jar task (kind of hacky) 34 | } 35 | 36 | compileJava.options.compilerArgs += '-Xlint:-unchecked' -------------------------------------------------------------------------------- /subprojects/parseq-lambda-names/setjdk_osx: -------------------------------------------------------------------------------- 1 | function setjdk() { 2 | if [ $# -ne 0 ]; then 3 | removeFromPath '/System/Library/Frameworks/JavaVM.framework/Home/bin' 4 | if [ -n "${JAVA_HOME+x}" ]; then 5 | removeFromPath $JAVA_HOME 6 | fi 7 | export JAVA_HOME=`/usr/libexec/java_home -v $@` 8 | export PATH=$JAVA_HOME/bin:$PATH 9 | fi 10 | } 11 | function removeFromPath() { 12 | export PATH=$(echo $PATH | sed -E -e "s;:$1;;" -e "s;$1:?;;") 13 | } 14 | -------------------------------------------------------------------------------- /subprojects/parseq-lambda-names/src/main/java/com/linkedin/parseq/TaskDescriptor.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq; 2 | 3 | /** 4 | * An API to provide description for task. 5 | * 6 | * parseq-lambda-names provide an implementation for this interface using Java SPI. Any changes made to this interface 7 | * might require a change to implementation in parseq-lambda-names. 8 | * 9 | * The implementation doesnt need to be thread-safe. 10 | * 11 | * @author Siddharth Sodhani (ssodhani@linkedin.com) 12 | */ 13 | public interface TaskDescriptor { 14 | 15 | /** 16 | * Give class name which could correspond to generated lambda expressions etc infer appropriate description for it 17 | * If it is unable to infer description, it returns className 18 | * 19 | * @param className 20 | * @return description for task it can be inferred else returns className 21 | */ 22 | String getDescription(String className); 23 | } 24 | -------------------------------------------------------------------------------- /subprojects/parseq-lambda-names/src/main/java/com/linkedin/parseq/lambda/InferredOperation.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.lambda; 2 | 3 | class InferredOperation { 4 | 5 | private final String _functionName; 6 | 7 | InferredOperation(String functionName) { 8 | _functionName = functionName; 9 | } 10 | 11 | @Override 12 | public String toString() { 13 | return _functionName == null ? "" : _functionName; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /subprojects/parseq-lambda-names/src/main/java/com/linkedin/parseq/lambda/LambdaClassDescription.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.lambda; 2 | 3 | import java.util.Optional; 4 | 5 | 6 | class LambdaClassDescription { 7 | 8 | private final String _className; 9 | private final SourcePointer _sourcePointer; 10 | private final Optional _inferredOperationOptional; 11 | 12 | LambdaClassDescription(String className, SourcePointer sourcePointer, 13 | InferredOperation inferredOperation) { 14 | _className = className; 15 | _sourcePointer = sourcePointer; 16 | _inferredOperationOptional = inferredOperation == null ? Optional.empty() : Optional.of(inferredOperation); 17 | } 18 | 19 | String getDescription() { 20 | StringBuilder builder = new StringBuilder(); 21 | if (_inferredOperationOptional.isPresent()) { 22 | String desc = _inferredOperationOptional.get().toString(); 23 | if (!desc.isEmpty()) { 24 | builder.append(desc).append(" "); 25 | } 26 | } 27 | 28 | builder.append(_sourcePointer); 29 | return builder.toString(); 30 | } 31 | 32 | String getClassName() { 33 | return _className; 34 | } 35 | 36 | @Override 37 | public String toString() { 38 | return getDescription(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /subprojects/parseq-lambda-names/src/main/resources/META-INF/services/com.linkedin.parseq.TaskDescriptor: -------------------------------------------------------------------------------- 1 | com.linkedin.parseq.lambda.ASMBasedTaskDescriptor 2 | -------------------------------------------------------------------------------- /subprojects/parseq-lambda-names/src/test/java/com/linkedin/parseq/lambda/TestStaticMethodInv.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.lambda; 2 | 3 | import java.util.Optional; 4 | import org.testng.annotations.Test; 5 | 6 | import static org.testng.Assert.assertTrue; 7 | 8 | 9 | public class TestStaticMethodInv extends BaseTest { 10 | 11 | private static final String CLASSNAME = TestStaticMethodInv.class.getSimpleName(); 12 | 13 | @Test 14 | public void testStaticFunction() { 15 | Optional description = getDescriptionForFunction(s -> BaseTest.staticFunction(s)); 16 | assertTrue(description.isPresent()); 17 | assertNameMatch("BaseTest.staticFunction(_)", "testStaticFunction", CLASSNAME, 15, description.get().toString()); 18 | } 19 | 20 | @Test 21 | public void testStaticCallable() { 22 | Optional description = getDescriptionForCallable(() -> BaseTest.staticCallable()); 23 | assertTrue(description.isPresent()); 24 | assertNameMatch("BaseTest.staticCallable()", "testStaticCallable", CLASSNAME, 22, description.get().toString()); 25 | } 26 | 27 | @Test 28 | public void testStaticConsumer() { 29 | Optional description = getDescriptionForConsumer(s 30 | -> 31 | BaseTest.staticConsumer(s)); 32 | assertTrue(description.isPresent()); 33 | assertNameMatch("BaseTest.staticConsumer(_)", "testStaticConsumer", CLASSNAME, 31, description.get().toString()); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /subprojects/parseq-lambda-names/src/test/java/com/linkedin/parseq/lambda/TestStaticMethodRef.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.lambda; 2 | 3 | import java.util.Optional; 4 | import org.testng.annotations.Test; 5 | 6 | import static org.testng.Assert.assertTrue; 7 | 8 | 9 | public class TestStaticMethodRef extends BaseTest { 10 | 11 | private static final String CLASSNAME = TestStaticMethodRef.class.getSimpleName(); 12 | 13 | @Test 14 | public void testStaticFunction() { 15 | Optional description = getDescriptionForFunction(BaseTest::staticFunction); 16 | assertTrue(description.isPresent()); 17 | assertNameMatch("BaseTest::staticFunction", "testStaticFunction", CLASSNAME, description.get().toString()); 18 | } 19 | 20 | @Test 21 | public void testStaticCallable() { 22 | Optional description = getDescriptionForCallable(BaseTest::staticCallable); 23 | assertTrue(description.isPresent()); 24 | assertNameMatch("BaseTest::staticCallable", "testStaticCallable", CLASSNAME, description.get().toString()); 25 | } 26 | 27 | @Test 28 | public void testStaticConsumer() { 29 | Optional description = getDescriptionForConsumer(BaseTest::staticConsumer); 30 | assertTrue(description.isPresent()); 31 | assertNameMatch("BaseTest::staticConsumer", "testStaticConsumer", CLASSNAME, description.get().toString()); 32 | } 33 | } -------------------------------------------------------------------------------- /subprojects/parseq-lambda-names/src/test/java/com/linkedin/parseq/lambda/TestUtil.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.lambda; 2 | 3 | import org.testng.annotations.Test; 4 | 5 | import static com.linkedin.parseq.lambda.Util.*; 6 | import static org.testng.Assert.*; 7 | 8 | 9 | public class TestUtil { 10 | @Test 11 | public void testRegexForLambdaClassName() { 12 | String lambdaIdentifierInHotSpot = "HelloWorld$$Lambda$1"; 13 | String lambdaIdentifierInZing = "HelloWorld$$Lambda$lambda$main$0$1310938867"; 14 | 15 | assertTrue(isALambdaClassByName(lambdaIdentifierInHotSpot)); 16 | assertTrue(isALambdaClassByName(lambdaIdentifierInZing)); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /subprojects/parseq-lambda-names/supported_jvms: -------------------------------------------------------------------------------- 1 | 1.8.0_212 2 | 11.0.8 3 | 13.0.4 4 | 14.0.2 5 | -------------------------------------------------------------------------------- /subprojects/parseq-lambda-names/test_supported_jvms: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | source setjdk_osx 6 | 7 | while IFS= read -r jvm 8 | do 9 | echo "Testing with $jvm" 10 | if [ "$(uname)" == "Darwin" ]; then 11 | setjdk $jvm 12 | elif [ "$(uname)" == "Linux" ]; then 13 | export JAVA_HOME=$(readlink -f $(which javac) | sed "s:JDK-.*:JDK-$jvm:") 14 | echo "Setting JAVA_HOME to $JAVA_HOME" 15 | fi 16 | ../../gradlew clean test --info --rerun-tasks --warning-mode all implements MockRequest 23 | { 24 | private final long _latency; 25 | private final Exception _error; 26 | 27 | public ErrorMockRequest(final long latency, final Exception error) 28 | { 29 | _latency = latency; 30 | _error = error; 31 | } 32 | 33 | public long getLatency() 34 | { 35 | return _latency; 36 | } 37 | 38 | @Override 39 | public T getResult() throws Exception 40 | { 41 | throw _error; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /subprojects/parseq-legacy-examples/src/main/java/com/linkedin/parseq/example/common/MockRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq.example.common; 18 | 19 | /** 20 | * @author Chris Pettitt (cpettitt@linkedin.com) 21 | */ 22 | public interface MockRequest 23 | { 24 | long getLatency(); 25 | 26 | RES getResult() throws Exception; 27 | } 28 | -------------------------------------------------------------------------------- /subprojects/parseq-legacy-examples/src/main/java/com/linkedin/parseq/example/common/SimpleMockRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq.example.common; 18 | 19 | /** 20 | * @author Chris Pettitt (cpettitt@linkedin.com) 21 | */ 22 | public class SimpleMockRequest implements MockRequest 23 | { 24 | private final long _latency; 25 | private final RES _result; 26 | 27 | public SimpleMockRequest(final long latency, final RES result) 28 | { 29 | _latency = latency; 30 | _result = result; 31 | } 32 | 33 | public long getLatency() 34 | { 35 | return _latency; 36 | } 37 | 38 | public RES getResult() 39 | { 40 | return _result; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /subprojects/parseq-legacy-examples/src/main/java/com/linkedin/parseq/example/composite/classifier/Classification.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq.example.composite.classifier; 18 | 19 | /** 20 | * @author Chris Pettitt (cpettitt@linkedin.com) 21 | */ 22 | public enum Classification 23 | { 24 | FULL_VISIBILITY, 25 | PARTIAL_VISIBILITY, 26 | NO_VISIBILITY 27 | } 28 | -------------------------------------------------------------------------------- /subprojects/parseq-legacy-examples/src/main/java/com/linkedin/parseq/example/composite/classifier/Classifier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq.example.composite.classifier; 18 | 19 | /** 20 | * @author Chris Pettitt 21 | * @version $Revision$ 22 | */ 23 | public interface Classifier 24 | { 25 | Classification classify(long vieweeId); 26 | } 27 | -------------------------------------------------------------------------------- /subprojects/parseq-legacy-examples/src/main/java/com/linkedin/parseq/example/composite/classifier/ConnectedClassifier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq.example.composite.classifier; 18 | 19 | /** 20 | * @author Chris Pettitt (cpettitt@linkedin.com) 21 | */ 22 | public class ConnectedClassifier implements Classifier 23 | { 24 | private final Network _subnet; 25 | 26 | public ConnectedClassifier(final Network subnet) 27 | { 28 | _subnet = subnet; 29 | } 30 | 31 | @Override 32 | public Classification classify(final long vieweeId) 33 | { 34 | return _subnet != null && Network.Distance.D1.equals(_subnet.getDistance(vieweeId)) 35 | ? Classification.FULL_VISIBILITY 36 | : null; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /subprojects/parseq-legacy-examples/src/main/java/com/linkedin/parseq/example/composite/classifier/DefaultClassifier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq.example.composite.classifier; 18 | 19 | /** 20 | * @author Chris Pettitt (cpettitt@linkedin.com) 21 | */ 22 | public class DefaultClassifier implements Classifier 23 | { 24 | private static DefaultClassifier INSTANCE = new DefaultClassifier(); 25 | 26 | public static DefaultClassifier instance() 27 | { 28 | return INSTANCE; 29 | } 30 | 31 | @Override 32 | public Classification classify(final long vieweeId) 33 | { 34 | return Classification.NO_VISIBILITY; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /subprojects/parseq-legacy-examples/src/main/java/com/linkedin/parseq/example/composite/classifier/NetworkClassifier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq.example.composite.classifier; 18 | 19 | /** 20 | * @author Chris Pettitt (cpettitt@linkedin.com) 21 | */ 22 | public class NetworkClassifier implements Classifier 23 | { 24 | private final Network _subnet; 25 | 26 | public NetworkClassifier(final Network subnet) 27 | { 28 | _subnet = subnet; 29 | } 30 | 31 | @Override 32 | public Classification classify(final long vieweeId) 33 | { 34 | final Network.Distance distance = _subnet.getDistance(vieweeId); 35 | 36 | return Network.Distance.D2.equals(distance) || Network.Distance.D3.equals(distance) 37 | ? Classification.PARTIAL_VISIBILITY 38 | : null; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /subprojects/parseq-legacy-examples/src/main/java/com/linkedin/parseq/example/composite/classifier/SelfClassifier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq.example.composite.classifier; 18 | 19 | /** 20 | * @author Chris Pettitt (cpettitt@linkedin.com) 21 | */ 22 | public class SelfClassifier implements Classifier 23 | { 24 | private final long viewerId; 25 | 26 | public SelfClassifier(final long viewerId) 27 | { 28 | this.viewerId = viewerId; 29 | } 30 | 31 | @Override 32 | public Classification classify(final long vieweeId) 33 | { 34 | return vieweeId == viewerId 35 | ? Classification.FULL_VISIBILITY 36 | : null; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /subprojects/parseq-legacy-examples/src/main/java/com/linkedin/parseq/example/composite/classifier/TruthMapClassifier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq.example.composite.classifier; 18 | 19 | import java.util.Map; 20 | 21 | /** 22 | * @author Chris Pettitt (cpettitt@linkedin.com) 23 | */ 24 | public class TruthMapClassifier implements Classifier 25 | { 26 | private final Classification _classification; 27 | private final Map _truthMap; 28 | 29 | public TruthMapClassifier(Classification classification, Map truthMap) 30 | { 31 | _classification = classification; 32 | _truthMap = truthMap; 33 | } 34 | 35 | @Override 36 | public Classification classify(final long vieweeId) 37 | { 38 | final Boolean b = _truthMap.get(vieweeId); 39 | return b != null && b 40 | ? _classification 41 | : null; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /subprojects/parseq-legacy-examples/src/main/java/com/linkedin/parseq/example/composite/classifier/client/Client.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq.example.composite.classifier.client; 18 | 19 | import com.linkedin.parseq.promise.Promise; 20 | 21 | /** 22 | * @author Chris Pettitt (cpettitt@linkedin.com) 23 | */ 24 | public interface Client 25 | { 26 | Promise sendRequest(final Request request); 27 | } 28 | -------------------------------------------------------------------------------- /subprojects/parseq-legacy-examples/src/main/java/com/linkedin/parseq/example/composite/classifier/client/Request.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq.example.composite.classifier.client; 18 | 19 | /** 20 | * @author Chris Pettitt (cpettitt@linkedin.com) 21 | */ 22 | public interface Request 23 | { 24 | T getResponse(); 25 | 26 | int getLatencyMean(); 27 | 28 | int getLatencyStdDev(); 29 | 30 | String getName(); 31 | } 32 | -------------------------------------------------------------------------------- /subprojects/parseq-legacy-examples/src/main/java/com/linkedin/parseq/example/composite/classifier/client/impl/AbstractRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq.example.composite.classifier.client.impl; 18 | 19 | import com.linkedin.parseq.example.composite.classifier.client.Request; 20 | 21 | /** 22 | * @author Chris Pettitt (cpettitt@linkedin.com) 23 | */ 24 | public abstract class AbstractRequest implements Request 25 | { 26 | private static final int DEFAULT_LATENCY_MEAN = 100; 27 | private static final int DEFAULT_LATENCY_STDDEV = 50; 28 | 29 | @Override 30 | public int getLatencyMean() 31 | { 32 | return DEFAULT_LATENCY_MEAN; 33 | } 34 | 35 | @Override 36 | public int getLatencyStdDev() 37 | { 38 | return DEFAULT_LATENCY_STDDEV; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /subprojects/parseq-legacy-examples/src/main/java/com/linkedin/parseq/example/composite/classifier/client/impl/GetNetworkRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq.example.composite.classifier.client.impl; 18 | 19 | import com.linkedin.parseq.example.composite.classifier.Network; 20 | 21 | /** 22 | * @author Chris Pettitt (cpettitt@linkedin.com) 23 | */ 24 | public class GetNetworkRequest extends AbstractRequest 25 | { 26 | private final long _memberId; 27 | 28 | public GetNetworkRequest(final long memberId) 29 | { 30 | _memberId = memberId; 31 | } 32 | 33 | @Override 34 | public Network getResponse() 35 | { 36 | return new Network(_memberId); 37 | } 38 | 39 | @Override 40 | public String getName() 41 | { 42 | return "getNetwork"; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /subprojects/parseq-restli-client/src/main/antlr4/com/linkedin/restli/client/config/RequestConfigKey.g4: -------------------------------------------------------------------------------- 1 | grammar RequestConfigKey; 2 | 3 | key : inbound '/' outbound EOF; 4 | inbound : ( restResource | '*' ) '.' ( operationIn | '*' ); 5 | outbound : ( restResource | '*' ) '.' ( operationOut | '*' ); 6 | restResource : Name ( '-' Name )* ( ':' Name )*; 7 | operationIn : simpleOp | complex | httpExtraOp; 8 | operationOut : simpleOp | complex; 9 | simpleOp : 'GET' | 'BATCH_GET' | 'CREATE' | 'BATCH_CREATE' | 10 | 'PARTIAL_UPDATE' | 'UPDATE' | 'BATCH_UPDATE' | 11 | 'DELETE' | 'BATCH_PARTIAL_UPDATE' | 'BATCH_DELETE' | 12 | 'GET_ALL' | 'OPTIONS'; 13 | httpExtraOp : 'HEAD' | 'POST' | 'PUT' | 'TRACE' | 'CONNECT'; 14 | complex : complexOp '-' ( Name | '*' ); 15 | complexOp : 'FINDER' | 'ACTION'; 16 | Name : [a-zA-Z0-9]+; 17 | -------------------------------------------------------------------------------- /subprojects/parseq-restli-client/src/main/java/RequestConfigKey.tokens: -------------------------------------------------------------------------------- 1 | T__0=1 2 | T__1=2 3 | T__2=3 4 | T__3=4 5 | T__4=5 6 | T__5=6 7 | T__6=7 8 | T__7=8 9 | T__8=9 10 | T__9=10 11 | T__10=11 12 | T__11=12 13 | T__12=13 14 | T__13=14 15 | T__14=15 16 | T__15=16 17 | T__16=17 18 | T__17=18 19 | T__18=19 20 | T__19=20 21 | T__20=21 22 | T__21=22 23 | T__22=23 24 | T__23=24 25 | Name=25 26 | '/'=1 27 | '*'=2 28 | '.'=3 29 | '-'=4 30 | ':'=5 31 | 'GET'=6 32 | 'BATCH_GET'=7 33 | 'CREATE'=8 34 | 'BATCH_CREATE'=9 35 | 'PARTIAL_UPDATE'=10 36 | 'UPDATE'=11 37 | 'BATCH_UPDATE'=12 38 | 'DELETE'=13 39 | 'BATCH_PARTIAL_UPDATE'=14 40 | 'BATCH_DELETE'=15 41 | 'GET_ALL'=16 42 | 'OPTIONS'=17 43 | 'HEAD'=18 44 | 'POST'=19 45 | 'PUT'=20 46 | 'TRACE'=21 47 | 'CONNECT'=22 48 | 'FINDER'=23 49 | 'ACTION'=24 50 | -------------------------------------------------------------------------------- /subprojects/parseq-restli-client/src/main/java/RequestConfigKeyLexer.tokens: -------------------------------------------------------------------------------- 1 | T__0=1 2 | T__1=2 3 | T__2=3 4 | T__3=4 5 | T__4=5 6 | T__5=6 7 | T__6=7 8 | T__7=8 9 | T__8=9 10 | T__9=10 11 | T__10=11 12 | T__11=12 13 | T__12=13 14 | T__13=14 15 | T__14=15 16 | T__15=16 17 | T__16=17 18 | T__17=18 19 | T__18=19 20 | T__19=20 21 | T__20=21 22 | T__21=22 23 | T__22=23 24 | T__23=24 25 | Name=25 26 | '/'=1 27 | '*'=2 28 | '.'=3 29 | '-'=4 30 | ':'=5 31 | 'GET'=6 32 | 'BATCH_GET'=7 33 | 'CREATE'=8 34 | 'BATCH_CREATE'=9 35 | 'PARTIAL_UPDATE'=10 36 | 'UPDATE'=11 37 | 'BATCH_UPDATE'=12 38 | 'DELETE'=13 39 | 'BATCH_PARTIAL_UPDATE'=14 40 | 'BATCH_DELETE'=15 41 | 'GET_ALL'=16 42 | 'OPTIONS'=17 43 | 'HEAD'=18 44 | 'POST'=19 45 | 'PUT'=20 46 | 'TRACE'=21 47 | 'CONNECT'=22 48 | 'FINDER'=23 49 | 'ACTION'=24 50 | -------------------------------------------------------------------------------- /subprojects/parseq-restli-client/src/main/java/com/linkedin/restli/client/DirectExecutor.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.restli.client; 2 | 3 | import java.util.concurrent.Executor; 4 | 5 | 6 | /** 7 | * A simple executor implementation that executes the task immediately on the calling thread 8 | */ 9 | class DirectExecutor implements Executor { 10 | 11 | private static final DirectExecutor INSTANCE = new DirectExecutor(); 12 | 13 | static DirectExecutor getInstance() { 14 | return INSTANCE; 15 | } 16 | 17 | @Override 18 | public void execute(Runnable command) { 19 | command.run(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /subprojects/parseq-restli-client/src/main/java/com/linkedin/restli/client/InboundRequestContext.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.restli.client; 2 | 3 | import java.util.Optional; 4 | 5 | public interface InboundRequestContext { 6 | 7 | public String getName(); 8 | 9 | public String getMethod(); 10 | 11 | public Optional getFinderName(); 12 | 13 | public Optional getActionName(); 14 | } 15 | -------------------------------------------------------------------------------- /subprojects/parseq-restli-client/src/main/java/com/linkedin/restli/client/InboundRequestContextBuilder.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.restli.client; 2 | 3 | import java.util.Optional; 4 | 5 | public class InboundRequestContextBuilder { 6 | 7 | private String _name; 8 | private String _method; 9 | private String _finderName; 10 | private String _actionName; 11 | 12 | public InboundRequestContextBuilder setName(String name) { 13 | _name = name; 14 | return this; 15 | } 16 | 17 | public InboundRequestContextBuilder setMethod(String method) { 18 | _method = method; 19 | return this; 20 | } 21 | 22 | public InboundRequestContextBuilder setFinderName(String finderName) { 23 | _finderName = finderName; 24 | return this; 25 | } 26 | 27 | public InboundRequestContextBuilder setActionName(String actionName) { 28 | _actionName = actionName; 29 | return this; 30 | } 31 | 32 | public InboundRequestContext build() { 33 | return new InboundRequestContextImpl(_name, _method, Optional.ofNullable(_finderName), Optional.ofNullable(_actionName)); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /subprojects/parseq-restli-client/src/main/java/com/linkedin/restli/client/InboundRequestContextFinder.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.restli.client; 2 | 3 | import java.util.Optional; 4 | 5 | @FunctionalInterface 6 | public interface InboundRequestContextFinder { 7 | Optional find(); 8 | } 9 | -------------------------------------------------------------------------------- /subprojects/parseq-restli-client/src/main/java/com/linkedin/restli/client/ParSeqRestliClientConfig.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.restli.client; 2 | 3 | import java.util.Map; 4 | 5 | public interface ParSeqRestliClientConfig { 6 | 7 | public Map getTimeoutMsConfig(); 8 | 9 | public Map isBatchingEnabledConfig(); 10 | 11 | public Map getMaxBatchSizeConfig(); 12 | } 13 | -------------------------------------------------------------------------------- /subprojects/parseq-restli-client/src/main/java/com/linkedin/restli/client/ParSeqRestliClientConfigChooser.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.restli.client; 2 | 3 | import java.util.Optional; 4 | import java.util.function.BiFunction; 5 | 6 | @FunctionalInterface 7 | public interface ParSeqRestliClientConfigChooser extends BiFunction, Request, String> { 8 | } 9 | -------------------------------------------------------------------------------- /subprojects/parseq-restli-client/src/main/java/com/linkedin/restli/client/ParSeqRestliClientConfigImpl.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.restli.client; 2 | 3 | import java.util.Map; 4 | 5 | class ParSeqRestliClientConfigImpl implements ParSeqRestliClientConfig { 6 | 7 | private final Map _timeoutMsConfig; 8 | private final Map _batchingEnabledConfig; 9 | private final Map _maxBatchSizeConfig; 10 | 11 | public ParSeqRestliClientConfigImpl(Map timeoutMsConfig, Map batchingEnabledConfig, 12 | Map maxBatchSizeConfig) { 13 | _timeoutMsConfig = timeoutMsConfig; 14 | _batchingEnabledConfig = batchingEnabledConfig; 15 | _maxBatchSizeConfig = maxBatchSizeConfig; 16 | } 17 | 18 | @Override 19 | public Map getTimeoutMsConfig() { 20 | return _timeoutMsConfig; 21 | } 22 | 23 | @Override 24 | public Map isBatchingEnabledConfig() { 25 | return _batchingEnabledConfig; 26 | } 27 | 28 | @Override 29 | public Map getMaxBatchSizeConfig() { 30 | return _maxBatchSizeConfig; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /subprojects/parseq-restli-client/src/main/java/com/linkedin/restli/client/config/RequestConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.restli.client.config; 18 | 19 | public interface RequestConfig { 20 | 21 | public ConfigValue getTimeoutMs(); 22 | 23 | public ConfigValue isBatchingEnabled(); 24 | 25 | public ConfigValue getMaxBatchSize(); 26 | } 27 | -------------------------------------------------------------------------------- /subprojects/parseq-restli-client/src/main/java/com/linkedin/restli/client/config/RequestConfigKeyParsingErrorListener.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.restli.client.config; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collections; 5 | import java.util.List; 6 | import java.util.StringJoiner; 7 | 8 | import org.antlr.v4.runtime.BaseErrorListener; 9 | import org.antlr.v4.runtime.RecognitionException; 10 | import org.antlr.v4.runtime.Recognizer; 11 | 12 | class RequestConfigKeyParsingErrorListener extends BaseErrorListener { 13 | 14 | private final List _errors = new ArrayList<>(); 15 | 16 | @Override 17 | public void syntaxError(Recognizer recognizer, Object offendingSymbol, int line, int charPositionInLine, 18 | String msg, RecognitionException e) { 19 | _errors.add("line " + line + ":" + charPositionInLine + " " + msg + "\n"); 20 | } 21 | 22 | public boolean hasErrors() { 23 | return !_errors.isEmpty(); 24 | } 25 | 26 | public List getErrors() { 27 | return Collections.unmodifiableList(_errors); 28 | } 29 | 30 | public int errorsSize() { 31 | return _errors.size(); 32 | } 33 | 34 | @Override 35 | public String toString() { 36 | StringJoiner sj = new StringJoiner(""); 37 | for (String error: _errors) { 38 | sj.add(error); 39 | } 40 | return sj.toString(); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /subprojects/parseq-restli-client/src/main/java/com/linkedin/restli/client/config/RequestConfigKeyParsingException.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.restli.client.config; 2 | 3 | class RequestConfigKeyParsingException extends Exception { 4 | 5 | public RequestConfigKeyParsingException(String message) { 6 | super(message); 7 | } 8 | 9 | public RequestConfigKeyParsingException(Exception e) { 10 | super(e); 11 | } 12 | 13 | private static final long serialVersionUID = 1L; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /subprojects/parseq-restli-client/src/main/java/com/linkedin/restli/client/config/RequestConfigOverrides.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.restli.client.config; 18 | 19 | import java.util.Optional; 20 | 21 | public interface RequestConfigOverrides { 22 | 23 | public Optional> getTimeoutMs(); 24 | 25 | public Optional> isBatchingEnabled(); 26 | 27 | public Optional> getMaxBatchSize(); 28 | } 29 | -------------------------------------------------------------------------------- /subprojects/parseq-restli-client/src/main/java/com/linkedin/restli/client/config/RequestConfigOverridesImpl.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.restli.client.config; 2 | 3 | import java.util.Optional; 4 | 5 | class RequestConfigOverridesImpl implements RequestConfigOverrides { 6 | 7 | private final Optional> _timeoutMs; 8 | private final Optional> _batchingEnabled; 9 | private final Optional> _maxBatchSize; 10 | 11 | RequestConfigOverridesImpl(Optional> timeoutMs, Optional> batchingEnabled, Optional> maxBatchSize) { 12 | _timeoutMs = timeoutMs; 13 | _batchingEnabled = batchingEnabled; 14 | _maxBatchSize = maxBatchSize; 15 | } 16 | 17 | @Override 18 | public Optional> getTimeoutMs() { 19 | return _timeoutMs; 20 | } 21 | 22 | @Override 23 | public Optional> isBatchingEnabled() { 24 | return _batchingEnabled; 25 | } 26 | 27 | @Override 28 | public Optional> getMaxBatchSize() { 29 | return _maxBatchSize; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /subprojects/parseq-restli-client/src/main/java/com/linkedin/restli/client/config/RequestConfigProvider.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.restli.client.config; 2 | 3 | import java.util.function.Function; 4 | 5 | import com.linkedin.restli.client.InboundRequestContextFinder; 6 | import com.linkedin.restli.client.ParSeqRestliClientConfig; 7 | import com.linkedin.restli.client.Request; 8 | 9 | @FunctionalInterface 10 | public interface RequestConfigProvider extends Function, RequestConfig> { 11 | 12 | /** 13 | * @param config configuration 14 | * @param inboundRequestContextFinder request config finder 15 | * @throws RuntimeException throws exception if config provider could not be built 16 | * @return instance of RequestConfigProvider 17 | */ 18 | public static RequestConfigProvider build(ParSeqRestliClientConfig config, InboundRequestContextFinder inboundRequestContextFinder) { 19 | try { 20 | RequestConfigProviderBuilder builder = new RequestConfigProviderBuilder(); 21 | builder.setInboundRequestFinder(inboundRequestContextFinder) 22 | .addConfig(getDefaultConfig()); 23 | if (config != null) { 24 | builder.addConfig(config); 25 | } 26 | return builder.build(); 27 | } catch (RequestConfigKeyParsingException e) { 28 | throw new RuntimeException(e); 29 | } 30 | } 31 | 32 | public static ParSeqRestliClientConfig getDefaultConfig() { 33 | return RequestConfigProviderImpl.DEFAULT_CONFIG; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /subprojects/parseq-restli-client/src/main/java/com/linkedin/restli/client/config/RequestConfigProviderBuilder.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.restli.client.config; 2 | 3 | import com.linkedin.restli.client.InboundRequestContextFinder; 4 | import com.linkedin.restli.client.ParSeqRestliClientConfig; 5 | import com.linkedin.restli.client.ParSeqRestliClientConfigBuilder; 6 | 7 | class RequestConfigProviderBuilder { 8 | 9 | private final ParSeqRestliClientConfigBuilder _config = new ParSeqRestliClientConfigBuilder(); 10 | private InboundRequestContextFinder _inboundRequestFinder; 11 | 12 | public RequestConfigProvider build() throws RequestConfigKeyParsingException { 13 | return new RequestConfigProviderImpl(_inboundRequestFinder, _config.build()); 14 | } 15 | 16 | public RequestConfigProviderBuilder addConfig(ParSeqRestliClientConfig config) { 17 | _config.addConfig(config); 18 | return this; 19 | } 20 | 21 | public RequestConfigProviderBuilder setInboundRequestFinder(InboundRequestContextFinder inboundRequestFinder) { 22 | _inboundRequestFinder = inboundRequestFinder; 23 | return this; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /subprojects/parseq-restli-client/src/main/java/com/linkedin/restli/client/metrics/Metrics.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.restli.client.metrics; 18 | 19 | public interface Metrics { 20 | 21 | public BatchingMetrics getBatchingMetrics(); 22 | 23 | } 24 | -------------------------------------------------------------------------------- /subprojects/parseq-test-api/build.gradle: -------------------------------------------------------------------------------- 1 | ext { 2 | description = '''Provides test fixtures for writing ParSeq-based integration/unit tests''' 3 | } 4 | 5 | dependencies { 6 | compile group: "org.testng", name: "testng", version: "6.9.9" 7 | compile group: "org.junit.jupiter", name: "junit-jupiter-api", version: "5.5.1" 8 | } 9 | 10 | javadoc { 11 | options.use = false 12 | } 13 | -------------------------------------------------------------------------------- /subprojects/parseq-tracevis-server/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu 2 | 3 | MAINTAINER Jaroslaw Odzga "jodzga@linkedin.com" 4 | 5 | # Update aptitude with new repo 6 | # Install other software 7 | RUN apt-get -y update && apt-get install -y \ 8 | graphviz \ 9 | default-jdk \ 10 | wget 11 | 12 | RUN mkdir /opt/parseq-tracevis-server 13 | RUN wget -O /opt/parseq-tracevis-server/parseq-tracevis-server-2.6.21-jar-with-dependencies.jar 'https://search.maven.org/remotecontent?filepath=com/linkedin/parseq/parseq-tracevis-server/2.6.21/parseq-tracevis-server-2.6.21-jar-with-dependencies.jar' 14 | 15 | # Expose port 8080 to the host 16 | EXPOSE 8080 17 | 18 | # Set the current work directory 19 | WORKDIR /opt/parseq-tracevis-server 20 | 21 | ENTRYPOINT ["java", "-Xmx2g", "-Xms2g", "-jar", "/opt/parseq-tracevis-server/parseq-tracevis-server-2.6.21-jar-with-dependencies.jar", "/usr/bin/dot", "8080"] 22 | -------------------------------------------------------------------------------- /subprojects/parseq-tracevis-server/assembly-descriptor.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | jar-with-dependencies 6 | 7 | jar 8 | 9 | false 10 | 11 | 12 | / 13 | true 14 | true 15 | runtime 16 | 17 | 18 | 19 | 20 | ${project.build.directory}/tracevis 21 | 22 | 23 | -------------------------------------------------------------------------------- /subprojects/parseq-tracevis-server/config.properties: -------------------------------------------------------------------------------- 1 | httpPort = YourHttpPortNumber 2 | sslPort = YourHttpsPortNumber 3 | trustStorePassword = YourTrustStorePassword 4 | trustStorePath = YourTrustStorePath 5 | keyStorePassword = YourKeyStorePassword 6 | keyStorePath = YourKeyStorePath -------------------------------------------------------------------------------- /subprojects/parseq-tracevis-server/src/main/java/com/linkedin/parseq/Constants.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq; 2 | 3 | public final class Constants { 4 | 5 | private Constants() {} 6 | 7 | public static final int DEFAULT_CACHE_SIZE = 1024; 8 | public static final long DEFAULT_TIMEOUT_MS = 300000; 9 | public static final String TRACEVIS_SUBDIRECTORY = "tracevis"; 10 | public static final String HEAPSTER_SUBDIRECTORY = "heapster"; 11 | public static final String CACHE_SUBDIRECTORY = "cache"; 12 | public static final String OUTPUT_TYPE = "svg"; 13 | public static final int DEFAULT_PORT = 8080; 14 | public static final long DEFAULT_REAPER_DELAY_MS = 5; 15 | public static final int DEFAULT_PROCESS_QUEUE_SIZE = 1000; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /subprojects/parseq-tracevis-server/src/main/java/com/linkedin/parseq/HashManager.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq; 2 | 3 | import java.util.ArrayDeque; 4 | import java.util.Deque; 5 | import java.util.HashSet; 6 | import java.util.Set; 7 | import java.util.function.Consumer; 8 | 9 | public class HashManager { 10 | 11 | private final Consumer _evictor; 12 | private final Deque _hashDeque = new ArrayDeque<>(); 13 | private final Set _hashSet = new HashSet<>(); 14 | private final int _max; 15 | 16 | public HashManager(Consumer evictor, int max) { 17 | _evictor = evictor; 18 | _max = max; 19 | } 20 | 21 | public synchronized boolean contains(String hash) { 22 | if (_hashSet.contains(hash)) { 23 | _hashDeque.remove(hash); 24 | _hashDeque.add(hash); 25 | return true; 26 | } else { 27 | return false; 28 | } 29 | } 30 | 31 | public synchronized void add(String hash) { 32 | if (!contains(hash)) { 33 | _hashSet.add(hash); 34 | _hashDeque.add(hash); 35 | if (_hashDeque.size() > _max) { 36 | _evictor.accept(_hashDeque.poll()); 37 | } 38 | } 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /subprojects/parseq-tracevis-server/src/main/java/com/linkedin/parseq/HealthCheckHandler.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq; 2 | 3 | import java.io.IOException; 4 | import javax.servlet.ServletException; 5 | import javax.servlet.http.HttpServletRequest; 6 | import javax.servlet.http.HttpServletResponse; 7 | import org.eclipse.jetty.server.Request; 8 | import org.eclipse.jetty.server.handler.AbstractHandler; 9 | 10 | 11 | /** 12 | * This class is for health check to check whether the service is running well or not. 13 | */ 14 | public class HealthCheckHandler extends AbstractHandler { 15 | 16 | @Override 17 | public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) 18 | throws IOException, ServletException { 19 | if (target.equals("/admin")) { 20 | response.setContentType("text/html;charset=utf-8"); 21 | response.setStatus(HttpServletResponse.SC_OK); 22 | baseRequest.setHandled(true); 23 | response.getWriter().println("GOOD"); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /subprojects/parseq-tracevis-server/src/main/java/com/linkedin/parseq/HttpResponse.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq; 2 | 3 | /** 4 | * The class GraphvizResponse contains the HTTP response information. 5 | */ 6 | public class HttpResponse { 7 | 8 | /** 9 | * The field _status is the HTTP response status code. 10 | */ 11 | private final Integer _status; 12 | 13 | /** 14 | * The field _body is the HTTP response body. 15 | */ 16 | private final String _body; 17 | 18 | /** 19 | * The constructor HttpResponse initializes both the status code and the body. 20 | * 21 | * @param status The HTTP response status code 22 | * @param body The HTTP response body 23 | */ 24 | public HttpResponse(final Integer status, final String body) { 25 | this._status = status; 26 | this._body = body; 27 | } 28 | 29 | /** 30 | * The method getStatus returns the HTTP response status code. 31 | * 32 | * @return The HTTP response status code 33 | */ 34 | public Integer getStatus() { 35 | return this._status; 36 | } 37 | 38 | /** 39 | * The method getBody returns the HTTP response body. 40 | * 41 | * @return the HTTP response body 42 | */ 43 | public String getBody() { 44 | return this._body; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /subprojects/parseq-tracevis-server/src/main/java/com/linkedin/parseq/TracevisServerMain.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq; 2 | 3 | import java.io.File; 4 | 5 | public class TracevisServerMain { 6 | 7 | public static void main(String[] args) throws Exception { 8 | 9 | if (args.length < 2 || args.length > 3) { 10 | System.out.println("Incorrect arguments, expecting: DOT_LOCATION TRACEVIS_LOCATION \n" 11 | + " DOT_LOCATION - location of graphviz dot executable\n" 12 | + " TRACEVIS_LOCATION - location of tracevis" 13 | + " HEAPSTER_LOCATION - location of heapster" 14 | + " - optional port number, default is " + Constants.DEFAULT_PORT); 15 | System.exit(1); 16 | } 17 | final String dotLocation = args[0]; 18 | final int port = (args.length == 4) ? Integer.parseInt(args[3]) : Constants.DEFAULT_PORT; 19 | 20 | new TracevisServer(dotLocation, port, new File(args[1]).toPath(), new File(args[2]).toPath(), Constants.DEFAULT_CACHE_SIZE, Constants.DEFAULT_TIMEOUT_MS) 21 | .start(); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /subprojects/parseq-tracevis-server/src/main/resources/heapster/img/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkedin/parseq/3a580be06c5c9f6af2bb13a788de968a6123b3e3/subprojects/parseq-tracevis-server/src/main/resources/heapster/img/icon.png -------------------------------------------------------------------------------- /subprojects/parseq-tracevis/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | /dist 3 | /node_modules 4 | -------------------------------------------------------------------------------- /subprojects/parseq-tracevis/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "eqeqeq": true, 3 | "newcap": true, 4 | "quotmark": true, 5 | "unused": true, 6 | "trailing": true, 7 | "laxbreak": true 8 | } 9 | -------------------------------------------------------------------------------- /subprojects/parseq-tracevis/.npmignore: -------------------------------------------------------------------------------- 1 | /build 2 | /node_modules 3 | -------------------------------------------------------------------------------- /subprojects/parseq-tracevis/README.md: -------------------------------------------------------------------------------- 1 | ParSeq Trace Visualization 2 | ========================== 3 | 4 | This project includes a trace visualizer for 5 | [https://github.com/linkedin/parseq](ParSeq) traces. 6 | 7 | 8 | Building 9 | ======== 10 | 11 | To build the trace visualizer, use `./gradlew makeDist`. This creates a package for the 12 | trace visualizer at `build/distributions/parseq-tracevis.tar.gz`. 13 | 14 | 15 | Running the Trace Visualizer 16 | ============================ 17 | 18 | To run the trace visualizer, extract `parseq-tracevis.tar.gz` and open 19 | trace.html in a browser. The tool can also be hosted from a web server. 20 | 21 | For coding / debugging, the trace visualizer can also be run from the directory 22 | that hosts this README. 23 | 24 | More Info 25 | ========= 26 | 27 | For more information, see the [ParSeq trace wiki](https://github.com/linkedin/parseq/wiki/Tracing#wiki-trace-tools). 28 | 29 | License 30 | ======= 31 | 32 | This tool is licensed under the terms of the Apache License, Version 2.0. 33 | -------------------------------------------------------------------------------- /subprojects/parseq-tracevis/bootstrap/img/glyphicons-halflings-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkedin/parseq/3a580be06c5c9f6af2bb13a788de968a6123b3e3/subprojects/parseq-tracevis/bootstrap/img/glyphicons-halflings-white.png -------------------------------------------------------------------------------- /subprojects/parseq-tracevis/bootstrap/img/glyphicons-halflings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkedin/parseq/3a580be06c5c9f6af2bb13a788de968a6123b3e3/subprojects/parseq-tracevis/bootstrap/img/glyphicons-halflings.png -------------------------------------------------------------------------------- /subprojects/parseq-tracevis/browser.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Copyright 2012 LinkedIn, Inc 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 6 | * use this file except in compliance with the License. You may obtain a copy of 7 | * the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | * License for the specific language governing permissions and limitations under 15 | * the License. 16 | */ 17 | global.parseqTracevis = require("./index"); 18 | -------------------------------------------------------------------------------- /subprojects/parseq-tracevis/css/table.css: -------------------------------------------------------------------------------- 1 | .tableview th:first-child { 2 | border-radius: 5px 0 0 0; 3 | } 4 | 5 | .tableview th:last-child { 6 | border-radius: 0 5px 0 0; 7 | } 8 | 9 | .tableview .hidden { 10 | display: none; 11 | } 12 | 13 | .tableview tr { 14 | background-color: #FFF; 15 | } 16 | 17 | .tableview tr.oddrow { 18 | background-color: #F8F8F8; 19 | } 20 | 21 | .tableview td { 22 | word-wrap: break-word; 23 | } 24 | 25 | /* Prevent long task names from dominating the table */ 26 | .tableview td:first-child { 27 | width: 50%; 28 | 29 | /* 30 | * The following value appears to be ignored by all tested browsers (Chrome, 31 | * Firefox, Safari), but without it, long task names dominate the entire 32 | * table. 33 | */ 34 | max-width: 20em; 35 | } 36 | 37 | .tableview td .expandable { 38 | cursor: pointer; 39 | } 40 | 41 | .tableview td:last-child { 42 | width: 50%; 43 | } 44 | 45 | .tableview td span.composite { 46 | font-weight: bold; 47 | } 48 | 49 | .tableview td.numeric { 50 | font-family: monospace; 51 | text-align: right; 52 | } 53 | 54 | .tableview td.value textarea { 55 | min-width: 100%; 56 | width: 100%; 57 | padding: 0; 58 | margin: 0; 59 | resize: vertical; 60 | } 61 | 62 | .tableview .success { 63 | color: green; 64 | } 65 | 66 | .tableview .error { 67 | color: red; 68 | } 69 | 70 | .tableview .early_finish { 71 | color: goldenrod; 72 | } 73 | 74 | .tableview .unfinished { 75 | color: gray; 76 | } 77 | -------------------------------------------------------------------------------- /subprojects/parseq-tracevis/css/waterfall.css: -------------------------------------------------------------------------------- 1 | .waterfallview .trace rect { stroke: #999; } 2 | 3 | .waterfallview .trace rect { fill: #ACACAC; } 4 | .waterfallview .trace rect.success { fill: #60D060; } 5 | .waterfallview .trace rect.error { fill: #FF6F6F; } 6 | .waterfallview .trace rect.early_finish { fill: #FFFD76; } 7 | 8 | .waterfallview .trace circle { 9 | fill: #FFFFFF; 10 | stroke: #333; 11 | stroke-width: 1px; 12 | } 13 | 14 | .waterfallview .trace line { 15 | stroke: #333; 16 | stroke-width: 1px; 17 | stroke-linecap: round; 18 | stroke-dasharray: 3; 19 | } 20 | 21 | .waterfallview .trace text, 22 | .waterfallview .trace text tspan { 23 | fill: #333; 24 | font-family: arial; 25 | } 26 | 27 | .waterfallview .trace.composite { 28 | cursor: pointer; 29 | } 30 | 31 | .waterfallview .x-axis path, 32 | .waterfallview .x-axis line { 33 | pointer-events: none; 34 | fill: none; 35 | stroke: black; 36 | shape-rendering: crispEdges; 37 | stroke-opacity: .1; 38 | } 39 | 40 | .waterfallview .x-axis .minor-grid line { 41 | stroke-opacity: .05; 42 | } 43 | 44 | .waterfallview { 45 | -webkit-touch-callout: none; 46 | -webkit-user-select: none; 47 | -khtml-user-select: none; 48 | -moz-user-select: none; 49 | -ms-user-select: none; 50 | user-select: none; 51 | } 52 | -------------------------------------------------------------------------------- /subprojects/parseq-tracevis/img/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkedin/parseq/3a580be06c5c9f6af2bb13a788de968a6123b3e3/subprojects/parseq-tracevis/img/icon.png -------------------------------------------------------------------------------- /subprojects/parseq-tracevis/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | trace: { 3 | parse: require("./lib/trace/parse"), 4 | excludeUserTasks: require("./lib/trace/exclude").userTasks, 5 | excludeSystemTasks: require("./lib/trace/exclude").systemTasks, 6 | excludeParentTasks: require("./lib/trace/exclude").parentTasks, 7 | excludeNonCriticalTasks: require("./lib/trace/exclude").nonCriticalTasks, 8 | criticalPath: require("./lib/trace/criticalPath").computeCriticalPath 9 | }, 10 | renderGraphviz: require("./lib/render/graphviz"), 11 | renderTable: require("./lib/render/table"), 12 | renderWaterfall: require("./lib/render/waterfall") 13 | }; 14 | -------------------------------------------------------------------------------- /subprojects/parseq-tracevis/lib/trace/util.js: -------------------------------------------------------------------------------- 1 | exports.alignMillis = function(millis) { 2 | var millisStr = String(millis); 3 | var indexOfPoint = millisStr.indexOf('.'); 4 | if (indexOfPoint === -1) { 5 | return millisStr + '.000'; 6 | } else { 7 | var delta = millisStr.length - indexOfPoint - 1; 8 | if (delta < 3) { 9 | millisStr += new Array(4 - delta).join('0'); 10 | } else if (delta > 3) { 11 | millisStr = millisStr.substring(0, indexOfPoint + 4); 12 | } 13 | } 14 | return millisStr; 15 | }; 16 | -------------------------------------------------------------------------------- /subprojects/parseq-tracevis/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "parseq-tracevis", 3 | "description": "A trace visualizer for ParSeq traces", 4 | "main": "index.js", 5 | "devDependencies": { 6 | "browserify": "^17.0.0", 7 | "chai": "1.8.x", 8 | "cp-data": "1.1.3", 9 | "istanbul": "^0.4.5", 10 | "jshint": "^2.13.6", 11 | "mocha": "^10.2.0", 12 | "puppeteer": "^21.3.8", 13 | "uglify-js": "2.6.0" 14 | }, 15 | "dependencies": { 16 | "graphlib": "0.7.4", 17 | "graphlib-dot": "0.4.9", 18 | "sha1": "1.1.0", 19 | "svg-injector": "1.1.2", 20 | "svg-pan-zoom": "3.1.3" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /subprojects/parseq-tracevis/test/unit/assert.js: -------------------------------------------------------------------------------- 1 | var chai = require('chai'); 2 | 3 | module.exports = chai.assert; 4 | 5 | chai.Assertion.includeStack = true; 6 | -------------------------------------------------------------------------------- /subprojects/parseq-zk-client/build.gradle: -------------------------------------------------------------------------------- 1 | ext { 2 | description = """Integrates ParSeq with the Apache ZooKeeper Library""" 3 | developers = [ 4 | [id: 'axu', name: 'Ang Xu', email: 'axu@linkedin.com'] 5 | ] 6 | } 7 | 8 | 9 | dependencies { 10 | compile group: 'org.apache.zookeeper', name: 'zookeeper', version:'3.4.6' 11 | testCompile project(':parseq-test-api') 12 | testCompile group: 'org.testng', name: 'testng', version:'6.9.9' 13 | testCompile group: 'com.linkedin.pegasus', name: 'd2', version:'2.6.0' 14 | } 15 | -------------------------------------------------------------------------------- /subprojects/parseq-zk-client/src/main/java/com/linkedin/parseq/zk/client/WatchableTask.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 LinkedIn Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq.zk.client; 18 | 19 | import com.linkedin.parseq.BaseTask; 20 | import org.apache.zookeeper.Watcher; 21 | 22 | 23 | /** 24 | * @author Ang Xu 25 | */ 26 | public abstract class WatchableTask extends BaseTask { 27 | 28 | protected Watcher _watcher = null; 29 | 30 | public WatchableTask(final String name) { 31 | super(name); 32 | } 33 | 34 | public WatchableTask withWatcher(Watcher watcher) { 35 | _watcher = watcher; 36 | return this; 37 | } 38 | } 39 | 40 | -------------------------------------------------------------------------------- /subprojects/parseq-zk-client/src/main/java/com/linkedin/parseq/zk/client/ZKClientBuilder.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.zk.client; 2 | 3 | import com.linkedin.parseq.Engine; 4 | import com.linkedin.parseq.internal.ArgumentUtil; 5 | 6 | 7 | /** 8 | * @author Ang Xu 9 | */ 10 | public class ZKClientBuilder { 11 | 12 | private String _connectionString; 13 | private int _sessionTimeout; 14 | private Engine _engine; 15 | 16 | public ZKClientBuilder setConnectionString(String connectionString) { 17 | ArgumentUtil.requireNotNull(connectionString, "zk connection string"); 18 | _connectionString = connectionString; 19 | return this; 20 | } 21 | 22 | public ZKClientBuilder setSessionTimeout(int sessionTimeout) { 23 | ArgumentUtil.requirePositive(sessionTimeout, "session timeout"); 24 | _sessionTimeout = sessionTimeout; 25 | return this; 26 | } 27 | 28 | public ZKClientBuilder setEngine(Engine engine) { 29 | ArgumentUtil.requireNotNull(engine, "engine"); 30 | _engine = engine; 31 | return this; 32 | } 33 | 34 | public ZKClient build() { 35 | return new ZKClientImpl(_connectionString, _sessionTimeout, _engine); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /subprojects/parseq-zk-client/src/main/java/com/linkedin/parseq/zk/recipes/MultiLocks.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.zk.recipes; 2 | 3 | import com.linkedin.parseq.Task; 4 | import com.linkedin.parseq.zk.client.ZKClient; 5 | import java.util.Arrays; 6 | import java.util.Collections; 7 | import java.util.List; 8 | import java.util.stream.Collectors; 9 | import org.apache.zookeeper.data.ACL; 10 | 11 | 12 | /** 13 | * This class represents multiple zookeeper locks that has to be 14 | * acquired in an atomic manner. Note that Locks are acquired in 15 | * the natural ordering of its lockPath to avoid deadlock. 16 | * 17 | * @author Ang Xu 18 | */ 19 | public class MultiLocks implements Synchronizable { 20 | 21 | /** 22 | * an unmodifiable list of {@link ZKLock}s to be acquired in order. 23 | */ 24 | private final List _locks; 25 | 26 | public MultiLocks(ZKClient zkClient, List acls, String... lockPaths) { 27 | List locks = Arrays.stream(lockPaths) 28 | .sorted() 29 | .map(lockPath -> new ZKLock(lockPath, zkClient, acls)) 30 | .collect(Collectors.toList()); 31 | _locks = Collections.unmodifiableList(locks); 32 | } 33 | 34 | /** 35 | * {@inheritDoc} 36 | */ 37 | @Override 38 | public Task synchronize(Task task, long deadline) { 39 | for (ZKLock lock : _locks) { 40 | task = lock.synchronize(task, deadline); 41 | } 42 | return task; 43 | } 44 | } -------------------------------------------------------------------------------- /subprojects/parseq-zk-client/src/main/java/com/linkedin/parseq/zk/recipes/Synchronizable.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.zk.recipes; 2 | 3 | import com.linkedin.parseq.Task; 4 | 5 | 6 | /** 7 | * Synchronizable represents a object upon which {@link Task}s within different plans 8 | * can be properly synchronized. 9 | * 10 | * @author Ang Xu 11 | */ 12 | public interface Synchronizable { 13 | /** 14 | * Runs the given task while holding this synchronizable. 15 | * 16 | * @param task task to run 17 | * @param deadline the absolute time, in milliseconds, to wait for the synchronizable. 18 | * 19 | * @return a new task wrapped with {@link ZKLock#synchronize(Task, long)} 20 | */ 21 | Task synchronize(Task task, long deadline); 22 | } 23 | -------------------------------------------------------------------------------- /subprojects/parseq-zk-client/src/test/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | log4j.rootLogger=INFO, stdout 2 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender 3 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 4 | log4j.appender.stdout.layout.ConversionPattern=%d [%t] %-5p %c: %m%n -------------------------------------------------------------------------------- /subprojects/parseq/src/main/codegen/config.fmpp: -------------------------------------------------------------------------------- 1 | data: { 2 | tdd(../data/fmpp.tdd) 3 | } 4 | 5 | freemarkerLinks: { 6 | includes: templates/ 7 | } 8 | 9 | modes: [ 10 | ignore(**/macros/) 11 | ] -------------------------------------------------------------------------------- /subprojects/parseq/src/main/codegen/data/fmpp.tdd: -------------------------------------------------------------------------------- 1 | max: 15 <#-- must be at least 3 --> 2 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/codegen/templates/com/linkedin/parseq/function/ConsumerN.java.ftl: -------------------------------------------------------------------------------- 1 | <#include "../../../../macros/macros.ftl"> 2 | <@pp.dropOutputFile /> 3 | <#list 1..max as i> 4 | <@pp.changeOutputFile name="Consumer" + i + ".java" /> 5 | package com.linkedin.parseq.function; 6 | 7 | 8 | @FunctionalInterface 9 | public interface Consumer${i}<<@typeParameters i/>> { 10 | 11 | void accept(<@csv 1..i; j>T${j} t${j}) throws Exception; 12 | 13 | } 14 | 15 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/codegen/templates/com/linkedin/parseq/function/FunctionN.java.ftl: -------------------------------------------------------------------------------- 1 | <#include "../../../../macros/macros.ftl"> 2 | <@pp.dropOutputFile /> 3 | <#list 2..max as i> 4 | <@pp.changeOutputFile name="Function" + i + ".java" /> 5 | package com.linkedin.parseq.function; 6 | 7 | import java.util.Objects; 8 | import com.linkedin.parseq.function.Function1; 9 | 10 | @FunctionalInterface 11 | public interface Function${i}<<@typeParameters i/>, R> { 12 | 13 | R apply(<@csv 1..i; j>T${j} t${j}) throws Exception; 14 | 15 | default Function${i}<<@typeParameters i/>, V> andThen(Function1 f) { 16 | Objects.requireNonNull(f); 17 | return (<@csv 1..i; j>T${j} t${j}) -> 18 | f.apply(apply(<@csv 1..i; j>t${j})); 19 | } 20 | 21 | } 22 | 23 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/codegen/templates/com/linkedin/parseq/function/Tuples.java.ftl: -------------------------------------------------------------------------------- 1 | <#include "../../../../macros/macros.ftl"> 2 | <@pp.dropOutputFile /> 3 | <@pp.changeOutputFile name="Tuples.java" /> 4 | package com.linkedin.parseq.function; 5 | 6 | public class Tuples { 7 | private Tuples() {} 8 | 9 | <@lines 2..max; i> public static <<@typeParameters i/>> Tuple${i}<<@typeParameters i/>> tuple(<@parameters i/>) { 10 | return new Tuple${i}<<@typeParameters i/>>(<@csv 1..i; j>t${j}); 11 | } 12 | 13 | 14 | } 15 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/codegen/templates/macros/macros.ftl: -------------------------------------------------------------------------------- 1 | <#macro seplist range sep=""> 2 | <#list range as x><#if x != range?first>${sep}<#nested x> 3 | <#macro csv range><@seplist range=range sep=", "; x><#nested x> 4 | <#macro csvNL range><@seplist range=range sep=",\n"; x><#nested x> 5 | <#macro lines range><@seplist range=range sep="\n"; x><#nested x> 6 | <#macro typeParameters arity><@csv 1..arity; j>T${j} 7 | <#macro parameters arity><@csv 1..arity; j>final T${j} t${j} 8 | <#macro repeat range><@seplist range=range sep=""; x><#nested x> 9 | <#macro tupleArgs arity><@csv 1..arity; j>tuple._${j}() -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/Cancellable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq; 18 | 19 | /** 20 | * An object that can be cancelled with a reason. 21 | * 22 | * @author Chris Pettitt (cpettitt@linkedin.com) 23 | */ 24 | public interface Cancellable { 25 | /** 26 | * Attempts to cancel the object with the given reason. Check the return 27 | * value to determine if cancellation was successful. Subsequent calls to 28 | * cancel will always return {@code false}. 29 | * 30 | * @param reason an Exception indicating why this object was cancelled 31 | * @return {@code true} iff the object was successfully cancelled as a result 32 | * of this invocation. 33 | */ 34 | boolean cancel(Exception reason); 35 | } 36 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/CancellationException.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq; 2 | 3 | public class CancellationException extends Exception { 4 | 5 | private static final long serialVersionUID = 1L; 6 | 7 | public CancellationException(String message, Throwable cause) { 8 | super(message, cause); 9 | } 10 | 11 | public CancellationException(String message) { 12 | super(message); 13 | } 14 | 15 | public CancellationException(Throwable cause) { 16 | super(cause); 17 | } 18 | 19 | public CancellationException() { 20 | super(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/DelayedExecutor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq; 18 | 19 | import java.util.concurrent.TimeUnit; 20 | 21 | import com.linkedin.parseq.Cancellable; 22 | 23 | 24 | /** 25 | * An object that allows a task to be scheduled for execution after some delay. 26 | * 27 | * @author Chris Pettitt (cpettitt@linkedin.com) 28 | */ 29 | public interface DelayedExecutor { 30 | /** 31 | * Schedules a command to execute after some period of delay. 32 | * 33 | * @param delay the amount of time to wait before executing the command 34 | * @param unit the time unit for the delay parameter 35 | * @param command the command to execute 36 | * @return a handle that can be used to cancel a future if it has not already run. 37 | */ 38 | Cancellable schedule(long delay, TimeUnit unit, Runnable command); 39 | } 40 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/DelayedExecutorAdapter.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq; 2 | 3 | import com.linkedin.parseq.DelayedExecutor; 4 | import com.linkedin.parseq.internal.CancellableScheduledFuture; 5 | import com.linkedin.parseq.Cancellable; 6 | 7 | import java.util.concurrent.ScheduledExecutorService; 8 | import java.util.concurrent.TimeUnit; 9 | 10 | 11 | /** 12 | * Adapts a {@link ScheduledExecutorService} to the simpler 13 | * {@link DelayedExecutor} interface. 14 | * 15 | * @author Chris Pettitt 16 | */ 17 | public class DelayedExecutorAdapter implements DelayedExecutor { 18 | private final ScheduledExecutorService _scheduler; 19 | 20 | public DelayedExecutorAdapter(final ScheduledExecutorService scheduler) { 21 | _scheduler = scheduler; 22 | } 23 | 24 | @Override 25 | public Cancellable schedule(final long delay, final TimeUnit unit, final Runnable command) { 26 | return new CancellableScheduledFuture(_scheduler.schedule(command, delay, unit)); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/EarlyFinishException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq; 18 | 19 | /** 20 | * This exception indicates that a task was cancelled because its parent was 21 | * resolved (a value was set for the parent) before the task itself was 22 | * resolved. 23 | * 24 | * @author Chris Pettitt (cpettitt@linkedin.com) 25 | */ 26 | public class EarlyFinishException extends Exception { 27 | private static final long serialVersionUID = 0L; 28 | 29 | public EarlyFinishException() { 30 | super(); 31 | } 32 | 33 | public EarlyFinishException(final String message) { 34 | super(message); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/EngineShutdownException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq; 18 | 19 | /** 20 | * This exception is raised when a Task is submitted to an engine after the 21 | * engine has been shutdown. 22 | * 23 | * @author Chris Pettitt (cpettitt@linkedin.com) 24 | */ 25 | public class EngineShutdownException extends Exception { 26 | private static final long serialVersionUID = 0L; 27 | 28 | public EngineShutdownException(final String message) { 29 | super(message); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/TaskDescriptor.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq; 2 | 3 | /** 4 | * An API to provide description for task. 5 | * 6 | * parseq-lambda-names provide an implementation for this interface using Java SPI. Any changes made to this interface 7 | * might require a change to implementation in parseq-lambda-names. 8 | * 9 | * The implementation doesnt need to be thread-safe. 10 | * 11 | * @author Siddharth Sodhani (ssodhani@linkedin.com) 12 | */ 13 | public interface TaskDescriptor { 14 | 15 | /** 16 | * Give class name which could correspond to generated lambda expressions etc infer appropriate description for it 17 | * If it is unable to infer description, it returns className 18 | * 19 | * @param className 20 | * @return description for task it can be inferred else returns className 21 | */ 22 | String getDescription(String className); 23 | } 24 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/TaskQueueFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq; 18 | 19 | import com.linkedin.parseq.internal.PrioritizableRunnable; 20 | import com.linkedin.parseq.internal.SerialExecutor; 21 | 22 | 23 | /** 24 | * A factory to create {@link com.linkedin.parseq.internal.SerialExecutor.TaskQueue}s. 25 | * 26 | * @author Ang Xu 27 | */ 28 | public interface TaskQueueFactory { 29 | SerialExecutor.TaskQueue newTaskQueue(); 30 | } 31 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/TaskType.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq; 2 | 3 | /** 4 | * Different types of parseq tasks. The idea is to attach type to a task so that it can be displayed in trace 5 | * visualization tool to help in debugging. 6 | */ 7 | public enum TaskType { 8 | FUSION ("fusion"), 9 | BLOCKING ("blocking"), 10 | SHAREABLE ("shareable"), 11 | FLATTEN ("flatten"), 12 | WITH_SIDE_EFFECT ("withSideEffect"), 13 | RETRY ("retry"), 14 | WITH_RETRY ("withRetry"), 15 | TIMEOUT ("timeout"), 16 | WITH_TIMEOUT ("withTimeout"), 17 | RECOVER ("recover"), 18 | WITH_RECOVER ("withRecover"), 19 | TRANSFORM ("transform"), 20 | WITH_TRANSFORM ("withTransform"), 21 | WITH_DELAY ("withDelay"); 22 | 23 | private final String _name; 24 | 25 | TaskType(String name) { 26 | _name = name; 27 | } 28 | 29 | public String getName() { 30 | return _name; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/ThrowableCallable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | package com.linkedin.parseq; 17 | 18 | import java.util.concurrent.Callable; 19 | 20 | 21 | /** 22 | * An object similar to {@link java.util.concurrent.Callable}, but the 23 | * {@link #call()} method allows a {@link Throwable} to be thrown. 24 | * 25 | * @deprecated As of 2.0.0, replaced by {@link Callable}. 26 | * @see Callable 27 | * @author Chris Pettitt 28 | */ 29 | @FunctionalInterface 30 | @Deprecated 31 | public interface ThrowableCallable { 32 | /** 33 | * Computes a value of type {@code T} or throws a {@link Throwable} if an 34 | * error occurred during the computation. 35 | * 36 | * @return the computed result for this callable 37 | * @throws Throwable if an error occurred during the computation. 38 | */ 39 | T call() throws Throwable; 40 | } 41 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/doc-files/andThen-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkedin/parseq/3a580be06c5c9f6af2bb13a788de968a6123b3e3/subprojects/parseq/src/main/java/com/linkedin/parseq/doc-files/andThen-1.png -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/doc-files/andThen-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkedin/parseq/3a580be06c5c9f6af2bb13a788de968a6123b3e3/subprojects/parseq/src/main/java/com/linkedin/parseq/doc-files/andThen-2.png -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/doc-files/andThen-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkedin/parseq/3a580be06c5c9f6af2bb13a788de968a6123b3e3/subprojects/parseq/src/main/java/com/linkedin/parseq/doc-files/andThen-3.png -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/doc-files/andThen-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkedin/parseq/3a580be06c5c9f6af2bb13a788de968a6123b3e3/subprojects/parseq/src/main/java/com/linkedin/parseq/doc-files/andThen-4.png -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/doc-files/flatMap-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkedin/parseq/3a580be06c5c9f6af2bb13a788de968a6123b3e3/subprojects/parseq/src/main/java/com/linkedin/parseq/doc-files/flatMap-1.png -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/doc-files/flatMap-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkedin/parseq/3a580be06c5c9f6af2bb13a788de968a6123b3e3/subprojects/parseq/src/main/java/com/linkedin/parseq/doc-files/flatMap-2.png -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/doc-files/map-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkedin/parseq/3a580be06c5c9f6af2bb13a788de968a6123b3e3/subprojects/parseq/src/main/java/com/linkedin/parseq/doc-files/map-1.png -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/doc-files/map-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkedin/parseq/3a580be06c5c9f6af2bb13a788de968a6123b3e3/subprojects/parseq/src/main/java/com/linkedin/parseq/doc-files/map-2.png -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/doc-files/onFailure-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkedin/parseq/3a580be06c5c9f6af2bb13a788de968a6123b3e3/subprojects/parseq/src/main/java/com/linkedin/parseq/doc-files/onFailure-1.png -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/doc-files/onFailure-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkedin/parseq/3a580be06c5c9f6af2bb13a788de968a6123b3e3/subprojects/parseq/src/main/java/com/linkedin/parseq/doc-files/onFailure-2.png -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/doc-files/recover-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkedin/parseq/3a580be06c5c9f6af2bb13a788de968a6123b3e3/subprojects/parseq/src/main/java/com/linkedin/parseq/doc-files/recover-1.png -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/doc-files/recoverWith-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkedin/parseq/3a580be06c5c9f6af2bb13a788de968a6123b3e3/subprojects/parseq/src/main/java/com/linkedin/parseq/doc-files/recoverWith-1.png -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/doc-files/shareable-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkedin/parseq/3a580be06c5c9f6af2bb13a788de968a6123b3e3/subprojects/parseq/src/main/java/com/linkedin/parseq/doc-files/shareable-1.png -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/doc-files/shareable-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkedin/parseq/3a580be06c5c9f6af2bb13a788de968a6123b3e3/subprojects/parseq/src/main/java/com/linkedin/parseq/doc-files/shareable-2.png -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/doc-files/toTry-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkedin/parseq/3a580be06c5c9f6af2bb13a788de968a6123b3e3/subprojects/parseq/src/main/java/com/linkedin/parseq/doc-files/toTry-1.png -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/doc-files/toTry-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkedin/parseq/3a580be06c5c9f6af2bb13a788de968a6123b3e3/subprojects/parseq/src/main/java/com/linkedin/parseq/doc-files/toTry-2.png -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/doc-files/transform-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkedin/parseq/3a580be06c5c9f6af2bb13a788de968a6123b3e3/subprojects/parseq/src/main/java/com/linkedin/parseq/doc-files/transform-1.png -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/doc-files/transformWith-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkedin/parseq/3a580be06c5c9f6af2bb13a788de968a6123b3e3/subprojects/parseq/src/main/java/com/linkedin/parseq/doc-files/transformWith-1.png -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/doc-files/withSideEffect-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkedin/parseq/3a580be06c5c9f6af2bb13a788de968a6123b3e3/subprojects/parseq/src/main/java/com/linkedin/parseq/doc-files/withSideEffect-1.png -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/doc-files/withTimeout-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linkedin/parseq/3a580be06c5c9f6af2bb13a788de968a6123b3e3/subprojects/parseq/src/main/java/com/linkedin/parseq/doc-files/withTimeout-1.png -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/function/Action.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.function; 2 | 3 | @FunctionalInterface 4 | public interface Action { 5 | public void run() throws Exception; 6 | } 7 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/function/Consumer1.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.function; 2 | 3 | 4 | @FunctionalInterface 5 | public interface Consumer1 { 6 | 7 | void accept(T1 t1) throws Exception; 8 | 9 | } 10 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/function/Consumer10.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.function; 2 | 3 | 4 | @FunctionalInterface 5 | public interface Consumer10 { 6 | 7 | void accept(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10) throws Exception; 8 | 9 | } 10 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/function/Consumer11.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.function; 2 | 3 | 4 | @FunctionalInterface 5 | public interface Consumer11 { 6 | 7 | void accept(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T11 t11) throws Exception; 8 | 9 | } 10 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/function/Consumer12.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.function; 2 | 3 | 4 | @FunctionalInterface 5 | public interface Consumer12 { 6 | 7 | void accept(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T11 t11, T12 t12) throws Exception; 8 | 9 | } 10 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/function/Consumer13.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.function; 2 | 3 | 4 | @FunctionalInterface 5 | public interface Consumer13 { 6 | 7 | void accept(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T11 t11, T12 t12, T13 t13) throws Exception; 8 | 9 | } 10 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/function/Consumer14.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.function; 2 | 3 | 4 | @FunctionalInterface 5 | public interface Consumer14 { 6 | 7 | void accept(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T11 t11, T12 t12, T13 t13, T14 t14) throws Exception; 8 | 9 | } 10 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/function/Consumer15.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.function; 2 | 3 | 4 | @FunctionalInterface 5 | public interface Consumer15 { 6 | 7 | void accept(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T11 t11, T12 t12, T13 t13, T14 t14, T15 t15) throws Exception; 8 | 9 | } 10 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/function/Consumer2.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.function; 2 | 3 | 4 | @FunctionalInterface 5 | public interface Consumer2 { 6 | 7 | void accept(T1 t1, T2 t2) throws Exception; 8 | 9 | } 10 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/function/Consumer3.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.function; 2 | 3 | 4 | @FunctionalInterface 5 | public interface Consumer3 { 6 | 7 | void accept(T1 t1, T2 t2, T3 t3) throws Exception; 8 | 9 | } 10 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/function/Consumer4.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.function; 2 | 3 | 4 | @FunctionalInterface 5 | public interface Consumer4 { 6 | 7 | void accept(T1 t1, T2 t2, T3 t3, T4 t4) throws Exception; 8 | 9 | } 10 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/function/Consumer5.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.function; 2 | 3 | 4 | @FunctionalInterface 5 | public interface Consumer5 { 6 | 7 | void accept(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5) throws Exception; 8 | 9 | } 10 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/function/Consumer6.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.function; 2 | 3 | 4 | @FunctionalInterface 5 | public interface Consumer6 { 6 | 7 | void accept(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6) throws Exception; 8 | 9 | } 10 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/function/Consumer7.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.function; 2 | 3 | 4 | @FunctionalInterface 5 | public interface Consumer7 { 6 | 7 | void accept(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7) throws Exception; 8 | 9 | } 10 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/function/Consumer8.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.function; 2 | 3 | 4 | @FunctionalInterface 5 | public interface Consumer8 { 6 | 7 | void accept(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8) throws Exception; 8 | 9 | } 10 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/function/Consumer9.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.function; 2 | 3 | 4 | @FunctionalInterface 5 | public interface Consumer9 { 6 | 7 | void accept(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9) throws Exception; 8 | 9 | } 10 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/function/Failure.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.function; 2 | 3 | import java.util.NoSuchElementException; 4 | import java.util.Objects; 5 | 6 | 7 | public class Failure implements Try { 8 | 9 | private final Throwable _error; 10 | 11 | private Failure(Throwable error) { 12 | _error = error; 13 | } 14 | 15 | @Override 16 | public T get() { 17 | throw (NoSuchElementException) new NoSuchElementException().initCause(_error); 18 | } 19 | 20 | @Override 21 | public boolean isFailed() { 22 | return true; 23 | } 24 | 25 | @Override 26 | public Throwable getError() { 27 | return _error; 28 | } 29 | 30 | @Override 31 | public ResultType resultType() { 32 | return ResultType.failure; 33 | } 34 | 35 | public static Try of(Throwable t) { 36 | return new Failure(t); 37 | } 38 | 39 | @Override 40 | public int hashCode() { 41 | return Objects.hash(_error); 42 | } 43 | 44 | @Override 45 | public boolean equals(Object other) { 46 | if (other instanceof Failure) { 47 | Failure that = (Failure) other; 48 | return Objects.equals(this._error, that._error); 49 | } else { 50 | return false; 51 | } 52 | } 53 | 54 | @Override 55 | public String toString() { 56 | return "failure(" + _error + ")"; 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/function/Function1.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.function; 2 | 3 | import java.util.Objects; 4 | 5 | 6 | @FunctionalInterface 7 | public interface Function1 { 8 | 9 | R apply(T1 t1) throws Exception; 10 | 11 | default Function1 andThen(Function1 f) { 12 | Objects.requireNonNull(f); 13 | return (T1 t1) -> f.apply(apply(t1)); 14 | } 15 | 16 | /** 17 | * Returns a function that always returns its input argument. 18 | * 19 | * @param the type of the input and output objects to the function 20 | * @return a function that always returns its input argument 21 | */ 22 | static Function1 identity() { 23 | return t -> t; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/function/Function10.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.function; 2 | 3 | import java.util.Objects; 4 | import com.linkedin.parseq.function.Function1; 5 | 6 | @FunctionalInterface 7 | public interface Function10 { 8 | 9 | R apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10) throws Exception; 10 | 11 | default Function10 andThen(Function1 f) { 12 | Objects.requireNonNull(f); 13 | return (T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10) -> 14 | f.apply(apply(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10)); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/function/Function11.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.function; 2 | 3 | import java.util.Objects; 4 | import com.linkedin.parseq.function.Function1; 5 | 6 | @FunctionalInterface 7 | public interface Function11 { 8 | 9 | R apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T11 t11) throws Exception; 10 | 11 | default Function11 andThen(Function1 f) { 12 | Objects.requireNonNull(f); 13 | return (T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T11 t11) -> 14 | f.apply(apply(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11)); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/function/Function12.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.function; 2 | 3 | import java.util.Objects; 4 | import com.linkedin.parseq.function.Function1; 5 | 6 | @FunctionalInterface 7 | public interface Function12 { 8 | 9 | R apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T11 t11, T12 t12) throws Exception; 10 | 11 | default Function12 andThen(Function1 f) { 12 | Objects.requireNonNull(f); 13 | return (T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T11 t11, T12 t12) -> 14 | f.apply(apply(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12)); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/function/Function13.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.function; 2 | 3 | import java.util.Objects; 4 | import com.linkedin.parseq.function.Function1; 5 | 6 | @FunctionalInterface 7 | public interface Function13 { 8 | 9 | R apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T11 t11, T12 t12, T13 t13) throws Exception; 10 | 11 | default Function13 andThen(Function1 f) { 12 | Objects.requireNonNull(f); 13 | return (T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T11 t11, T12 t12, T13 t13) -> 14 | f.apply(apply(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13)); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/function/Function14.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.function; 2 | 3 | import java.util.Objects; 4 | import com.linkedin.parseq.function.Function1; 5 | 6 | @FunctionalInterface 7 | public interface Function14 { 8 | 9 | R apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T11 t11, T12 t12, T13 t13, T14 t14) throws Exception; 10 | 11 | default Function14 andThen(Function1 f) { 12 | Objects.requireNonNull(f); 13 | return (T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T11 t11, T12 t12, T13 t13, T14 t14) -> 14 | f.apply(apply(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14)); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/function/Function15.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.function; 2 | 3 | import java.util.Objects; 4 | import com.linkedin.parseq.function.Function1; 5 | 6 | @FunctionalInterface 7 | public interface Function15 { 8 | 9 | R apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T11 t11, T12 t12, T13 t13, T14 t14, T15 t15) throws Exception; 10 | 11 | default Function15 andThen(Function1 f) { 12 | Objects.requireNonNull(f); 13 | return (T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9, T10 t10, T11 t11, T12 t12, T13 t13, T14 t14, T15 t15) -> 14 | f.apply(apply(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15)); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/function/Function2.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.function; 2 | 3 | import java.util.Objects; 4 | import com.linkedin.parseq.function.Function1; 5 | 6 | @FunctionalInterface 7 | public interface Function2 { 8 | 9 | R apply(T1 t1, T2 t2) throws Exception; 10 | 11 | default Function2 andThen(Function1 f) { 12 | Objects.requireNonNull(f); 13 | return (T1 t1, T2 t2) -> 14 | f.apply(apply(t1, t2)); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/function/Function3.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.function; 2 | 3 | import java.util.Objects; 4 | import com.linkedin.parseq.function.Function1; 5 | 6 | @FunctionalInterface 7 | public interface Function3 { 8 | 9 | R apply(T1 t1, T2 t2, T3 t3) throws Exception; 10 | 11 | default Function3 andThen(Function1 f) { 12 | Objects.requireNonNull(f); 13 | return (T1 t1, T2 t2, T3 t3) -> 14 | f.apply(apply(t1, t2, t3)); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/function/Function4.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.function; 2 | 3 | import java.util.Objects; 4 | import com.linkedin.parseq.function.Function1; 5 | 6 | @FunctionalInterface 7 | public interface Function4 { 8 | 9 | R apply(T1 t1, T2 t2, T3 t3, T4 t4) throws Exception; 10 | 11 | default Function4 andThen(Function1 f) { 12 | Objects.requireNonNull(f); 13 | return (T1 t1, T2 t2, T3 t3, T4 t4) -> 14 | f.apply(apply(t1, t2, t3, t4)); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/function/Function5.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.function; 2 | 3 | import java.util.Objects; 4 | import com.linkedin.parseq.function.Function1; 5 | 6 | @FunctionalInterface 7 | public interface Function5 { 8 | 9 | R apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5) throws Exception; 10 | 11 | default Function5 andThen(Function1 f) { 12 | Objects.requireNonNull(f); 13 | return (T1 t1, T2 t2, T3 t3, T4 t4, T5 t5) -> 14 | f.apply(apply(t1, t2, t3, t4, t5)); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/function/Function6.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.function; 2 | 3 | import java.util.Objects; 4 | import com.linkedin.parseq.function.Function1; 5 | 6 | @FunctionalInterface 7 | public interface Function6 { 8 | 9 | R apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6) throws Exception; 10 | 11 | default Function6 andThen(Function1 f) { 12 | Objects.requireNonNull(f); 13 | return (T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6) -> 14 | f.apply(apply(t1, t2, t3, t4, t5, t6)); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/function/Function7.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.function; 2 | 3 | import java.util.Objects; 4 | import com.linkedin.parseq.function.Function1; 5 | 6 | @FunctionalInterface 7 | public interface Function7 { 8 | 9 | R apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7) throws Exception; 10 | 11 | default Function7 andThen(Function1 f) { 12 | Objects.requireNonNull(f); 13 | return (T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7) -> 14 | f.apply(apply(t1, t2, t3, t4, t5, t6, t7)); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/function/Function8.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.function; 2 | 3 | import java.util.Objects; 4 | import com.linkedin.parseq.function.Function1; 5 | 6 | @FunctionalInterface 7 | public interface Function8 { 8 | 9 | R apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8) throws Exception; 10 | 11 | default Function8 andThen(Function1 f) { 12 | Objects.requireNonNull(f); 13 | return (T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8) -> 14 | f.apply(apply(t1, t2, t3, t4, t5, t6, t7, t8)); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/function/Function9.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.function; 2 | 3 | import java.util.Objects; 4 | import com.linkedin.parseq.function.Function1; 5 | 6 | @FunctionalInterface 7 | public interface Function9 { 8 | 9 | R apply(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9) throws Exception; 10 | 11 | default Function9 andThen(Function1 f) { 12 | Objects.requireNonNull(f); 13 | return (T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9) -> 14 | f.apply(apply(t1, t2, t3, t4, t5, t6, t7, t8, t9)); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/function/Success.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.function; 2 | 3 | import java.util.Objects; 4 | 5 | 6 | public class Success implements Try { 7 | 8 | private final T _value; 9 | 10 | private Success(T value) { 11 | this._value = value; 12 | } 13 | 14 | @Override 15 | public T get() { 16 | return _value; 17 | } 18 | 19 | @Override 20 | public boolean isFailed() { 21 | return false; 22 | } 23 | 24 | @Override 25 | public Throwable getError() { 26 | return null; 27 | } 28 | 29 | @Override 30 | public ResultType resultType() { 31 | return ResultType.success; 32 | } 33 | 34 | public static Try of(R value) { 35 | return new Success(value); 36 | } 37 | 38 | @Override 39 | public int hashCode() { 40 | return Objects.hash(_value); 41 | } 42 | 43 | @Override 44 | public boolean equals(Object other) { 45 | if (other instanceof Success) { 46 | Success that = (Success) other; 47 | return Objects.equals(this._value, that._value); 48 | } else { 49 | return false; 50 | } 51 | } 52 | 53 | @Override 54 | public String toString() { 55 | return "success(" + _value + ")"; 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/function/Try.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.function; 2 | 3 | import java.util.NoSuchElementException; 4 | 5 | 6 | /** 7 | * The {@code Try} interface represents result that may either be a 8 | * successful completion or a failure. It has two implementation: {@link Success} 9 | * and {@link Failure}. New instances of {@code Try} can be created by either 10 | * calling {@code Success.of(...)} of {@code Failure.of(...)}. 11 | * 12 | * 13 | * @see Success 14 | * @see Failure 15 | * 16 | * @author Jaroslaw Odzga (jodzga@linkedin.com) 17 | */ 18 | public interface Try { 19 | 20 | public enum ResultType { 21 | success, 22 | failure 23 | } 24 | 25 | /** 26 | * Returns value associated with successful completion or 27 | * {@link NoSuchElementException} if result represents a failure. 28 | * @return value associated with successful completion 29 | * @throws NoSuchElementException if result is a failure 30 | */ 31 | T get(); 32 | 33 | boolean isFailed(); 34 | 35 | /** 36 | * Returns {@code Throwable} associated with this failure or 37 | * null if result represents successful completion. 38 | * @return the error associated with this failure 39 | */ 40 | Throwable getError(); 41 | 42 | /** 43 | * Returns either {@link ResultType#success success} or {@link ResultType#failure failure}. 44 | * @return the type of the result 45 | */ 46 | ResultType resultType(); 47 | 48 | } 49 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/function/Tuple.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.function; 2 | 3 | public interface Tuple extends Iterable { 4 | 5 | int arity(); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/internal/CachedLoggerFactory.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.internal; 2 | 3 | import org.slf4j.ILoggerFactory; 4 | import org.slf4j.Logger; 5 | 6 | import java.util.concurrent.ConcurrentHashMap; 7 | 8 | 9 | /** 10 | * This wrapper class caches the Logger for given logger names. 11 | * This is going to be the default LoggerFactory used to build Engine 12 | * The motivation to avoid the performance impact of log4j2's getLogger() method, which calls slow getContext() method. 13 | * 14 | * Note that as a tradeoff, LoggerContext is not supported. 15 | * 16 | * @author Zhenkai Zhu 17 | */ 18 | public class CachedLoggerFactory implements ILoggerFactory { 19 | private final ILoggerFactory _loggerFactory; 20 | private final ConcurrentHashMap _loggers; 21 | 22 | public CachedLoggerFactory(ILoggerFactory loggerFactory) { 23 | _loggerFactory = loggerFactory; 24 | _loggers = new ConcurrentHashMap<>(); 25 | } 26 | 27 | @Override 28 | public Logger getLogger(String name) { 29 | return _loggers.computeIfAbsent(name, _loggerFactory::getLogger); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/internal/CancellableScheduledFuture.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq.internal; 18 | 19 | import com.linkedin.parseq.Cancellable; 20 | 21 | import java.util.concurrent.ScheduledFuture; 22 | 23 | 24 | /** 25 | * @author Chris Pettitt (cpettitt@linkedin.com) 26 | */ 27 | public class CancellableScheduledFuture implements Cancellable { 28 | private final ScheduledFuture _future; 29 | 30 | public CancellableScheduledFuture(final ScheduledFuture future) { 31 | _future = future; 32 | } 33 | 34 | @Override 35 | public boolean cancel(final Exception reason) { 36 | return _future.cancel(false); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/internal/Clock.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.internal; 2 | 3 | /** 4 | * Abstraction over nanoseconds precision clock. Useful for unit testing. 5 | * 6 | * @author Jaroslaw Odzga (jodzga@linkedin.com) 7 | * 8 | */ 9 | public interface Clock { 10 | 11 | /** 12 | * 13 | * @return the current value of the running Java Virtual Machine's 14 | * high-resolution time source, in nanoseconds. 15 | * Default implementation delegates to {@link System#nanoTime()}. 16 | */ 17 | long nanoTime(); 18 | 19 | /** 20 | * Performs a sleep using nanoseconds as a time unit. 21 | * Default implementation delegates to {@link Thread#sleep(long, int)}. 22 | * 23 | * @param nano the minimum time to sleep. If less than 24 | * or equal to zero, do not sleep at all. 25 | * @throws InterruptedException if interrupted while sleeping 26 | */ 27 | void sleepNano(long nano) throws InterruptedException; 28 | 29 | } 30 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/internal/IdGenerator.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.internal; 2 | 3 | import java.util.concurrent.atomic.AtomicLong; 4 | 5 | 6 | /** 7 | * Id generator that avoids inter-thread coordination. 8 | * 9 | * @author Jaroslaw Odzga (jodzga@linkedin.com) 10 | * 11 | */ 12 | public class IdGenerator { 13 | 14 | private static final long CHUNK_SIZE = 1000; 15 | private static final AtomicLong _nextFreeId = new AtomicLong(); 16 | 17 | private static class Chunk { 18 | private long _current; 19 | private final long _max; 20 | 21 | public Chunk(long current, long max) { 22 | _current = current; 23 | _max = max; 24 | } 25 | 26 | public boolean isEmpty() { 27 | return _current == _max; 28 | } 29 | 30 | public long next() { 31 | return _current++; 32 | } 33 | } 34 | 35 | private static final ThreadLocal CHUNK = new ThreadLocal() { 36 | @Override 37 | protected Chunk initialValue() { 38 | return claim(); 39 | }; 40 | }; 41 | 42 | private static Chunk claim() { 43 | long newMax = _nextFreeId.addAndGet(CHUNK_SIZE); 44 | return new Chunk(newMax - CHUNK_SIZE, newMax); 45 | } 46 | 47 | public static long getNextId() { 48 | Chunk chunk = CHUNK.get(); 49 | if (chunk.isEmpty()) { 50 | chunk = claim(); 51 | CHUNK.set(chunk); 52 | } 53 | return chunk.next(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/internal/PlanBasedRateLimiter.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.internal; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | 6 | /** 7 | * Rate limiter that can apply throttling on plan class. 8 | * 9 | * @author Min Chen (mnchen@linkedin.com) 10 | */ 11 | public interface PlanBasedRateLimiter { 12 | /** 13 | * Try acquire a rate limit permit for the given plan class. 14 | * @param planClass plan class name. 15 | * @return true if a permit is granted, false otherwise. 16 | */ 17 | boolean tryAcquire(String planClass); 18 | 19 | /** 20 | * Try acquire a rate limit permit for the given plan class within the specified 21 | * time window. 22 | * @param planClass plan class name. 23 | * @param timeout timeout window 24 | * @param unit timeout unit. 25 | * @return true if a permit is granted within the time window, false otherwise. 26 | * @throws InterruptedException 27 | */ 28 | boolean tryAcquire(String planClass, long timeout, TimeUnit unit) throws InterruptedException; 29 | 30 | /** 31 | * Acquire a rate limit permit, blocking until the permit is granted. 32 | * @param planClass plan class name. 33 | * @throws InterruptedException 34 | */ 35 | void acquire(String planClass) throws InterruptedException; 36 | 37 | /** 38 | * Release a rate limit permit for the given plan class. 39 | * @param planClass plan class name 40 | */ 41 | void release(String planClass); 42 | } 43 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/internal/PlanCompletionListener.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.internal; 2 | 3 | /** 4 | * @author Ang Xu 5 | */ 6 | public interface PlanCompletionListener { 7 | 8 | void onPlanCompleted(PlanContext planContext); 9 | 10 | } 11 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/internal/PlanDeactivationListener.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.internal; 2 | 3 | import com.linkedin.parseq.EngineBuilder; 4 | 5 | /** 6 | * This listener interface allows receiving notifications about plan deactivation. 7 | * It can be used for monitoring and to optimize task implementation e.g. to implement batching. 8 | * @see EngineBuilder#setPlanDeactivationListener(PlanDeactivationListener) for details 9 | * 10 | * @author Jaroslaw Odzga (jodzga@linkedin.com) 11 | * 12 | */ 13 | public interface PlanDeactivationListener { 14 | 15 | void onPlanDeactivated(PlanContext planContext); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/internal/PlatformClock.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.internal; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | /** 6 | * Default implementation of Clock interface that delegates to default Java platform's nano timer. 7 | * 8 | * @author Jaroslaw Odzga (jodzga@linkedin.com) 9 | * 10 | */ 11 | public class PlatformClock implements Clock { 12 | 13 | @Override 14 | public long nanoTime() { 15 | return System.nanoTime(); 16 | } 17 | 18 | @Override 19 | public void sleepNano(long nano) throws InterruptedException { 20 | TimeUnit.NANOSECONDS.sleep(nano); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/internal/Prioritizable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq.internal; 18 | 19 | /** 20 | * @author Chris Pettitt (cpettitt@linkedin.com) 21 | */ 22 | public interface Prioritizable { 23 | int getPriority(); 24 | } 25 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/internal/PrioritizableRunnable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq.internal; 18 | 19 | import com.linkedin.parseq.Priority; 20 | 21 | 22 | /** 23 | * @author Chris Pettitt (cpettitt@linkedin.com) 24 | */ 25 | public interface PrioritizableRunnable extends Runnable, Prioritizable { 26 | 27 | @Override 28 | default int getPriority() { 29 | return Priority.DEFAULT_PRIORITY; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/internal/SerialExecutionException.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.internal; 2 | 3 | public class SerialExecutionException extends Exception { 4 | private static final long serialVersionUID = 0L; 5 | 6 | public SerialExecutionException(String msg, Throwable error) { 7 | super(msg, error); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/internal/SystemHiddenTask.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.internal; 2 | 3 | import com.linkedin.parseq.BaseTask; 4 | import com.linkedin.parseq.function.Function1; 5 | 6 | 7 | /** 8 | * Base class for system hidden tasks. It has exactly the same behavior as {@link BaseTask} 9 | * except the visibility of a trace created by this class is system hidden. 10 | *

11 | * Instead of extending this class consider using 12 | * 13 | * {@link com.linkedin.parseq.Task#async(String, Function1)}. 14 | * @see com.linkedin.parseq.Task#async(String, Function1) 15 | */ 16 | public abstract class SystemHiddenTask extends BaseTask { 17 | protected SystemHiddenTask(String name) { 18 | super(name); 19 | _shallowTraceBuilder.setSystemHidden(true); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/internal/TimeUnitHelper.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.internal; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | 6 | public class TimeUnitHelper { 7 | 8 | private static final String[] names = new String[] { "ns", "us", "ms", "s", "min", "h", "d" }; 9 | 10 | public static String toString(TimeUnit unit) { 11 | return names[unit.ordinal()]; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/internal/UncaughtExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.internal; 2 | 3 | /** 4 | * A handler that is invoked whenever the {@link SerialExecutor}'s execution loop 5 | * throws an uncaught exception. 6 | */ 7 | public interface UncaughtExceptionHandler { 8 | /** 9 | * This method is invoked whenever a {@link SerialExecutor}'s execution loop throws 10 | * an uncaught exception 11 | * 12 | * @param error the error that was raised by the underlying executor. 13 | */ 14 | void uncaughtException(Throwable error); 15 | } 16 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Core ParSeq classes. 3 | * See {@link com.linkedin.parseq.Task} for methods to create common types of Tasks. 4 | */ 5 | package com.linkedin.parseq; 6 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/promise/PromiseException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq.promise; 18 | 19 | /** 20 | * A general exception indicating that there was a {@link Promise} related 21 | * error. 22 | * 23 | * @author Chris Pettitt (cpettitt@linkedin.com) 24 | */ 25 | public class PromiseException extends RuntimeException { 26 | private static final long serialVersionUID = 1L; 27 | 28 | public PromiseException(final String message) { 29 | super(message); 30 | } 31 | 32 | public PromiseException(final Throwable cause) { 33 | super(cause); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/promise/PromisePropagator.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.promise; 2 | 3 | import java.util.function.BiConsumer; 4 | 5 | 6 | public interface PromisePropagator extends BiConsumer, Settable> { 7 | 8 | default PromisePropagator compose(final PromisePropagator propagator) { 9 | final PromisePropagator that = this; 10 | return (src, dst) -> { 11 | that.accept(src, new Settable() { 12 | @Override 13 | public void done(T value) throws PromiseResolvedException { 14 | propagator.accept(Promises.value(value), dst); 15 | } 16 | 17 | @Override 18 | public void fail(Throwable error) throws PromiseResolvedException { 19 | propagator.accept(Promises.error(error), dst); 20 | } 21 | }); 22 | }; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/promise/PromiseResolvedException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq.promise; 18 | 19 | /** 20 | * This exception is thrown when attempting to set a value or error on a promise 21 | * that is already resolved (i.e. already has a value or error). A promise can 22 | * only be resolved once. 23 | * 24 | * @author Chris Pettitt (cpettitt@linkedin.com) 25 | */ 26 | public class PromiseResolvedException extends PromiseException { 27 | private static final long serialVersionUID = 1L; 28 | 29 | public PromiseResolvedException(final String message) { 30 | super(message); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/promise/PromiseUnresolvedException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq.promise; 18 | 19 | /** 20 | * This exception is thrown when attempting to get a value from a promise 21 | * that has not yet finished. Use {@link Promise#addListener(PromiseListener)} 22 | * or {@link com.linkedin.parseq.promise.Promise#await()} to wait for the 23 | * completion of the promise before getting it's value. 24 | * 25 | * @author Chris Pettitt (cpettitt@linkedin.com) 26 | */ 27 | public class PromiseUnresolvedException extends PromiseException { 28 | private static final long serialVersionUID = 1L; 29 | 30 | public PromiseUnresolvedException(final String message) { 31 | super(message); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/promise/ResolvedError.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.promise; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | 6 | public class ResolvedError implements Promise { 7 | 8 | private final Throwable _error; 9 | 10 | public ResolvedError(Throwable error) { 11 | _error = error; 12 | } 13 | 14 | @Override 15 | public T get() throws PromiseException { 16 | throw new PromiseException(_error); 17 | } 18 | 19 | @Override 20 | public Throwable getError() throws PromiseUnresolvedException { 21 | return _error; 22 | } 23 | 24 | @Override 25 | public T getOrDefault(T defaultValue) throws PromiseUnresolvedException { 26 | return defaultValue; 27 | } 28 | 29 | @Override 30 | public void await() throws InterruptedException { 31 | } 32 | 33 | @Override 34 | public boolean await(long time, TimeUnit unit) throws InterruptedException { 35 | return true; 36 | } 37 | 38 | @Override 39 | public void addListener(PromiseListener listener) { 40 | listener.onResolved(this); 41 | } 42 | 43 | @Override 44 | public boolean isDone() { 45 | return true; 46 | } 47 | 48 | @Override 49 | public boolean isFailed() { 50 | return true; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/promise/ResolvedValue.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.promise; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | 9 | public class ResolvedValue implements Promise { 10 | 11 | private static final Logger LOGGER = LoggerFactory.getLogger(ResolvedValue.class); 12 | 13 | private final T _value; 14 | 15 | public ResolvedValue(T value) { 16 | _value = value; 17 | } 18 | 19 | @Override 20 | public T get() throws PromiseException { 21 | return _value; 22 | } 23 | 24 | @Override 25 | public Throwable getError() throws PromiseUnresolvedException { 26 | return null; 27 | } 28 | 29 | @Override 30 | public T getOrDefault(T defaultValue) throws PromiseUnresolvedException { 31 | return _value; 32 | } 33 | 34 | @Override 35 | public void await() throws InterruptedException { 36 | } 37 | 38 | @Override 39 | public boolean await(long time, TimeUnit unit) throws InterruptedException { 40 | return true; 41 | } 42 | 43 | @Override 44 | public void addListener(PromiseListener listener) { 45 | try { 46 | listener.onResolved(this); 47 | } catch (Throwable e) { 48 | LOGGER.warn("An exception was thrown by listener: " + listener.getClass(), e); 49 | } 50 | } 51 | 52 | @Override 53 | public boolean isDone() { 54 | return true; 55 | } 56 | 57 | @Override 58 | public boolean isFailed() { 59 | return false; 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/promise/Settable.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.promise; 2 | 3 | public interface Settable

{ 4 | /** 5 | * Sets the value for this promise to the given value. 6 | *

7 | * The guarantee is that after this method is finished the promise 8 | * has been completed but it is not guaranteed that all listeners have been 9 | * called. Listeners can be notified shortly after this method returns. 10 | * 11 | * @param value the value to set on this promise. 12 | * @throws PromiseResolvedException if the promise already has a value set. 13 | */ 14 | void done(P value) throws PromiseResolvedException; 15 | 16 | /** 17 | * Sets an error on this promise. 18 | *

19 | * The guarantee is that after this method is finished the promise 20 | * has been completed but it is not guaranteed that all listeners have been 21 | * called. Listeners can be notified shortly after this method returns. 22 | * 23 | * @param error the error to set on this promise 24 | * @throws PromiseResolvedException if the promise already has a value set. 25 | */ 26 | void fail(Throwable error) throws PromiseResolvedException; 27 | 28 | } 29 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/promise/SettablePromise.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq.promise; 18 | 19 | /** 20 | * A {@link Promise} that can have its value set. 21 | * 22 | * @author Chris Pettitt (cpettitt@linkedin.com) 23 | */ 24 | public interface SettablePromise

extends Promise

, Settable

{ 25 | } 26 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/promise/TransformingPromiseListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq.promise; 18 | 19 | public class TransformingPromiseListener implements PromiseListener { 20 | private final Settable _dest; 21 | private final PromisePropagator _propagator; 22 | 23 | public TransformingPromiseListener(final Settable dest, final PromisePropagator propagator) { 24 | _dest = dest; 25 | _propagator = propagator; 26 | } 27 | 28 | @Override 29 | public void onResolved(final Promise resolvedPromise) { 30 | _propagator.accept(resolvedPromise, _dest); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/promise/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Promises are like {@link java.util.concurrent.Future}s, but they provide 3 | * a listener mechanism to wait for completion asynchronously. 4 | *

5 | * @see com.linkedin.parseq.promise.Promise for details about the Promise 6 | * API. 7 | * @see com.linkedin.parseq.promise.Promises for convenience methods to create Promises. 8 | */ 9 | package com.linkedin.parseq.promise; 10 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/retry/ErrorClassification.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.retry; 2 | 3 | import java.util.concurrent.CancellationException; 4 | import java.util.function.Function; 5 | 6 | 7 | /** 8 | * Definitions of the supported error classifications and the default classification function. 9 | * 10 | * @author Oleg Anashkin (oleg.anashkin@gmail.com) 11 | */ 12 | public enum ErrorClassification { 13 | /** The classification of errors that will interrupt the retry operation. */ 14 | UNRECOVERABLE, 15 | 16 | /** The classification of errors that will not interrupt the retry operation. */ 17 | RECOVERABLE; 18 | 19 | /** Default error classification: non-fatal errors are recoverable, and fatal errors are not recoverable. */ 20 | public static final Function DEFAULT = throwable -> 21 | nonFatal(throwable) ? ErrorClassification.RECOVERABLE : ErrorClassification.UNRECOVERABLE; 22 | 23 | protected static boolean nonFatal(Throwable throwable) { 24 | return throwable instanceof StackOverflowError || !(throwable instanceof VirtualMachineError || throwable instanceof ThreadDeath 25 | || throwable instanceof InterruptedException || throwable instanceof LinkageError || throwable instanceof CancellationException); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/retry/backoff/ConstantBackoff.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.retry.backoff; 2 | 3 | 4 | /** 5 | * A policy that uses the same backoff after every retry. 6 | * 7 | * @author Oleg Anashkin (oleg.anashkin@gmail.com) 8 | */ 9 | public class ConstantBackoff implements BackoffPolicy { 10 | protected final long _backoff; 11 | 12 | /** 13 | * A policy that uses the same backoff after every retry. 14 | * 15 | * @param backoff The backoff used for every retry. 16 | */ 17 | public ConstantBackoff(final long backoff) { 18 | _backoff = backoff; 19 | } 20 | 21 | /** 22 | * {@inheritDoc} 23 | */ 24 | @Override 25 | public long nextBackoff(int attempts, Throwable error) { 26 | return _backoff; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/retry/backoff/ExponentialBackoff.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.retry.backoff; 2 | 3 | 4 | /** 5 | * A policy that doubles the backoff duration after every attempt. 6 | * 7 | * @author Oleg Anashkin (oleg.anashkin@gmail.com) 8 | */ 9 | public class ExponentialBackoff implements BackoffPolicy { 10 | protected final long _backoff; 11 | 12 | /** 13 | * A policy that doubles the backoff duration after every attempt. 14 | * 15 | * @param backoff The backoff used for the first retry as well as the base for all subsequent attempts. 16 | */ 17 | public ExponentialBackoff(final long backoff) { 18 | _backoff = backoff; 19 | } 20 | 21 | /** 22 | * {@inheritDoc} 23 | */ 24 | @Override 25 | public long nextBackoff(int attempts, Throwable error) { 26 | return (1L << attempts - 1) * _backoff; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/retry/backoff/FibonacciBackoff.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.retry.backoff; 2 | 3 | 4 | /** 5 | * A policy that increases the initial backoff duration by repeatedly multiplying by an approximation of the golden 6 | * ratio (8 / 5, the sixth and fifth fibonacci numbers). 7 | * 8 | * @author Oleg Anashkin (oleg.anashkin@gmail.com) 9 | */ 10 | public class FibonacciBackoff implements BackoffPolicy { 11 | protected final long _backoff; 12 | 13 | /** 14 | * A policy that increases the initial backoff duration by repeatedly multiplying by an approximation of the golden 15 | * ratio (8 / 5, the sixth and fifth fibonacci numbers). 16 | * 17 | * @param backoff The backoff used for the first retry as well as the base for all subsequent attempts. 18 | */ 19 | public FibonacciBackoff(final long backoff) { 20 | _backoff = backoff; 21 | } 22 | 23 | /** 24 | * {@inheritDoc} 25 | */ 26 | @Override 27 | public long nextBackoff(int attempts, Throwable error) { 28 | return Math.round(Math.pow(1.6, attempts - 1) * _backoff); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/retry/backoff/LinearBackoff.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.retry.backoff; 2 | 3 | 4 | /** 5 | * A policy that increases the backoff duration by the same amount after every retry. 6 | * 7 | * @author Oleg Anashkin (oleg.anashkin@gmail.com) 8 | */ 9 | public class LinearBackoff implements BackoffPolicy { 10 | protected final long _backoff; 11 | 12 | /** 13 | * A policy that increases the backoff duration by the same amount after every retry. 14 | * 15 | * @param backoff The backoff used for the first retry as well as the base for all subsequent attempts. 16 | */ 17 | public LinearBackoff(final long backoff) { 18 | _backoff = backoff; 19 | } 20 | 21 | /** 22 | * {@inheritDoc} 23 | */ 24 | @Override 25 | public long nextBackoff(int attempts, Throwable error) { 26 | return attempts * _backoff; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/retry/backoff/SelectedBackoff.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.retry.backoff; 2 | 3 | import java.util.function.Function; 4 | 5 | 6 | /** 7 | * A policy that delegates to another policy that is selected based on the most recent error. 8 | * 9 | * @author Oleg Anashkin (oleg.anashkin@gmail.com) 10 | */ 11 | public class SelectedBackoff implements BackoffPolicy { 12 | protected final Function _policyFunction; 13 | 14 | /** 15 | * A policy that delegates to another policy that is selected based on the most recent error. 16 | * 17 | * @param policyFunction The function that maps from errors to backoff policies. 18 | */ 19 | public SelectedBackoff(Function policyFunction) { 20 | _policyFunction = policyFunction; 21 | } 22 | 23 | /** 24 | * {@inheritDoc} 25 | */ 26 | @Override 27 | public long nextBackoff(int attempts, Throwable error) { 28 | return _policyFunction.apply(error).nextBackoff(attempts, error); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/retry/termination/GuavaRateLimiter.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.retry.termination; 2 | 3 | /** 4 | * A RateLimiter implementation based on the guava RateLimiter. 5 | * Guava RateLimiter uses the token bucket algorithm and this 6 | * rate limiter allows bursts. 7 | * 8 | * @author Mohamed Isoukrane (isoukrane.mohamed@gmail.com) 9 | */ 10 | public class GuavaRateLimiter implements RateLimiter { 11 | private final com.google.common.util.concurrent.RateLimiter _rateLimiter; 12 | 13 | public GuavaRateLimiter(double permitsPerSecond) { 14 | _rateLimiter = com.google.common.util.concurrent.RateLimiter.create(permitsPerSecond); 15 | } 16 | 17 | /** 18 | * {@inheritDoc} 19 | */ 20 | @Override 21 | public boolean tryAcquire() { 22 | return _rateLimiter.tryAcquire(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/retry/termination/LimitAttempts.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.retry.termination; 2 | 3 | import com.linkedin.parseq.internal.ArgumentUtil; 4 | 5 | 6 | /** 7 | * A termination policy that limits the number of attempts made. 8 | * 9 | * @author Oleg Anashkin (oleg.anashkin@gmail.com) 10 | */ 11 | public class LimitAttempts implements TerminationPolicy { 12 | protected final int _maxAttempts; 13 | 14 | /** 15 | * A termination policy that limits the number of attempts made. 16 | * 17 | * @param maxAttempts The maximum number of attempts that can be performed. 18 | */ 19 | public LimitAttempts(int maxAttempts) { 20 | ArgumentUtil.requirePositive(maxAttempts, "maxAttempts"); 21 | _maxAttempts = maxAttempts; 22 | } 23 | 24 | /** 25 | * {@inheritDoc} 26 | */ 27 | @Override 28 | public boolean shouldTerminate(int attempts, long nextAttemptAt) { 29 | return attempts >= _maxAttempts; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/retry/termination/LimitDuration.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.retry.termination; 2 | 3 | 4 | /** 5 | * A termination policy that limits the amount of time spent retrying. 6 | * 7 | * @author Oleg Anashkin (oleg.anashkin@gmail.com) 8 | */ 9 | public class LimitDuration implements TerminationPolicy { 10 | protected final long _maxDuration; 11 | 12 | /** 13 | * A termination policy that limits the amount of time spent retrying. 14 | * 15 | * @param maxDuration The maximum duration that a retry operation should not exceed. 16 | */ 17 | public LimitDuration(long maxDuration) { 18 | _maxDuration = maxDuration; 19 | } 20 | 21 | /** 22 | * {@inheritDoc} 23 | */ 24 | @Override 25 | public boolean shouldTerminate(int attempts, long nextAttemptAt) { 26 | return nextAttemptAt >= _maxDuration; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/retry/termination/LimitRate.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.retry.termination; 2 | 3 | /** 4 | * A termination policy that limits the rate of retries. 5 | * 6 | * @author Mohamed Isoukrane (isoukrane.mohamed@gmail.com) 7 | */ 8 | public class LimitRate implements TerminationPolicy { 9 | protected final RateLimiter _rateLimiter; 10 | 11 | /** 12 | * A termination policy that limits the rate of retries. 13 | * 14 | * @param rateLimiter The rate limiter implementation that will rate the retries qps. 15 | */ 16 | public LimitRate(RateLimiter rateLimiter) { 17 | _rateLimiter = rateLimiter; 18 | } 19 | 20 | /** 21 | * {@inheritDoc} 22 | */ 23 | @Override 24 | public boolean shouldTerminate(int attempts, long nextAttemptAt) { 25 | return !_rateLimiter.tryAcquire(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/retry/termination/RateLimiter.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.retry.termination; 2 | 3 | /** 4 | * A rate limiter that allows a certain number of retries per second. 5 | * 6 | * @author Mohamed Isoukrane (isoukrane.mohamed@gmail.com) 7 | */ 8 | public interface RateLimiter { 9 | 10 | /** 11 | * Acquires a permit to process a retry request if it can be acquired immediately without delay. 12 | * It needs ot be thread safe and nonblocking. 13 | */ 14 | boolean tryAcquire(); 15 | } 16 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/retry/termination/RequireAny.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.retry.termination; 2 | 3 | /** 4 | * A termination policy that signals for termination after any of the specified policies terminate. 5 | * 6 | * @author Mohamed Isoukrane (isoukrane.mohamed@gmail.com) 7 | */ 8 | public class RequireAny implements TerminationPolicy { 9 | 10 | private final TerminationPolicy[] _policies; 11 | 12 | /** 13 | * A termination policy that signals for termination after any of the specified policies terminate. 14 | * 15 | * @param policies The list of policies that may signal for termination. 16 | */ 17 | public RequireAny(TerminationPolicy... policies) { 18 | _policies = policies; 19 | } 20 | 21 | /** 22 | * {@inheritDoc} 23 | */ 24 | @Override 25 | public boolean shouldTerminate(int attempts, long nextAttemptAt) { 26 | for (TerminationPolicy policy : _policies) { 27 | if (policy.shouldTerminate(attempts, nextAttemptAt)) { 28 | return true; 29 | } 30 | } 31 | return false; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/retry/termination/RequireBoth.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.retry.termination; 2 | 3 | 4 | /** 5 | * A termination policy that signals for termination after both of the specified policies terminate. 6 | * 7 | * @author Oleg Anashkin (oleg.anashkin@gmail.com) 8 | */ 9 | public class RequireBoth implements TerminationPolicy { 10 | protected final TerminationPolicy _first; 11 | protected final TerminationPolicy _second; 12 | 13 | /** 14 | * A termination policy that signals for termination after both of the specified policies terminate. 15 | * 16 | * @param first The first of the two policies that must signal for termination. 17 | * @param second The second of the two policies that must signal for termination. 18 | */ 19 | public RequireBoth(TerminationPolicy first, TerminationPolicy second) { 20 | _first = first; 21 | _second = second; 22 | } 23 | 24 | /** 25 | * {@inheritDoc} 26 | */ 27 | @Override 28 | public boolean shouldTerminate(int attempts, long nextAttemptAt) { 29 | return _first.shouldTerminate(attempts, nextAttemptAt) && _second.shouldTerminate(attempts, nextAttemptAt); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/retry/termination/RequireEither.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.retry.termination; 2 | 3 | 4 | /** 5 | * A termination policy that signals for termination after either of the specified policies terminate. 6 | * 7 | * @author Oleg Anashkin (oleg.anashkin@gmail.com) 8 | */ 9 | public class RequireEither implements TerminationPolicy { 10 | protected final TerminationPolicy _first; 11 | protected final TerminationPolicy _second; 12 | 13 | /** 14 | * A termination policy that signals for termination after either of the specified policies terminate. 15 | * 16 | * @param first The first of the two policies that may signal for termination. 17 | * @param second The second of the two policies that may signal for termination. 18 | */ 19 | public RequireEither(TerminationPolicy first, TerminationPolicy second) { 20 | _first = first; 21 | _second = second; 22 | } 23 | 24 | /** 25 | * {@inheritDoc} 26 | */ 27 | @Override 28 | public boolean shouldTerminate(int attempts, long nextAttemptAt) { 29 | return _first.shouldTerminate(attempts, nextAttemptAt) || _second.shouldTerminate(attempts, nextAttemptAt); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/trace/Relationship.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq.trace; 18 | 19 | /** 20 | * A list of relationship types used by the trace system. 21 | * 22 | * @author Chris Pettitt (cpettitt@linkedin.com) 23 | * @author Chi Chan (ckchan@linkedin.com) 24 | */ 25 | public enum Relationship { 26 | PARENT_OF, 27 | SUCCESSOR_OF, 28 | POSSIBLE_SUCCESSOR_OF, 29 | CHILD_OF, 30 | POTENTIAL_CHILD_OF, 31 | POTENTIAL_PARENT_OF, 32 | } 33 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/trace/TraceUtil.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.trace; 2 | 3 | import java.io.IOException; 4 | 5 | import com.linkedin.parseq.Task; 6 | import com.linkedin.parseq.trace.codec.json.JsonTraceCodec; 7 | 8 | /** 9 | * @author Jaroslaw Odzga (jodzga@linkedin.com) 10 | */ 11 | public class TraceUtil { 12 | 13 | private static final JsonTraceCodec JSON_CODEC = new JsonTraceCodec(); 14 | 15 | /** 16 | * Returns trace of a task serialized to a JSON string. 17 | * @param task task to get trace from 18 | * @return JSON representation of the trace 19 | * @throws IOException 20 | */ 21 | public static String getJsonTrace(final Task task) throws IOException { 22 | return JSON_CODEC.encode(task.getTrace()); 23 | } 24 | 25 | /** 26 | * Returns trace serialized to a JSON string. 27 | * @param trace trace to serialize to JSON 28 | * @return JSON representation of the trace 29 | * @throws IOException 30 | */ 31 | public static String getJsonTrace(final Trace trace) throws IOException { 32 | return JSON_CODEC.encode(trace); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/trace/codec/json/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * {@link com.linkedin.parseq.trace.Trace} codec specific to the 3 | * JSON format. 4 | */ 5 | package com.linkedin.parseq.trace.codec.json; 6 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/trace/codec/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * {@link com.linkedin.parseq.trace.Trace} codec API. 3 | * 4 | * @see com.linkedin.parseq.trace.codec.TraceCodec 5 | */ 6 | package com.linkedin.parseq.trace.codec; 7 | -------------------------------------------------------------------------------- /subprojects/parseq/src/main/java/com/linkedin/parseq/trace/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Tracing related APIs and functionality. 3 | * 4 | * To get a {@link com.linkedin.parseq.trace.Trace} use 5 | * {@link com.linkedin.parseq.Task#getTrace()}. Use 6 | * {@link com.linkedin.parseq.trace.codec.json.JsonTraceCodec} to serialize a 7 | * Trace to a String. 8 | */ 9 | package com.linkedin.parseq.trace; 10 | -------------------------------------------------------------------------------- /subprojects/parseq/src/test/java/com/linkedin/parseq/TestCancellingPlanExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq; 2 | 3 | 4 | import com.linkedin.parseq.internal.PrioritizableRunnable; 5 | import com.linkedin.parseq.internal.SerialExecutor; 6 | import java.util.concurrent.TimeUnit; 7 | import org.testng.annotations.Test; 8 | 9 | 10 | public class TestCancellingPlanExceptionHandler extends BaseEngineTest { 11 | 12 | @Override 13 | protected void customizeEngine(EngineBuilder engineBuilder) { 14 | engineBuilder.setTaskQueueFactory(ThrowingTaskQueue::new); 15 | } 16 | 17 | @Test 18 | public void testThrowingTaskQueue() { 19 | Task task = Task.value(1); 20 | 21 | runAndWaitException(task, CancellationException.class, 5, TimeUnit.SECONDS); 22 | } 23 | 24 | private static class ThrowingTaskQueue implements SerialExecutor.TaskQueue { 25 | 26 | @Override 27 | public void add(PrioritizableRunnable value) { 28 | } 29 | 30 | @Override 31 | public PrioritizableRunnable poll() { 32 | return () -> { throw new RuntimeException(); }; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /subprojects/parseq/src/test/java/com/linkedin/parseq/TestWithTry.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq; 2 | 3 | import static org.testng.Assert.*; 4 | 5 | import org.testng.annotations.Test; 6 | 7 | import com.linkedin.parseq.function.Try; 8 | 9 | 10 | /** 11 | * @author Jaroslaw Odzga (jodzga@linkedin.com) 12 | */ 13 | public class TestWithTry extends BaseEngineTest { 14 | 15 | @Test 16 | public void testHappyPath() throws InterruptedException { 17 | final Task> task = Task.callable("test", () -> "hello").toTry(); 18 | 19 | runAndWait("TestWithTry.testHappyPath", task); 20 | 21 | assertFalse(task.get().isFailed()); 22 | assertEquals("hello", task.get().get()); 23 | } 24 | 25 | @Test 26 | public void testError() throws InterruptedException { 27 | @SuppressWarnings("unused") 28 | final Task> task = Task.callable("test", () -> { 29 | if (true) { 30 | throw new RuntimeException("boom"); 31 | } 32 | return "hello"; 33 | } ).toTry(); 34 | 35 | runAndWait("TestWithTry.testError", task); 36 | 37 | assertTrue(task.get().isFailed()); 38 | assertTrue(task.get().getError() instanceof RuntimeException); 39 | assertEquals(task.get().getError().getMessage(), "boom"); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /subprojects/parseq/src/test/java/com/linkedin/parseq/ThrowingRunnable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012 LinkedIn, Inc 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | package com.linkedin.parseq; 18 | 19 | /** 20 | * @author Chris Pettitt (cpettitt@linkedin.com) 21 | */ 22 | public interface ThrowingRunnable { 23 | void run() throws Exception; 24 | } 25 | -------------------------------------------------------------------------------- /subprojects/parseq/src/test/java/com/linkedin/parseq/internal/TestArgumentUtil.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.internal; 2 | 3 | import org.testng.annotations.Test; 4 | 5 | 6 | public class TestArgumentUtil { 7 | @Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = ".*foo.*") 8 | public void testNotNullWithNull() { 9 | ArgumentUtil.requireNotNull(null, "foo"); 10 | } 11 | 12 | @Test 13 | public void testNotNullWithNotNull() { 14 | // This should not throw 15 | ArgumentUtil.requireNotNull(new Object(), "foo"); 16 | } 17 | 18 | @Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = ".*foo.*") 19 | public void testNotEmptyWithNull() { 20 | ArgumentUtil.requireNotEmpty(null, "foo"); 21 | } 22 | 23 | @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = ".*foo.*") 24 | public void testNotEmptyWithEmptyString() { 25 | ArgumentUtil.requireNotEmpty("", "foo"); 26 | } 27 | 28 | @Test 29 | public void testNotEmptyWithNotEmptyString() { 30 | // This should not throw 31 | ArgumentUtil.requireNotEmpty("not empty string", "foo"); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /subprojects/parseq/src/test/java/com/linkedin/parseq/internal/TestClock.java: -------------------------------------------------------------------------------- 1 | package com.linkedin.parseq.internal; 2 | 3 | import com.linkedin.parseq.function.Consumer1; 4 | import java.util.concurrent.Callable; 5 | 6 | 7 | public class TestClock implements Clock { 8 | 9 | private final Callable _timer; 10 | 11 | private final Consumer1 _sleeper; 12 | 13 | public TestClock(Callable timer, Consumer1 sleeper) { 14 | _timer = timer; 15 | _sleeper = sleeper; 16 | } 17 | 18 | @Override 19 | public long nanoTime() { 20 | try { 21 | return _timer.call(); 22 | } catch (Exception e) { 23 | throw new RuntimeException(e); 24 | } 25 | } 26 | 27 | @Override 28 | public void sleepNano(long nano) throws InterruptedException { 29 | try { 30 | _sleeper.accept(nano); 31 | } catch (Exception e) { 32 | throw new RuntimeException(e); 33 | } 34 | } 35 | 36 | 37 | } 38 | -------------------------------------------------------------------------------- /subprojects/parseq/src/test/java/log4j.properties: -------------------------------------------------------------------------------- 1 | log4j.rootLogger=INFO, stdout 2 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender 3 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 4 | log4j.appender.stdout.layout.ConversionPattern=%d [%t] %-5p %c: %m%n 5 | --------------------------------------------------------------------------------