├── .github ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── publish.yml │ └── pull-request.yml ├── .gitignore ├── AUTHORS.txt ├── CONTRIBUTING.md ├── LICENSE.txt ├── README.md ├── build.sbt ├── compileOptions.sbt ├── docs ├── CONTRIBUTING.md ├── LICENSE.txt ├── actor-hierarchy.md ├── blocking-dispatcher.md ├── bootstrap.md ├── circuitbreaker.md ├── configuration.md ├── console.md ├── customizing-stream-control.md ├── deduplicate.md ├── flow-ordering.md ├── flow-retry.md ├── flow-timeout.md ├── http-services.md ├── httpclient.md ├── img │ ├── Processor.jpg │ ├── RequestContext.jpg │ ├── close-httpclient.png │ ├── delete-httpclient.png │ ├── deleteall-httpclients.png │ ├── favicon.ico │ ├── get-httpclient.png │ ├── getall-httpclients.png │ ├── httpclient-call-delete.png │ ├── httpclient-call-get.png │ ├── httpclient-call-head.png │ ├── httpclient-call-options.png │ ├── httpclient-call-post.png │ ├── httpclient-call-put.png │ ├── markdown-httpclient.png │ ├── markup-httpclient.png │ ├── squbs-actor-hierarchy.png │ ├── squbs-logo-transparent.png │ ├── update-httpclient-cb.png │ ├── update-httpclient-config.png │ ├── update-httpclient-fallback.png │ ├── update-httpclient-pipeline.png │ └── update-httpclient-settings.png ├── index.md ├── lifecycle.md ├── marshalling.md ├── materialization-metrics-collector.md ├── messages.md ├── monitor.md ├── orchestration_dsl.md ├── packaging.md ├── perpetualstream.md ├── persistent-buffer.md ├── pipeline.md ├── presentations.md ├── principles_of_the_squbs_design.md ├── registry.md ├── resolver.md ├── testing.md ├── timeoutpolicy.md ├── validation.md └── zkcluster.md ├── jvmopts ├── mkdocs.yml ├── project ├── Shared.scala ├── Versions.scala ├── build.properties └── plugins.sbt ├── publish.sbt ├── scalastyle-config.xml ├── sonatype_credentials.asc ├── squbs-actormonitor ├── NOTICE.txt ├── build.sbt └── src │ ├── main │ ├── resources │ │ ├── META-INF │ │ │ └── squbs-meta.conf │ │ ├── build.properties │ │ └── reference.conf │ └── scala │ │ └── org │ │ └── squbs │ │ └── actormonitor │ │ ├── ActorMonitor.scala │ │ ├── ActorMonitorBean.scala │ │ └── ActorMonitorInit.scala │ └── test │ ├── resources │ ├── README │ ├── classpaths │ │ ├── ActorMonitorCube │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ └── TestCube │ │ │ └── META-INF │ │ │ └── squbs-meta.conf │ └── reference.conf │ └── scala │ └── org │ └── squbs │ └── actormonitor │ ├── ActorMonitorSpec.scala │ └── TestCube │ └── TestCube.scala ├── squbs-actorregistry ├── NOTICE.txt ├── build.sbt └── src │ ├── main │ ├── resources │ │ ├── META-INF │ │ │ └── squbs-meta.conf │ │ ├── build.properties │ │ └── reference.conf │ └── scala │ │ └── org │ │ └── squbs │ │ └── actorregistry │ │ ├── ActorLookup.scala │ │ ├── ActorRegistry.scala │ │ ├── ActorRegistryBean.scala │ │ ├── ActorRegistryInit.scala │ │ └── japi │ │ └── ActorLookup.scala │ └── test │ ├── java │ └── org │ │ └── squbs │ │ └── actorregistry │ │ └── japi │ │ └── ActorRegistryTest.java │ ├── resources │ └── classpaths │ │ ├── ActorRegistryCube │ │ └── META-INF │ │ │ └── squbs-meta.conf │ │ ├── NoWellKnownActorsCube │ │ └── META-INF │ │ │ └── squbs-meta.conf │ │ ├── TestCube │ │ └── META-INF │ │ │ └── squbs-meta.conf │ │ └── TestCubeWithRouter │ │ └── META-INF │ │ └── squbs-meta.conf │ └── scala │ └── org │ └── squbs │ └── actorregistry │ ├── ActorRegistrySpec.scala │ ├── NoWellKnownActorsSpec.scala │ └── testcube │ └── TestCube.scala ├── squbs-admin ├── NOTICE.txt ├── build.sbt ├── findbugsExclude.xml └── src │ ├── main │ ├── resources │ │ └── META-INF │ │ │ └── squbs-meta.conf │ └── scala │ │ └── org │ │ └── squbs │ │ └── admin │ │ ├── AdminSvc.scala │ │ └── MBeanUtil.scala │ └── test │ └── scala │ └── org │ └── squbs │ └── admin │ ├── AdminSvcTest.scala │ └── MBeanUtilTest.scala ├── squbs-ext ├── NOTICE.txt ├── build.sbt └── src │ ├── main │ ├── java │ │ └── org │ │ │ └── squbs │ │ │ └── streams │ │ │ └── circuitbreaker │ │ │ └── impl │ │ │ └── AbstractAtomicCircuitBreakerLogic.java │ ├── resources │ │ └── reference.conf │ └── scala │ │ └── org │ │ ├── apache │ │ └── pekko │ │ │ └── http │ │ │ └── org │ │ │ └── squbs │ │ │ └── util │ │ │ └── JavaConverters.scala │ │ └── squbs │ │ ├── env │ │ └── Environment.scala │ │ ├── marshallers │ │ ├── MarshalUnmarshal.scala │ │ └── json │ │ │ ├── JacksonMapperSupport.scala │ │ │ ├── ReflectHelper.scala │ │ │ └── XLangJsonSupport.scala │ │ ├── metrics │ │ ├── MetricsExtension.scala │ │ └── MetricsFlow.scala │ │ ├── resolver │ │ └── Resolver.scala │ │ ├── streams │ │ ├── BoundedOrdering.scala │ │ ├── Deduplicate.scala │ │ ├── DemandSupplyMetrics.scala │ │ ├── Retry.scala │ │ ├── Timeout.scala │ │ ├── UniqueId.scala │ │ └── circuitbreaker │ │ │ ├── CircuitBreaker.scala │ │ │ ├── CircuitBreakerState.scala │ │ │ ├── impl │ │ │ └── AtomicCircuitBreakerState.scala │ │ │ └── japi │ │ │ └── CircuitBreakerSettings.scala │ │ └── util │ │ ├── ConfigUtil.scala │ │ └── DurationConverters.scala │ └── test │ ├── java │ └── org │ │ └── squbs │ │ ├── env │ │ └── EnvironmentTest.java │ │ ├── marshallers │ │ └── json │ │ │ ├── EmployeeBean.java │ │ │ ├── JacksonMapperTest.java │ │ │ ├── PageData.java │ │ │ ├── PagedResult.java │ │ │ ├── TeamBeanWithCaseClassMember.java │ │ │ ├── TeamWithPrivateMembers.java │ │ │ ├── XLangJsonSpecHelper.java │ │ │ └── XLangJsonTest.java │ │ ├── metrics │ │ └── MaterializationMetricsCollectorTest.java │ │ ├── resolver │ │ ├── DummyLocalhostJavaResolver.java │ │ └── ResolverTest.java │ │ └── streams │ │ ├── BoundedOrderingTest.java │ │ ├── RetryTest.java │ │ ├── TimeoutTest.java │ │ └── circuitbreaker │ │ ├── CircuitBreakerStateTest.java │ │ └── CircuitBreakerTest.java │ └── scala │ └── org │ └── squbs │ ├── env │ ├── DummyEnvironmentResolver.scala │ ├── EnvTestHelper.scala │ ├── EnvironmentResolverRegistryJMXSpec.scala │ └── EnvironmentSpec.scala │ ├── marshallers │ └── json │ │ ├── JacksonMapperSpec.scala │ │ ├── Json4sJacksonSpec.scala │ │ ├── Json4sNativeSpec.scala │ │ ├── ReflectHelperSpec.scala │ │ ├── TestData.scala │ │ └── XLangJsonSpec.scala │ ├── metrics │ ├── MaterializationMetricsCollectorSpec.scala │ └── MetricsFlowSpec.scala │ ├── resolver │ ├── DummyEndpointResolver.scala │ ├── ResolverRegistryJMXSpec.scala │ ├── ResolverSpec.scala │ └── ResolverTestHelper.scala │ ├── streams │ ├── BoundedOrderingSpec.scala │ ├── DeduplicateSpec.scala │ ├── DemandSupplyMetricsSpec.scala │ ├── RetryJMXSpec.scala │ ├── RetrySpec.scala │ ├── TimeoutSpec.scala │ └── circuitbreaker │ │ ├── CircuitBreakerSpec.scala │ │ └── CircuitBreakerStateSpec.scala │ └── util │ └── ConfigUtilSpec.scala ├── squbs-httpclient ├── NOTICE.txt ├── build.sbt └── src │ ├── main │ └── scala │ │ └── org │ │ └── squbs │ │ └── httpclient │ │ ├── ClientFlow.scala │ │ ├── DefaultHttpEndpointResolver.scala │ │ ├── HttpClientCircuitBreaker.scala │ │ ├── HttpClientException.scala │ │ ├── HttpClientJMX.scala │ │ ├── HttpEndpoint.scala │ │ ├── SSLEngineProvider.scala │ │ ├── TimeBucketMetrics.scala │ │ └── pipeline │ │ └── HttpClientPipeline.scala.waiting │ └── test │ ├── java │ └── org │ │ └── squbs │ │ └── httpclient │ │ ├── ClientFlowCircuitBreakerTest.java │ │ ├── ClientFlowHttpsEndpointTest.java │ │ ├── ClientFlowHttpsEnvTest.java │ │ ├── ClientFlowHttpsTest.java │ │ ├── ClientFlowPipelineTest.java │ │ ├── ClientFlowTest.java │ │ ├── HttpClientTest.java │ │ ├── JavaEndpointResolver.java │ │ └── JavaEndpointResolver2.java │ ├── resources │ ├── ClientFlowHttpsSpec │ │ ├── example.com.jks │ │ └── exampletrust.jks │ └── application.conf │ └── scala │ └── org │ └── squbs │ └── httpclient │ ├── ClientConfigurationSpec.scala │ ├── ClientFlowCircuitBreakerSpec.scala │ ├── ClientFlowHttpsProxySpec.scala │ ├── ClientFlowHttpsSpec.scala │ ├── ClientFlowIdleTimeoutSpec.scala │ ├── ClientFlowPipelineSpec.scala │ ├── ClientFlowSpec.scala │ ├── DefaultHttpEndpointResolverSpec.scala │ ├── HttpClientJMXSpec.scala │ ├── HttpClientSpec.scala │ ├── MetricsFlowSpec.scala │ ├── TimeBucketMetricsSpec.scala │ ├── dummy │ ├── DummyEndpointResolver.scala │ └── DummyService.scala │ └── package.scala ├── squbs-pattern ├── NOTICE.txt ├── build.sbt └── src │ ├── main │ ├── boilerplate │ │ └── org │ │ │ └── squbs │ │ │ └── pattern │ │ │ └── orchestration │ │ │ └── package.scala.template │ ├── java │ │ └── org │ │ │ └── squbs │ │ │ └── pattern │ │ │ ├── stream │ │ │ └── IndexFile.java │ │ │ └── timeoutpolicy │ │ │ ├── TimedFn.java │ │ │ └── TimeoutPolicyType.java │ └── scala │ │ └── org │ │ └── squbs │ │ └── pattern │ │ ├── orchestration │ │ ├── Aggregator.scala │ │ ├── OFuture.scala │ │ ├── OPromise.scala │ │ ├── Orchestrator.scala │ │ ├── impl │ │ │ └── OPromise.scala │ │ └── japi │ │ │ └── AbstractOrchestrator.scala │ │ ├── stream │ │ ├── BroadcastBuffer.scala │ │ ├── BroadcastBufferBase.scala │ │ ├── PersistentBuffer.scala │ │ ├── PersistentBufferBase.scala │ │ ├── PersistentQueue.scala │ │ ├── PersistentQueueCloserActor.scala │ │ ├── QueueConfig.scala │ │ └── QueueSerializer.scala │ │ ├── timeoutpolicy │ │ ├── MathUtil.scala │ │ ├── Metrics.scala │ │ ├── TimeoutPolicy.scala │ │ └── package.scala │ │ └── validation │ │ └── ValidationDirectives.scala │ └── test │ ├── java │ └── org │ │ └── squbs │ │ └── pattern │ │ ├── orchestration │ │ └── japi │ │ │ ├── AskOrchestrator.java │ │ │ ├── AskOrchestratorTest.java │ │ │ ├── Messages.java │ │ │ ├── OrchestratorTest.java │ │ │ ├── SelectionOrchestrator.java │ │ │ ├── SelectionOrchestratorTest.java │ │ │ ├── ServiceEmulator.java │ │ │ ├── TestOrchestrator.java │ │ │ └── TimedOutOrchestratorTest.java │ │ └── timeoutpolicy │ │ └── TimeoutPolicyJ.java │ └── scala │ └── org │ └── squbs │ └── pattern │ ├── orchestration │ ├── OFutureSpec.scala │ ├── OPromiseSpec.scala │ ├── OrchestratorSpec.scala │ ├── OrchestratorStress2Test.scala │ └── OrchestratorStressTest.scala │ ├── stream │ ├── BroadcastBufferAtLeastOnceSpec.scala │ ├── BroadcastBufferCommitOrderSpec.scala │ ├── BroadcastBufferSpec.scala │ ├── PersistentBufferAtLeastOnceSpec.scala │ ├── PersistentBufferCommitOrderSpec.scala │ ├── PersistentBufferSpec.scala │ ├── PersistentQueueSpec.scala │ ├── QueueConfigSpec.scala │ └── StreamSpecUtil.scala │ ├── timeoutpolicy │ ├── MathUtilSpec.scala │ ├── MetricsSpec.scala │ ├── SimulateDistributionSpec.scala │ ├── TimeoutPolicyFeatureSpec.scala │ ├── TimeoutPolicyJSpec.scala │ ├── TimeoutPolicySpec.scala │ └── TimeoutRuleConversionsSpec.scala │ └── validation │ ├── Person.scala │ └── ValidationDirectivesSpec.scala ├── squbs-pipeline ├── NOTICE.txt ├── build.sbt ├── findbugsExclude.xml └── src │ ├── main │ └── scala │ │ └── org │ │ └── squbs │ │ └── pipeline │ │ ├── PipelineExtension.scala │ │ ├── RequestContext.scala │ │ └── package.scala │ └── test │ ├── java │ └── org │ │ └── squbs │ │ └── pipeline │ │ ├── AbortableBidiFlowTest.java │ │ ├── DummyFlow2J.java │ │ ├── DummyFlowJ.java │ │ ├── PipelineExtensionTest.java │ │ ├── PostFlowJ.java │ │ ├── PreFlowJ.java │ │ └── RequestContextTest.java │ ├── resources │ └── testng.yaml │ └── scala │ └── org │ └── squbs │ └── pipeline │ ├── AbortableBidiFlowSpec.scala │ ├── PipelineExtensionSpec.scala │ ├── RequestContextSpec.scala │ └── Timeouts.scala ├── squbs-testkit ├── NOTICE.txt ├── build.sbt └── src │ ├── main │ ├── resources │ │ ├── build.properties │ │ └── default-test.conf │ └── scala │ │ └── org │ │ └── squbs │ │ └── testkit │ │ ├── CustomRouteTestKit.scala │ │ ├── CustomTestKit.scala │ │ ├── DebugTiming.scala │ │ ├── PortGetter.scala │ │ ├── Tags.scala │ │ ├── TestRoute.scala │ │ ├── Timeouts.scala │ │ ├── japi │ │ ├── CustomTestKit.scala │ │ ├── DebugTimingTestKit.scala │ │ ├── JUnitCustomRouteTestKit.scala │ │ ├── JUnitRouteTest.scala │ │ ├── RouteDefinitionTest.scala │ │ ├── TestNGCustomRouteTestKit.scala │ │ ├── TestNGRouteTest.scala │ │ └── Timeouts.scala │ │ └── stress │ │ └── LoadActor.scala │ └── test │ ├── java │ └── org │ │ └── squbs │ │ └── testkit │ │ ├── TestActorJ.java │ │ ├── japi │ │ ├── CustomTestKitConfigAndResourcesTest.java │ │ ├── CustomTestKitConfigTest.java │ │ ├── CustomTestKitDefaultJUnitTest.java │ │ ├── CustomTestKitDefaultWithActorSystemNameTest.java │ │ ├── CustomTestKitEmptyResourcesTest.java │ │ ├── CustomTestKitNoClassPathTest.java │ │ ├── CustomTestKitResourcesJUnitTest.java │ │ ├── CustomTestKitResourcesWithActorSystemNameTest.java │ │ ├── CustomTestKitTest.java │ │ ├── CustomTestKitWithClassPathTest.java │ │ ├── DecrementActor.java │ │ ├── IncrementActor.java │ │ ├── InfoRoute.java │ │ ├── InfoRouteWithActor.java │ │ ├── RouteInfo.java │ │ ├── RouteResultInfo.java │ │ ├── junit │ │ │ ├── CustomRouteTestKitConfigResourcesTest.java │ │ │ ├── CustomRouteTestKitConfigTest.java │ │ │ ├── CustomRouteTestKitResourcesTest.java │ │ │ ├── CustomRouteTestKitTest.java │ │ │ ├── CustomRouteTestKitWithClassPathTest.java │ │ │ └── RouteTestTest.java │ │ └── testng │ │ │ ├── CustomRouteTestKitConfigResourcesTest.java │ │ │ ├── CustomRouteTestKitConfigTest.java │ │ │ ├── CustomRouteTestKitResourcesTest.java │ │ │ ├── CustomRouteTestKitTest.java │ │ │ ├── CustomRouteTestKitWithClassPathTest.java │ │ │ └── RouteTestTest.java │ │ └── stress │ │ └── LoadActorTest.java │ ├── resources │ ├── CustomRouteTestKitSpec │ │ └── META-INF │ │ │ └── squbs-meta.conf │ ├── CustomTestKitDefaultSpec │ │ └── META-INF │ │ │ └── squbs-meta.conf │ ├── CustomTestKitTest │ │ └── META-INF │ │ │ └── squbs-meta.conf │ ├── META-INF │ │ └── squbs-meta.conf │ ├── PortGetterSpec │ │ └── META-INF │ │ │ └── squbs-meta.conf │ ├── README │ └── testng.yaml │ └── scala │ └── org │ └── squbs │ └── testkit │ ├── CustomRouteTestKitSpec.scala │ ├── CustomTestKitSpec.scala │ ├── PortGetterSpec.scala │ ├── TestRouteSpec.scala │ ├── package.scala │ └── stress │ └── LoadActorSpec.scala ├── squbs-unicomplex ├── NOTICE.txt ├── build.sbt └── src │ ├── main │ ├── java │ │ └── org │ │ │ └── squbs │ │ │ └── stream │ │ │ └── TriggerEvent.java │ ├── resources │ │ ├── build.properties │ │ └── reference.conf │ └── scala │ │ └── org │ │ └── squbs │ │ ├── dispatcher │ │ └── ForkJoinConfigurator.scala │ │ ├── lifecycle │ │ ├── ExtensionLifecycle.scala │ │ └── GracefulStopHelper.scala │ │ ├── stream │ │ ├── AbstractPerpetualStream.scala │ │ ├── LifecycleEventSource.scala │ │ ├── PerpetualStream.scala │ │ ├── PerpetualStreamBase.scala │ │ └── TriggerMerge.scala │ │ └── unicomplex │ │ ├── Bootstrap.scala │ │ ├── FlowHandler.scala │ │ ├── Headers.scala │ │ ├── JMX.scala │ │ ├── JavaServiceDefinitions.scala │ │ ├── ServiceRegistry.scala │ │ ├── ServiceRegistryBase.scala │ │ ├── Unicomplex.scala │ │ └── UnicomplexBoot.scala │ └── test │ ├── java │ └── org │ │ └── squbs │ │ ├── lifecycle │ │ └── GracefulStopHelperTest.java │ │ ├── stream │ │ ├── HttpFlowWithMergeHubJ.java │ │ ├── IllegalStateStreamJ.java │ │ ├── KillSwitchMatStreamJ.java │ │ ├── KillSwitchStreamJ.java │ │ ├── KillSwitchWithChildActorStreamJ.java │ │ ├── PerpetualStreamWithMergeHubJ.java │ │ ├── ProperShutdownStreamJ.java │ │ ├── ThrowExceptionStreamJ.java │ │ ├── TriggerMergeJ.java │ │ ├── UnicomplexActorPublisherJ.java │ │ └── javasamples │ │ │ ├── HttpFlowWithMergeHub.java │ │ │ ├── MsgReceivingStream.java │ │ │ └── PerpetualStreamWithMergeHub.java │ │ └── unicomplex │ │ ├── javafailedflowsvc │ │ └── JavaFailedFlowSvc.java │ │ ├── javafailedroutesvc │ │ └── JavaFailedRouteSvc.java │ │ ├── javaflowsvc │ │ └── JavaFlowSvc.java │ │ ├── javaroutenohandlersvc │ │ └── JavaRouteNoHandlerSvc.java │ │ └── javaroutesvc │ │ └── JavaRouteSvc.java │ ├── resources │ ├── META-INF │ │ └── squbs-meta.conf │ ├── README │ ├── classpaths │ │ ├── BadCube │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── BadCube1 │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── BadCube2 │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── BadUnicomplexBoot │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── ClassNotFoundCube │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── ConnectionMetricsSpec │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── CubeActorErrorStates │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── DummyCube │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── DummyCubeSvc │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── DummyExtensions │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── DummyFailedExtensions │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── DummyFailedFlowSvc1 │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── DummyFlowSvc │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── DummySvc │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── DummySvcActor │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── FailedRouteSvc │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── FlowDefinitionSpec │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── IllegalStateStream │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── InitBlockCube │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── InitCubeA │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── InitCubeB │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── InitFailCube │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── InvalidPipelineFlowSvc │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── JavaFailedFlowSvc │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── JavaFailedRouteSvc │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── JavaFlowSvc │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── JavaIllegalStateStream │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── JavaKillSwitchMatStream │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── JavaKillSwitchStream │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── JavaKillSwitchWithChildActorStream │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── JavaPerpetualStreamMergeHubSpec │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── JavaProperShutdownStream │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── JavaRootSvc │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── JavaRouteNoHandlerSvc │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── JavaRouteSvc │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── JavaThrowExceptionStream │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── KillSwitchMatStream │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── KillSwitchStream │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── KillSwitchWithChildActorStream │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── ListenerState │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── LocalPortListener │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── MaterializerSpec │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── MultiListeners │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── PerpetualStreamMergeHubSpec │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── ProperShutdownStream │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── RootCtxFlowSpec │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── RootCtxRoute │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── RouteActorHandler │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── RouteDefinitionSpec │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── StashCube │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── StreamSvc │ │ │ ├── META-INF │ │ │ │ └── squbs-meta.conf │ │ │ └── dummy.txt │ │ ├── ThrowExceptionStream │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ ├── UnicomplexBootTimeouts │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ └── pipeline │ │ │ ├── BadPipelineFactorySpec │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ │ ├── BadPipelineNameSpec │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ │ ├── MetricsFlowSpec │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ │ ├── PipelineChunkingSpec │ │ │ └── META-INF │ │ │ │ └── squbs-meta.conf │ │ │ └── PipelineSpec │ │ │ └── META-INF │ │ │ └── squbs-meta.conf │ └── reference.conf │ └── scala │ └── org │ └── squbs │ ├── dispatcher │ └── ForkJoinConfiguratorSpec.scala │ ├── lifecycle │ └── GracefulStopHelperSpec.scala │ ├── stream │ ├── IllegalStateStream.scala │ ├── JavaPerpetualStreamSpec.scala │ ├── KillSwitchMatStream.scala │ ├── KillSwitchStream.scala │ ├── KillSwitchWithChildActorStream.scala │ ├── PerpetualStreamMatValueSpec.scala │ ├── PerpetualStreamMergeHubJSpec.scala │ ├── PerpetualStreamMergeHubSpec.scala │ ├── PerpetualStreamSpec.scala │ ├── ProperShutdownStream.scala │ ├── ThrowExceptionStream.scala │ ├── TriggerMergeJSpec.scala │ ├── TriggerMergeSpec.scala │ ├── UnicomplexActorPublisherJSpec.scala │ └── UnicomplexActorPublisherSpec.scala │ └── unicomplex │ ├── BadUnicomplexBootSpec.scala │ ├── ClassNotFoundSpec.scala │ ├── ConnectionMetricsSpec.scala │ ├── CubeActorErrorStatesSpec.scala │ ├── FailedFlow1Spec.scala │ ├── FailedRouteSvcSpec.scala │ ├── FlowDefinitionSpec.scala │ ├── InvalidPipelineFlowSpec.scala │ ├── JavaFailedFlowSvcSpec.scala │ ├── JavaFailedRouteSvcSpec.scala │ ├── JavaFlowSvcSpec.scala │ ├── JavaRootSvcSpec.scala │ ├── JavaRouteNoHandlerSvcSpec.scala │ ├── JavaRouteSvcSpec.scala │ ├── ListenerStateSpec.scala │ ├── LocalPortListenerSpec.scala │ ├── MultiListenerSpec.scala │ ├── MultipleUnicomplexTest.scala │ ├── RegisterContextSpec.scala │ ├── RootCtxFlowSpec.scala │ ├── RootCtxRouteSpec.scala │ ├── RouteActorHandlerSpec.scala │ ├── RouteDefinitionSpec.scala │ ├── ScanResourceSpec.scala │ ├── ServiceRegistrySpec.scala │ ├── ShutdownSpec.scala │ ├── StopAndStartCubeSpec.scala │ ├── StreamTestSpec.scala │ ├── SystemSettingBeanSpec.scala │ ├── SystemStatusTest.scala │ ├── TestMsg.scala │ ├── Timeouts.scala │ ├── UnicomplexBootSpec.scala │ ├── UnicomplexPortAutoSelectSpec.scala │ ├── UnicomplexSpec.scala │ ├── UnicomplexTestModeOnSpec.scala │ ├── UnicomplexTimeoutSpec.scala │ ├── cubeA │ └── CubeA.scala │ ├── cubeB │ └── CubeB.scala │ ├── dummycube │ └── DummyCube.scala │ ├── dummycubesvc │ └── PingPongSvc.scala │ ├── dummyextensions │ └── DummyExtensions.scala │ ├── dummyfailedextensions │ └── DummyFailedExtensions.scala │ ├── dummyfailedflowsvc1 │ └── DummyFailedFlowSvc1.scala │ ├── dummyflowsvc │ └── DummyFlowSvc.scala │ ├── dummysvc │ └── DummySvc.scala │ ├── dummysvcactor │ └── DummySvcActor.scala │ ├── initblock │ └── InitBlockActor.scala │ ├── initfail │ └── InitFailActor.scala │ ├── package.scala │ ├── pipeline │ ├── BadPipelineFactorySpec.scala │ ├── BadPipelineNameSpec.scala │ ├── MetricsFlowSpec.scala │ ├── PipelineChunkingSpec.scala │ └── PipelineSpec.scala │ ├── stashcube │ └── StashCubeSvc.scala │ ├── streamSvc │ └── StreamSvc.scala │ └── timeout │ └── ConfigurableInitTimeActor.scala ├── squbs-zkcluster ├── .gitignore ├── NOTICE.txt ├── build.sbt └── src │ ├── main │ ├── resources │ │ ├── build.properties │ │ └── reference.conf │ └── scala │ │ └── org │ │ └── squbs │ │ └── cluster │ │ ├── JMX.scala │ │ ├── RemoteGuardian.scala │ │ ├── ZkCluster.scala │ │ ├── ZkClusterActor.scala │ │ ├── ZkMembershipMonitor.scala │ │ ├── ZkMessages.scala │ │ ├── ZkPartitionsManager.scala │ │ ├── package.scala │ │ └── rebalance │ │ ├── DataCenterAwareness.scala │ │ └── package.scala │ └── test │ ├── resources │ ├── logback.xml │ ├── reference.conf │ └── zoo.cfg │ └── scala │ └── org │ └── squbs │ └── cluster │ ├── DataCenterAwarenessSpec.scala │ ├── SessionExpirationTest.scala │ ├── ZkClusterEdgeCaseTest.scala │ ├── ZkClusterInitTest.scala │ ├── ZkClusterNormalTest.scala │ └── test │ ├── ZkClusterMultiActorSystemTestKit.scala │ └── ZkClusterTestHelper.scala └── version.sbt /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | Thanks for your pull request. Please review the following guidelines. 3 | 4 | - [ ] Title includes issue id. 5 | - [ ] Description of the change added. 6 | - [ ] Commits are squashed. 7 | - [ ] Tests added. 8 | - [ ] Documentation added/updated. 9 | - [ ] Also please review [CONTRIBUTING.md](https://github.com/paypal/squbs/blob/master/CONTRIBUTING.md). 10 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 'on': 3 | push: 4 | branches: 5 | - master 6 | jobs: 7 | test: 8 | strategy: 9 | matrix: 10 | scala-version: [2.12.15, 2.13.7] 11 | runs-on: ubuntu-latest 12 | env: 13 | ACTION_JDK_VERSION: openjdk8 14 | SCALA_VERSION: ${{ matrix.scala-version }} 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v4 18 | - name: Setup JDK 19 | uses: olafurpg/setup-scala@v11 20 | with: 21 | java-version: adopt@1.8.0 22 | - name: Import GPG key 23 | id: import_gpg 24 | uses: crazy-max/ghaction-import-gpg@v6 25 | with: 26 | gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} 27 | passphrase: ${{ secrets.PASSPHRASE }} 28 | - run: sbt ++$SCALA_VERSION clean coverage test 29 | - run: sbt ++$SCALA_VERSION coverageReport 30 | - run: sbt ++$SCALA_VERSION coverageAggregate 31 | - run: gpg --batch --passphrase ${{ secrets.PASSPHRASE }} --decrypt sonatype_credentials.asc > ~/.sbt/.sonatype_credentials 32 | - run: echo 'credentials += Credentials(Path.userHome / ".sbt" / ".sonatype_credentials")' > ~/.sbt/1.0/sonatype.sbt 33 | - run: sbt ++$SCALA_VERSION clean publishSigned 34 | - run: rm ~/.sbt/1.0/sonatype.sbt ~/.sbt/.sonatype_credentials 35 | -------------------------------------------------------------------------------- /.github/workflows/pull-request.yml: -------------------------------------------------------------------------------- 1 | name: Pull Request 2 | 'on': 3 | pull_request: 4 | branches: 5 | - master 6 | jobs: 7 | test: 8 | strategy: 9 | matrix: 10 | scala-version: [2.12.15, 2.13.7] 11 | runs-on: ubuntu-latest 12 | env: 13 | ACTION_JDK_VERSION: openjdk8 14 | SCALA_VERSION: ${{ matrix.scala-version }} 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v4 18 | - name: Setup JDK 19 | uses: olafurpg/setup-scala@v11 20 | with: 21 | java-version: adopt@1.8.0 22 | - run: sbt ++$SCALA_VERSION clean coverage test 23 | - run: sbt ++$SCALA_VERSION coverageReport 24 | - run: sbt ++$SCALA_VERSION coverageAggregate 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | *.iml 3 | *.log 4 | .cache 5 | .DS_Store 6 | bin 7 | report/ 8 | squbsconfig/ 9 | var/ 10 | 11 | # sbt specific 12 | .bsp/ 13 | dist/* 14 | target/ 15 | test-output/ 16 | lib_managed/ 17 | src_managed/ 18 | project/boot/ 19 | project/plugins/project/ 20 | 21 | # Scala-IDE specific 22 | .scala_dependencies 23 | 24 | # IntelliJ specific 25 | .idea/ 26 | .metadata/ 27 | temp_*.xml 28 | .idea_modules/ 29 | 30 | # travis-ci 31 | local.* 32 | -------------------------------------------------------------------------------- /AUTHORS.txt: -------------------------------------------------------------------------------- 1 | squbs 2 | 3 | Original Authors 4 | ---------------- 5 | eBay 6 | (c) 2015 7 | 8 | PayPal 9 | (c) 2015 10 | 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![image](docs/img/squbs-logo-transparent.png) 2 | 3 | [![Join the chat at https://gitter.im/paypal/squbs](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/paypal/squbs?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 4 | [![Build Status](https://github.com/paypal/squbs/actions/workflows/publish.yml/badge.svg)](https://github.com/paypal/squbs/actions/workflows/publish.yml) 5 | [![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.squbs/squbs-unicomplex_2.12/badge.svg?style=flat)](http://search.maven.org/#search|ga|1|g:org.squbs) 6 | [![License](https://img.shields.io/badge/License-Apache%202.0-red.svg)](https://opensource.org/licenses/Apache-2.0) 7 | 8 | squbs (pronounced "skewbs") is a suite of components enabling standardization and operationalization of Pekko and Pekko HTTP applications/services in a large scale, managed, cloud environment. It standardizes how Pekko applications are deployed in different environments and how they are hooked up to the operational environments of large, internet-scale organizations. 9 | 10 | ## Documentation 11 | 12 | [![Documentation Status](https://readthedocs.org/projects/squbs/badge/?version=latest)](https://squbs.readthedocs.io) 13 | 14 | [https://paypal.github.io/squbs/](https://paypal.github.io/squbs/) 15 | 16 | ## Getting Started 17 | 18 | The easiest way to getting started is to create a project from one of the squbs templates. The followings are currently available giter8 templates: 19 | 20 | * [squbs-scala-seed](https://github.com/paypal/squbs-scala-seed.g8): Template for creating sample squbs scala application 21 | * [squbs-java-seed](https://github.com/paypal/squbs-java-seed.g8): Template for creating sample squbs java application 22 | 23 | ## Contributing to squbs 24 | 25 | Thank you very much for contributing to squbs. Please read the [contribution guidelines](CONTRIBUTING.md) for the process. 26 | 27 | ## License 28 | 29 | squbs is licensed under the [Apache License, v2.0](LICENSE.txt) 30 | -------------------------------------------------------------------------------- /docs/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ../CONTRIBUTING.md -------------------------------------------------------------------------------- /docs/LICENSE.txt: -------------------------------------------------------------------------------- 1 | ../LICENSE.txt -------------------------------------------------------------------------------- /docs/img/Processor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paypal/squbs/2569bf50c7510a4a0817e50978be0826f07b6dcd/docs/img/Processor.jpg -------------------------------------------------------------------------------- /docs/img/RequestContext.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paypal/squbs/2569bf50c7510a4a0817e50978be0826f07b6dcd/docs/img/RequestContext.jpg -------------------------------------------------------------------------------- /docs/img/close-httpclient.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paypal/squbs/2569bf50c7510a4a0817e50978be0826f07b6dcd/docs/img/close-httpclient.png -------------------------------------------------------------------------------- /docs/img/delete-httpclient.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paypal/squbs/2569bf50c7510a4a0817e50978be0826f07b6dcd/docs/img/delete-httpclient.png -------------------------------------------------------------------------------- /docs/img/deleteall-httpclients.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paypal/squbs/2569bf50c7510a4a0817e50978be0826f07b6dcd/docs/img/deleteall-httpclients.png -------------------------------------------------------------------------------- /docs/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paypal/squbs/2569bf50c7510a4a0817e50978be0826f07b6dcd/docs/img/favicon.ico -------------------------------------------------------------------------------- /docs/img/get-httpclient.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paypal/squbs/2569bf50c7510a4a0817e50978be0826f07b6dcd/docs/img/get-httpclient.png -------------------------------------------------------------------------------- /docs/img/getall-httpclients.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paypal/squbs/2569bf50c7510a4a0817e50978be0826f07b6dcd/docs/img/getall-httpclients.png -------------------------------------------------------------------------------- /docs/img/httpclient-call-delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paypal/squbs/2569bf50c7510a4a0817e50978be0826f07b6dcd/docs/img/httpclient-call-delete.png -------------------------------------------------------------------------------- /docs/img/httpclient-call-get.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paypal/squbs/2569bf50c7510a4a0817e50978be0826f07b6dcd/docs/img/httpclient-call-get.png -------------------------------------------------------------------------------- /docs/img/httpclient-call-head.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paypal/squbs/2569bf50c7510a4a0817e50978be0826f07b6dcd/docs/img/httpclient-call-head.png -------------------------------------------------------------------------------- /docs/img/httpclient-call-options.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paypal/squbs/2569bf50c7510a4a0817e50978be0826f07b6dcd/docs/img/httpclient-call-options.png -------------------------------------------------------------------------------- /docs/img/httpclient-call-post.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paypal/squbs/2569bf50c7510a4a0817e50978be0826f07b6dcd/docs/img/httpclient-call-post.png -------------------------------------------------------------------------------- /docs/img/httpclient-call-put.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paypal/squbs/2569bf50c7510a4a0817e50978be0826f07b6dcd/docs/img/httpclient-call-put.png -------------------------------------------------------------------------------- /docs/img/markdown-httpclient.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paypal/squbs/2569bf50c7510a4a0817e50978be0826f07b6dcd/docs/img/markdown-httpclient.png -------------------------------------------------------------------------------- /docs/img/markup-httpclient.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paypal/squbs/2569bf50c7510a4a0817e50978be0826f07b6dcd/docs/img/markup-httpclient.png -------------------------------------------------------------------------------- /docs/img/squbs-actor-hierarchy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paypal/squbs/2569bf50c7510a4a0817e50978be0826f07b6dcd/docs/img/squbs-actor-hierarchy.png -------------------------------------------------------------------------------- /docs/img/squbs-logo-transparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paypal/squbs/2569bf50c7510a4a0817e50978be0826f07b6dcd/docs/img/squbs-logo-transparent.png -------------------------------------------------------------------------------- /docs/img/update-httpclient-cb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paypal/squbs/2569bf50c7510a4a0817e50978be0826f07b6dcd/docs/img/update-httpclient-cb.png -------------------------------------------------------------------------------- /docs/img/update-httpclient-config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paypal/squbs/2569bf50c7510a4a0817e50978be0826f07b6dcd/docs/img/update-httpclient-config.png -------------------------------------------------------------------------------- /docs/img/update-httpclient-fallback.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paypal/squbs/2569bf50c7510a4a0817e50978be0826f07b6dcd/docs/img/update-httpclient-fallback.png -------------------------------------------------------------------------------- /docs/img/update-httpclient-pipeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paypal/squbs/2569bf50c7510a4a0817e50978be0826f07b6dcd/docs/img/update-httpclient-pipeline.png -------------------------------------------------------------------------------- /docs/img/update-httpclient-settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paypal/squbs/2569bf50c7510a4a0817e50978be0826f07b6dcd/docs/img/update-httpclient-settings.png -------------------------------------------------------------------------------- /docs/monitor.md: -------------------------------------------------------------------------------- 1 | # Monitoring Actors at Runtime 2 | 3 | ## Overview 4 | 5 | The squbs-actormonitor module attaches monitoring to each actor in the actor system. For large number of actors, this can get intrusive. The number of actors to monitor can be configured through `application.conf`. Use judgement attaching this module in production. There is no user API to this module. 6 | 7 | ## Dependencies 8 | 9 | Add the following dependency to your build.sbt or scala build file: 10 | 11 | ``` 12 | "org.squbs" %% "squbs-actormonitor" % squbsVersion 13 | ``` 14 | 15 | ## Monitoring 16 | 17 | Each actor has a corresponding JMXBean(org.squbs.unicomplex:type=ActorMonitor,name=%actorPath) to expose the actor information: 18 | 19 | ``` 20 | trait ActorMonitorMXBean { 21 | def getActor: String 22 | def getClassName: String 23 | def getRouteConfig : String 24 | def getParent: String 25 | def getChildren: String 26 | def getDispatcher : String 27 | def getMailBoxSize : String 28 | } 29 | ``` 30 | 31 | ## Configuration 32 | 33 | The following is the configuration entries for squbs-actormonitor: 34 | 35 | ``` 36 | squbs-actormonitor = { 37 | maxActorCount = 500 38 | maxChildrenDisplay = 20 39 | } 40 | ``` 41 | 42 | A JMX Bean `org.squbs.unicomplex:type=ActorMonitor` exposes the configuration of Actor Monitor. The JMX Bean is read-only. 43 | 44 | ``` 45 | trait ActorMonitorConfigMXBean { 46 | def getCount : Int //Count of JMX bean has been created 47 | def getMaxCount: Int //Maximum JMX bean can be created 48 | def getMaxChildrenDisplay: Int //Per each actor, maximum children can be exposed 49 | } 50 | ``` 51 | 52 | 53 | -------------------------------------------------------------------------------- /docs/packaging.md: -------------------------------------------------------------------------------- 1 | # Application Lifecycle Management 2 | 3 | This page describes a quick way to package, deploy, and start a squbs application. This guide uses Amazon EC2 as an example, showing how to run a squbs application in less than half an hour. 4 | 5 | ## Packaging 6 | 7 | You need to install the following on your build instance 8 | 9 | - [git](https://git-scm.com/downloads) 10 | - [java 8](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html) 11 | - [sbt](http://www.scala-sbt.org/release/docs/Setup.html) 12 | 13 | Steps to build: 14 | 15 | - Clone the source code from the git repo to the `` directory 16 | - cd `` 17 | - Run the sbt build command, including "packArchive", such as: `sbt clean update test packArchive` 18 | - There are two archives created under `/target` 19 | - `-.tar.gz` 20 | - `-.zip` 21 | 22 | ## Start 23 | 24 | You need to install the following on your running instance 25 | 26 | - [java 8](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html) 27 | 28 | Steps to run: 29 | 30 | - Copy either of the archives to the running instance 31 | - `-.tar.gz` 32 | - `-.zip` 33 | - For example, explode the tarball `tar zxvf -.tar.gz` to the `-` directory 34 | - start the application `-/bin/run &` 35 | - You can check the admin `http://localhost:8080/adm` from that instance, or `http://:8080/adm` 36 | 37 | ## Shutdown 38 | 39 | You can terminate the running process, for example, in linux `kill $(lsof -ti TCP:8080 | head -1)` 40 | Since the application registers a shutdown hook with the JVM, it will shutdown gracefully, unless it is abrupt. 41 | 42 | ## Amazon EC2 43 | 44 | Log into AWS EC2 and launch an instance 45 | 46 | - You can create from free-tier, if the capacity meet your needs 47 | - Security group open (inbound) SSH – port 22, Custom TCP Rule – 8080 48 | - SSH into server (see AWS Console -> Instances -> Actions -> Connect) 49 | - Execute step `Start` and `Shutdown` as described above 50 | -------------------------------------------------------------------------------- /docs/presentations.md: -------------------------------------------------------------------------------- 1 | # Presentations 2 | 3 | ## QCon London 4 | 5 | Streaming Reactive Systems & Data Pipes w. Squbs - March 5, 2018 6 | 7 | * [Video Recording and Slides](https://www.infoq.com/presentations/squbs) 8 | 9 | ## Reactive Summit 10 | 11 | Back-Pressure in Action: Handling High-Burst Workloads with pekko Streams & Kafka - October 5, 2016 12 | 13 | * [Video Recording](https://www.youtube.com/watch?v=dsuvnoEezxs) 14 | * [Slides](http://www.slideshare.net/AkaraSucharitakul/backpressure-in-action-handling-highburst-workloads-with-pekko-streams-kafka) 15 | 16 | ## Scala Up North 17 | 18 | Service Stampede: Surviving a Thousand Services - August 5, 2016 19 | 20 | * [Video Recording](https://www.youtube.com/watch?v=8hJMcI8O5J0&list=PL-ziwLLJ3XaLspsk9o7gQJB5oZtqS43Qu&index=5) 21 | * [Slides](http://www.slideshare.net/AnilGursel/service-stampede-surviving-a-thousand-services) 22 | 23 | ## Scala Bay Meetup 24 | 25 | Asynchronous Orchestration DSL on squbs - June 13, 2016 26 | 27 | * [Video Recording](https://www.youtube.com/watch?v=qeBlZF-MB78) 28 | * [Slides](https://www.slideshare.net/AnilGursel/asynchronous-orchestration-dsl-on-squbs) 29 | -------------------------------------------------------------------------------- /jvmopts: -------------------------------------------------------------------------------- 1 | -Xms1g 2 | -Xmx1g 3 | -Dfile.encoding=UTF8 4 | 5 | -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: squbs 2 | theme: readthedocs 3 | repo_url: https://github.com/paypal/squbs 4 | edit_uri: blob/master/docs/ 5 | pages: 6 | - Overview: 'index.md' 7 | - About: 8 | - 'Contributing': 'CONTRIBUTING.md' 9 | - 'License': 'LICENSE.txt' 10 | - 'Presentations': 'presentations.md' 11 | - Documentation: 12 | - 'Principles of squbs Design': 'principles_of_the_squbs_design.md' 13 | - 'Unicomplex & Cube Bootstrapping': 'bootstrap.md' 14 | - 'Unicomplex Actor Hierarchy': 'actor-hierarchy.md' 15 | - 'Runtime Lifecycle & API': 'lifecycle.md' 16 | - 'Implementing HTTP(S) Services': 'http-services.md' 17 | - 'Pekko HTTP Client on Steroids': 'httpclient.md' 18 | - 'Request/Response Pipeline': 'pipeline.md' 19 | - 'Marshalling and Unmarshalling': 'marshalling.md' 20 | - 'Configuration': 'configuration.md' 21 | - 'Testing squbs Applications': 'testing.md' 22 | - 'Clustering squbs Services using ZooKeeper': 'zkcluster.md' 23 | - 'Blocking Dispatcher': 'blocking-dispatcher.md' 24 | - 'Message Guidelines': 'messages.md' 25 | - 'Actor Monitor': 'monitor.md' 26 | - 'Orchestration DSL': 'orchestration_dsl.md' 27 | - 'Actor Registry': 'registry.md' 28 | - 'Admin Console': 'console.md' 29 | - 'Application Lifecycle Management': 'packaging.md' 30 | - 'Resource Resolution': 'resolver.md' 31 | - 'Perpetual Stream': 'perpetualstream.md' 32 | - 'Customizing Stream Control': 'customizing-stream-control.md' 33 | - 'Pekko Streams GraphStages': 34 | - 'Persistent Buffer': 'persistent-buffer.md' 35 | - 'Circuit Breaker': 'circuitbreaker.md' 36 | - 'Timeout': 'flow-timeout.md' 37 | - 'Deduplicate': 'deduplicate.md' 38 | - 'Retry': 'flow-retry.md' 39 | - 'Materialization Metrics Collector': 'materialization-metrics-collector.md' 40 | - 'Bounded Ordering': 'flow-ordering.md' 41 | - 'Timeout Policy': 'timeoutpolicy.md' 42 | - 'Validation': 'validation.md' 43 | -------------------------------------------------------------------------------- /project/Shared.scala: -------------------------------------------------------------------------------- 1 | object Shared { 2 | 3 | val par = { 4 | val ci = sys.env.getOrElse("CI", default = "false") == "true" 5 | if (ci) 2 6 | else sys.runtime.availableProcessors 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /project/Versions.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | object Versions { 18 | val pekkoV = "1.0.2" 19 | val pekkoHttpV = "1.0.1" 20 | val akkaKryoV = "1.2.0" 21 | val scalaCompatV = "2.11.0" 22 | val scalatestV = "3.2.3" 23 | val scalatestplusV = "3.2.3.0" 24 | val flexmarkV = "0.35.10" 25 | val mockitoV = "2.28.2" 26 | val scalaLoggingV = "3.9.5" 27 | val slf4jV = "1.7.25" 28 | val jacksonV = "2.17.0" 29 | val json4sV = "4.0.7" 30 | val pjfanningAkkaHttpJsonV = "2.4.0" 31 | val metricsV = "4.0.5" 32 | val junitInterfaceV = "0.11" 33 | val junitV = "4.12" 34 | val testngV = "6.14.3" 35 | val accordV = "0.7.4" 36 | val chronicleQueueV = "4.16.5" 37 | val logbackInTestV = "1.2.3" 38 | val curatorV = "4.1.0" 39 | } 40 | -------------------------------------------------------------------------------- /project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=1.9.9 2 | -------------------------------------------------------------------------------- /project/plugins.sbt: -------------------------------------------------------------------------------- 1 | resolvers += "Typesafe Repository" at "https://repo.typesafe.com/typesafe/releases/" 2 | 3 | addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.9.3") 4 | 5 | addSbtPlugin("com.codacy" % "sbt-codacy-coverage" % "3.0.3") 6 | 7 | addSbtPlugin("org.scalastyle" %% "scalastyle-sbt-plugin" % "1.0.0") 8 | 9 | addSbtPlugin("io.spray" % "sbt-boilerplate" % "0.6.1") 10 | 11 | addSbtPlugin("com.github.gseitz" % "sbt-release" % "1.0.11") 12 | 13 | addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.12") 14 | 15 | addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.1.2") 16 | 17 | addSbtPlugin("io.spray" % "sbt-revolver" % "0.9.1") 18 | 19 | //addSbtPlugin("de.johoop" % "sbt-testng-plugin" % "3.1.1") 20 | 21 | addSbtPlugin("com.timushev.sbt" % "sbt-updates" % "0.4.2") 22 | -------------------------------------------------------------------------------- /publish.sbt: -------------------------------------------------------------------------------- 1 | ThisBuild / organization := "org.squbs" 2 | ThisBuild / organizationName := "squbs.org" 3 | ThisBuild / organizationHomepage := Some(url("https://github.com/paypal/squbs")) 4 | 5 | ThisBuild / pomIncludeRepository := { _ => false } 6 | 7 | ThisBuild / publishTo := { 8 | val nexus = "https://oss.sonatype.org/" 9 | if (version.value.trim.endsWith("SNAPSHOT")) 10 | Some("snapshots" at nexus + "content/repositories/snapshots") 11 | else 12 | Some("releases" at nexus + "service/local/staging/deploy/maven2") 13 | } 14 | 15 | ThisBuild / publishMavenStyle := true 16 | 17 | Test / publishArtifact := false -------------------------------------------------------------------------------- /sonatype_credentials.asc: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP MESSAGE----- 2 | 3 | hQGMA0dC26Tm+AF1AQwAgKW6HedeW1CbDAiZ69aHgaTboga2nYkYSn0mhzUm+asJ 4 | ZgKhNUbzye5UwBU140R8DQjiV2n0t8KNyBlZRcqEHhSv4oCwbfDDyn3GyhMDf7fb 5 | yQTPCc/AM8IWmnsiQVtDkBLp2ie7aCSLqVIgLa4Cg1FsYI7ckBaLaoyYUAiEGqJF 6 | 3aXiarpZfrJ9PXw7Vh3NBdmroLhGrH19yxlNVuCu5ObVeJL+J40CZqaclTwxlugX 7 | eRmggVqt72I/hRx7Tss32Cdr9vuluH3aZHNmBmRmd6tddQVeDmEpbtW3sRKru5/9 8 | tb1d7t7GsS+aAEkuPsK8jT4dFdp1//Tz22Bu6rWaaTTq2FdWDUCP7sZS1Y68TWMk 9 | nPeUjLT3maWzMWkRx1i2dUUUPaWTm+hSfhKHMe3Mn6N414l3J0GTdSN5wtwOD7NH 10 | f3pUJ0/SB36sfhSr8uJG6isx1z1hO789PMKj+xgW2wbzXjMwcrtNPHjX59n3saRv 11 | +DhDj28LC1PsMmLmCqGt0ukB7IS8fYaKpLm3wvQf/VsKXxsxwMYlDQtjOF0zN1zq 12 | vCOgGPnhOlDg1Zu7cpclDChn1ugfbHC6sSR6lS/oakvTW6taqEep/7nd9Euuf6id 13 | W1GcY9R7ytES6+jVGgBhf8IAqWbIjkU9EoVCLTja6xB0oJEMJGd/SCvJJlT+0vIz 14 | Yu1j3+gYEB5aFVZVYkb3HtRnkc2Cbg2htpX3H+7HA+Cr8M5X+F+VtgBhHPIxax5A 15 | bZh0FoAvFRYXUxdu6QC82q7IYDA/8QSjuHNAME6JPliEqbZrdVHXTCRbe/4YYiBn 16 | gvZZG7+IPdUpxX8xl4NIrxeaF7vzvIjyFI8jRbvWeWzy3TRHMrEnWwhebNsLUtBj 17 | H++WJ97Kxs/cDHYGOoADhipRNgDdW8a+PxXFWXV2Bo3yP2m/jcilkQyNOo24/6Zw 18 | DnU8ZK48iCcHUtzZcxQ0aWlvEmFhW532AzU+PDnQTicVeBKrLExVYfR3GM0sJOi1 19 | VNgvlN4TnSr3yErB6kNACmu7y1tJP42HvtwRLj8C4kS8RfBmKXcuU/m0o6VpDes1 20 | PYOsEAWFbmHSnQOnX6XL9BIY6ec2y56Dyjba2w5lKMM6/2Mg+MAB4RZ9TOJpnPYR 21 | bTh5Na5cAhxO5lrvt713mZ+5hEZIOHhIpONXXwKAnb4WsrrYpbW6hl7JUaHS+GoI 22 | 8HEYhmBmVyCe09cLzxgUXORDDLmj9eHMsmRGtnXW2dtGLpCYWDF84VkNMXWYAVtg 23 | d9/OesspDOVLTeo+u8rZ2/gBNRMSSXXRnBzM1DtuJoo010VWUdD2WNhUpyU7xjkC 24 | P6nM516GfBRukY65/WjWNdlY6A== 25 | =UUTb 26 | -----END PGP MESSAGE----- 27 | -------------------------------------------------------------------------------- /squbs-actormonitor/build.sbt: -------------------------------------------------------------------------------- 1 | import Versions._ 2 | 3 | name := "squbs-actormonitor" 4 | 5 | Test / javaOptions += "-Xmx512m" 6 | 7 | libraryDependencies ++= Seq( 8 | "org.scala-lang" % "scala-reflect" % scalaVersion.value, 9 | "org.scalatest" %% "scalatest" % scalatestV % Test, 10 | "org.apache.pekko" %% "pekko-actor" % pekkoV, 11 | "org.apache.pekko" %% "pekko-testkit" % pekkoV % Test, 12 | "com.typesafe.scala-logging" %% "scala-logging" % scalaLoggingV, 13 | "com.vladsch.flexmark" % "flexmark-all" % flexmarkV % Test, 14 | "ch.qos.logback" % "logback-classic" % logbackInTestV % Test 15 | ) 16 | 17 | updateOptions := updateOptions.value.withCachedResolution(true) 18 | 19 | Test / testOptions += Tests.Argument(TestFrameworks.ScalaTest, "-h", "report/unicomplex") 20 | -------------------------------------------------------------------------------- /squbs-actormonitor/src/main/resources/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.ActorMonitorCube 2 | cube-version = "0.6.0" 3 | squbs-extensions = [ 4 | { 5 | class-name = org.squbs.actormonitor.ActorMonitorInit 6 | sequence = 1001 7 | } 8 | ] 9 | 10 | -------------------------------------------------------------------------------- /squbs-actormonitor/src/main/resources/build.properties: -------------------------------------------------------------------------------- 1 | custom=true 2 | -------------------------------------------------------------------------------- /squbs-actormonitor/src/main/resources/reference.conf: -------------------------------------------------------------------------------- 1 | squbs-actormonitor = { 2 | maxActorCount = 500 3 | maxChildrenDisplay = 20 4 | } 5 | -------------------------------------------------------------------------------- /squbs-actormonitor/src/main/scala/org/squbs/actormonitor/ActorMonitorInit.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.actormonitor 18 | 19 | import org.apache.pekko.actor._ 20 | import com.typesafe.scalalogging.LazyLogging 21 | import org.squbs.lifecycle.ExtensionLifecycle 22 | 23 | 24 | private class ActorMonitorInit extends ExtensionLifecycle with LazyLogging { 25 | 26 | override def postInit(): Unit = { 27 | logger.info(s"postInit ${this.getClass}") 28 | 29 | import boot._ 30 | implicit val system = actorSystem 31 | 32 | val monitorConfig = config.getConfig("squbs-actormonitor") 33 | 34 | import monitorConfig._ 35 | system.actorOf(Props(classOf[ActorMonitor], 36 | ActorMonitorConfig(getInt("maxActorCount"), getInt("maxChildrenDisplay"))), "squbs-actormonitor") 37 | } 38 | } 39 | 40 | 41 | -------------------------------------------------------------------------------- /squbs-actormonitor/src/test/resources/README: -------------------------------------------------------------------------------- 1 | Test resources shall be in this directory. 2 | -------------------------------------------------------------------------------- /squbs-actormonitor/src/test/resources/classpaths/ActorMonitorCube/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.ActorMonitorCube 2 | cube-version = "0.6.0" 3 | squbs-extensions = [ 4 | { 5 | class-name = org.squbs.actormonitor.ActorMonitorInit 6 | sequence = 1001 7 | } 8 | ] 9 | -------------------------------------------------------------------------------- /squbs-actormonitor/src/test/resources/classpaths/TestCube/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.actormonitor.TestCube 2 | cube-version = "0.0.6" 3 | squbs-actors = [ 4 | { 5 | class-name = org.squbs.actormonitor.testcube.TestActor 6 | name = TestActor 7 | }, 8 | { 9 | class-name = org.squbs.actormonitor.testcube.TestActorWithRoute 10 | name = TestActorWithRoute 11 | with-router = true 12 | }, 13 | { 14 | class-name = org.squbs.actormonitor.testcube.TestActor1 15 | name = TestActor1 16 | 17 | } 18 | 19 | ] -------------------------------------------------------------------------------- /squbs-actormonitor/src/test/resources/reference.conf: -------------------------------------------------------------------------------- 1 | blocking-dispatcher { 2 | # Dispatcher is the name of the event-based dispatcher 3 | type = Dispatcher 4 | # What kind of ExecutionService to use 5 | executor = "fork-join-executor" 6 | # Configuration for the fork join pool 7 | fork-join-executor { 8 | # Min number of threads to cap factor-based parallelism number to 9 | parallelism-min = 2 10 | # Parallelism (threads) ... ceil(available processors * factor) 11 | parallelism-factor = 3.0 12 | # Max number of threads to cap factor-based parallelism number to 13 | parallelism-max = 24 14 | } 15 | # Throughput defines the maximum number of messages to be 16 | # processed per actor before the thread jumps to the next actor. 17 | # Set to 1 for as fair as possible. 18 | throughput = 2 19 | } 20 | 21 | pekko.actor.deployment { 22 | /TestCube/TestActorWithRoute { 23 | router = round-robin-pool 24 | resizer { 25 | lower-bound = 1 26 | upper-bound = 10 27 | } 28 | } 29 | 30 | # Sale is used with router. Dispatcher configuration for sale actors themselves are at /ItemCube/Sale/* 31 | "/TestCube/TestActorWithRoute/*" { 32 | dispatcher = blocking-dispatcher 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /squbs-actormonitor/src/test/scala/org/squbs/actormonitor/TestCube/TestCube.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.actormonitor.testcube 18 | 19 | import org.apache.pekko.actor.Actor 20 | 21 | 22 | class TestActor extends Actor { 23 | def receive = { 24 | case x => sender() ! x 25 | } 26 | } 27 | 28 | class TestActorWithRoute extends Actor { 29 | def receive = { 30 | case x => sender() ! x 31 | } 32 | } 33 | 34 | class TestActor1 extends Actor { 35 | def receive = { 36 | case x =>context.stop(self) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /squbs-actorregistry/build.sbt: -------------------------------------------------------------------------------- 1 | import Versions._ 2 | 3 | name := "squbs-actorregistry" 4 | 5 | Test / javaOptions += "-Xmx512m" 6 | 7 | libraryDependencies ++= Seq( 8 | "org.scala-lang" % "scala-reflect" % scalaVersion.value, 9 | "org.scalatest" %% "scalatest" % scalatestV % Test, 10 | "com.typesafe.scala-logging" %% "scala-logging" % scalaLoggingV, 11 | "org.apache.pekko" %% "pekko-actor" % pekkoV, 12 | "org.apache.pekko" %% "pekko-testkit" % pekkoV % Test, 13 | "com.vladsch.flexmark" % "flexmark-all" % flexmarkV % Test, 14 | "ch.qos.logback" % "logback-classic" % logbackInTestV % Test, 15 | "junit" % "junit" % junitV % Test, 16 | "com.novocode" % "junit-interface" % junitInterfaceV % Test 17 | ) 18 | 19 | Test / testOptions ++= Seq( 20 | Tests.Argument(TestFrameworks.JUnit, "-v", "-a"), 21 | Tests.Argument(TestFrameworks.ScalaTest, "-h", "report/unicomplex") 22 | ) 23 | 24 | updateOptions := updateOptions.value.withCachedResolution(true) 25 | 26 | javacOptions ++= Seq("-Xlint:unchecked") 27 | 28 | scalacOptions ++= Seq("-feature") -------------------------------------------------------------------------------- /squbs-actorregistry/src/main/resources/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.ActorRegistryCube 2 | cube-version = "0.6.0" 3 | squbs-extensions = [ 4 | { 5 | class-name = org.squbs.actorregistry.ActorRegistryInit 6 | sequence = 1000 7 | } 8 | ] 9 | 10 | squbs-actors = [ 11 | { 12 | class-name = org.squbs.actorregistry.ActorRegistry 13 | name = ActorRegistry 14 | init-required = true 15 | } 16 | ] 17 | -------------------------------------------------------------------------------- /squbs-actorregistry/src/main/resources/build.properties: -------------------------------------------------------------------------------- 1 | custom=true 2 | -------------------------------------------------------------------------------- /squbs-actorregistry/src/main/resources/reference.conf: -------------------------------------------------------------------------------- 1 | squbs-actorregistry = { 2 | timeout = 1000 3 | } -------------------------------------------------------------------------------- /squbs-actorregistry/src/main/scala/org/squbs/actorregistry/ActorRegistryBean.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.actorregistry 18 | 19 | import java.lang.management.ManagementFactory 20 | import javax.management.MXBean 21 | 22 | import org.apache.pekko.actor.{ActorContext, ActorRef} 23 | import org.squbs.unicomplex.JMX._ 24 | 25 | 26 | 27 | private[actorregistry] object ActorRegistryBean { 28 | val Pattern = "org.squbs.unicomplex:type=ActorRegistry,name=" 29 | val Total = Pattern + "*" 30 | 31 | def objName(actor: ActorRef) (implicit context: ActorContext)= prefix + Pattern + actor.path.toString.split(s"${actor.path.root}user/").mkString("") 32 | def totalBeans(implicit context: ActorContext) = ManagementFactory.getPlatformMBeanServer.queryNames(prefix + Total, null) 33 | } 34 | 35 | @MXBean 36 | private[actorregistry] trait ActorRegistryMXBean { 37 | def getPath : String 38 | def getActorMessageTypeList: java.util.List[String] 39 | } 40 | 41 | @MXBean 42 | private[actorregistry] trait ActorRegistryConfigMXBean { 43 | def getCount : Int 44 | def getTimeout: Int 45 | } 46 | 47 | private[actorregistry] class ActorRegistryConfigBean(timeout: Int, implicit val context: ActorContext) extends ActorRegistryConfigMXBean { 48 | def getCount : Int = ActorRegistryBean.totalBeans.size 49 | def getTimeout: Int = timeout 50 | } 51 | -------------------------------------------------------------------------------- /squbs-actorregistry/src/test/resources/classpaths/ActorRegistryCube/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.ActorRegistryCube 2 | cube-version = "0.6.0" 3 | squbs-extensions = [ 4 | { 5 | class-name = org.squbs.actorregistry.ActorRegistryInit 6 | sequence = 1000 7 | } 8 | ] 9 | 10 | squbs-actors = [ 11 | { 12 | class-name = org.squbs.actorregistry.ActorRegistry 13 | name = ActorRegistry 14 | init-required = true 15 | } 16 | ] 17 | -------------------------------------------------------------------------------- /squbs-actorregistry/src/test/resources/classpaths/NoWellKnownActorsCube/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.ActorRegistryCube 2 | cube-version = "0.6.0" 3 | squbs-extensions = [ 4 | { 5 | class-name = org.squbs.actorregistry.ActorRegistryInit 6 | sequence = 1000 7 | } 8 | ] 9 | 10 | squbs-actors = [ 11 | { 12 | class-name = org.squbs.actorregistry.ActorRegistry 13 | name = ActorRegistry 14 | init-required = true 15 | } 16 | ] 17 | -------------------------------------------------------------------------------- /squbs-actorregistry/src/test/resources/classpaths/TestCube/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.TestCube 2 | cube-version = "0.0.5" 3 | squbs-actors = [ 4 | { 5 | class-name = org.squbs.actorregistry.testcube.TestActor 6 | name = TestActor 7 | message-class = [ 8 | { 9 | request = org.squbs.actorregistry.testcube.TestRequest 10 | response= org.squbs.actorregistry.testcube.TestResponse 11 | } 12 | ] 13 | }, 14 | { 15 | class-name = org.squbs.actorregistry.testcube.TestActor1 16 | name = TestActor1 17 | } 18 | ] -------------------------------------------------------------------------------- /squbs-actorregistry/src/test/resources/classpaths/TestCubeWithRouter/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.TestCube 2 | cube-version = "0.0.5" 3 | squbs-actors = [ 4 | { 5 | class-name = org.squbs.actorregistry.testcube.TestActor 6 | name = TestActor 7 | with-router = true 8 | message-class = [ 9 | { 10 | request = org.squbs.actorregistry.testcube.TestRequest 11 | response= org.squbs.actorregistry.testcube.TestResponse 12 | } 13 | ] 14 | }, 15 | { 16 | class-name = org.squbs.actorregistry.testcube.TestActor1 17 | name = TestActor1 18 | } 19 | ] -------------------------------------------------------------------------------- /squbs-actorregistry/src/test/scala/org/squbs/actorregistry/testcube/TestCube.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.squbs.actorregistry.testcube 17 | 18 | import org.apache.pekko.actor.Actor 19 | 20 | case class TestRequest(msg: String) 21 | case class TestRequest1(msg: String) 22 | case class TestResponse(msg: String) 23 | 24 | 25 | class TestActor extends Actor { 26 | def receive = { 27 | case TestRequest(msg) => 28 | sender() ! TestResponse(msg) 29 | case TestRequest => 30 | sender() ! TestResponse 31 | } 32 | } 33 | 34 | class TestActor1 extends Actor { 35 | def receive = { 36 | case TestRequest1(msg) => 37 | sender() ! TestResponse(msg) 38 | case TestRequest1 => 39 | sender() ! TestResponse 40 | } 41 | } 42 | 43 | -------------------------------------------------------------------------------- /squbs-admin/build.sbt: -------------------------------------------------------------------------------- 1 | import Versions._ 2 | 3 | name := "squbs-admin" 4 | 5 | Revolver.settings 6 | 7 | Test / javaOptions += "-Xmx512m" 8 | 9 | libraryDependencies ++= Seq( 10 | "org.scala-lang" % "scala-reflect" % scalaVersion.value, 11 | "org.scalatest" %% "scalatest" % scalatestV % Test, 12 | "org.apache.pekko" %% "pekko-actor" % pekkoV, 13 | "org.apache.pekko" %% "pekko-http" % pekkoHttpV, 14 | "org.apache.pekko" %% "pekko-http-testkit" % pekkoHttpV % Test, 15 | "com.typesafe.scala-logging" %% "scala-logging" % scalaLoggingV, 16 | "org.apache.pekko" %% "pekko-testkit" % pekkoV % Test, 17 | "com.vladsch.flexmark" % "flexmark-all" % flexmarkV % Test, 18 | "ch.qos.logback" % "logback-classic" % logbackInTestV % Test, 19 | "org.json4s" %% "json4s-jackson" % json4sV 20 | ) 21 | 22 | Test / testOptions += Tests.Argument(TestFrameworks.ScalaTest, "-h", "report/squbs-unicomplex") 23 | 24 | updateOptions := updateOptions.value.withCachedResolution(true) 25 | 26 | Compile / run / mainClass := Some("org.squbs.unicomplex.Bootstrap") -------------------------------------------------------------------------------- /squbs-admin/src/main/resources/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.admin 2 | 3 | cube-version = "0.7.1" 4 | squbs-services = [ 5 | { 6 | class-name = org.squbs.admin.AdminSvc 7 | listeners = [ admin-listener ] 8 | web-context = adm 9 | defaultPipeline = off 10 | } 11 | ] 12 | -------------------------------------------------------------------------------- /squbs-ext/build.sbt: -------------------------------------------------------------------------------- 1 | import Versions._ 2 | 3 | name := "squbs-ext" 4 | 5 | Revolver.settings 6 | 7 | Test / javaOptions += "-Xmx512m" 8 | 9 | Test / testOptions ++= Seq( 10 | Tests.Argument(TestFrameworks.JUnit, "-v", "-a") 11 | ) 12 | 13 | libraryDependencies ++= Seq( 14 | "org.scala-lang.modules" %% "scala-collection-compat" % scalaCompatV, 15 | "io.dropwizard.metrics" % "metrics-core" % metricsV, 16 | "io.dropwizard.metrics" % "metrics-jmx" % metricsV, 17 | "org.scala-lang.modules" %% "scala-java8-compat" % "1.0.2", 18 | "org.apache.pekko" %% "pekko-stream" % pekkoV % Optional, 19 | "org.apache.pekko" %% "pekko-http-core" % pekkoHttpV % Optional, 20 | "org.apache.pekko" %% "pekko-http" % pekkoHttpV % Optional, 21 | "com.github.pjfanning" %% "pekko-http-json4s" % pjfanningAkkaHttpJsonV % Optional, 22 | "com.github.pjfanning" %% "pekko-http-jackson" % pjfanningAkkaHttpJsonV % Optional, 23 | "org.json4s" %% "json4s-native" % json4sV % Optional, 24 | "org.json4s" %% "json4s-jackson" % json4sV % Optional, 25 | "com.fasterxml.jackson.core" % "jackson-core" % jacksonV % Optional, 26 | "com.fasterxml.jackson.core" % "jackson-databind" % jacksonV % Optional, 27 | "com.fasterxml.jackson.module" %% "jackson-module-scala" % jacksonV % Optional, 28 | "com.fasterxml.jackson.module" % "jackson-module-parameter-names" % jacksonV % Optional, 29 | "org.apache.pekko" %% "pekko-testkit" % pekkoV % Test, 30 | "org.apache.pekko" %% "pekko-stream-testkit" % pekkoV % Test, 31 | "junit" % "junit" % junitV % Test, 32 | "org.testng" % "testng" % testngV % Test, 33 | "com.novocode" % "junit-interface" % junitInterfaceV % Test, 34 | "org.scalatest" %% "scalatest" % scalatestV % Test, 35 | "com.vladsch.flexmark" % "flexmark-all" % flexmarkV % Test 36 | ) 37 | -------------------------------------------------------------------------------- /squbs-ext/src/main/java/org/squbs/streams/circuitbreaker/impl/AbstractAtomicCircuitBreakerLogic.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /** 18 | * Copyright (C) 2009-2016 Lightbend Inc. 19 | */ 20 | package org.squbs.streams.circuitbreaker.impl; 21 | 22 | import org.apache.pekko.util.Unsafe; 23 | 24 | class AbstractAtomicCircuitBreakerLogic { 25 | protected final static long stateOffset; 26 | protected final static long resetTimeoutOffset; 27 | 28 | static { 29 | try { 30 | stateOffset = Unsafe.instance.objectFieldOffset(AtomicCircuitBreakerState.class.getDeclaredField("_currentStateDoNotCallMeDirectly")); 31 | resetTimeoutOffset = Unsafe.instance.objectFieldOffset(AtomicCircuitBreakerState.class.getDeclaredField("_currentResetTimeoutDoNotCallMeDirectly")); 32 | } catch(Throwable t){ 33 | throw new ExceptionInInitializerError(t); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /squbs-ext/src/main/resources/reference.conf: -------------------------------------------------------------------------------- 1 | squbs.circuit-breaker { 2 | max-failures = 5 3 | call-timeout = 1 second 4 | reset-timeout = 5 seconds 5 | max-reset-timeout = 36500 days 6 | exponential-backoff-factor = 1.0 7 | } -------------------------------------------------------------------------------- /squbs-ext/src/main/scala/org/squbs/metrics/MetricsExtension.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.metrics 18 | 19 | import org.apache.pekko.actor._ 20 | import com.codahale.metrics.MetricRegistry 21 | import com.codahale.metrics.jmx.JmxReporter 22 | 23 | object MetricsExtension extends ExtensionId[MetricsExtensionImpl] with ExtensionIdProvider { 24 | 25 | override def lookup: MetricsExtension.type = MetricsExtension 26 | 27 | override def createExtension(system: ExtendedActorSystem) = new MetricsExtensionImpl(system) 28 | 29 | /** 30 | * Java API: retrieve the Count extension for the given system. 31 | */ 32 | override def get(system: ActorSystem): MetricsExtensionImpl = super.get(system) 33 | } 34 | 35 | class MetricsExtensionImpl(system: ActorSystem) extends Extension { 36 | val Domain = s"org.squbs.metrics.${system.name}" 37 | val metrics = new MetricRegistry() 38 | val jmxReporter = JmxReporter.forRegistry(metrics).inDomain(Domain).build() 39 | jmxReporter.start() 40 | } 41 | -------------------------------------------------------------------------------- /squbs-ext/src/main/scala/org/squbs/streams/UniqueId.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.squbs.streams 17 | 18 | 19 | object UniqueId { 20 | 21 | /** 22 | * A message type can implement this interface to map itself to a unique id. 23 | * 24 | * If a message cannot implement this interface, it is also possible to wrap the message in [[Envelope]]. 25 | */ 26 | trait Provider { 27 | def uniqueId: Any 28 | } 29 | 30 | /** 31 | * If a message cannot implement [[Provider]], it can also be wrapped with this envelope to provide a 32 | * unique id along with it. 33 | */ 34 | final case class Envelope(message: Any, id: Any) extends Provider { 35 | override def uniqueId: Any = id 36 | } 37 | } -------------------------------------------------------------------------------- /squbs-ext/src/test/java/org/squbs/marshallers/json/PageData.java: -------------------------------------------------------------------------------- 1 | package org.squbs.marshallers.json; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | import java.util.List; 6 | 7 | public class PageData extends PagedResult { 8 | 9 | public PageData(Integer startPage, List pages) { 10 | setStartPage(startPage); 11 | setPages(pages); 12 | } 13 | 14 | public PageData() { 15 | } 16 | 17 | @Override 18 | @JsonProperty("data_pages") 19 | public List getPages() { 20 | return pages; 21 | } 22 | 23 | @Override 24 | public boolean equals(Object obj) { 25 | if (obj instanceof PageData) { 26 | PageData p = (PageData) obj; 27 | if (pages.equals(p.getPages()) && getStartPage().equals(p.getStartPage())) { 28 | return true; 29 | } 30 | } 31 | return false; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /squbs-ext/src/test/java/org/squbs/marshallers/json/PagedResult.java: -------------------------------------------------------------------------------- 1 | package org.squbs.marshallers.json; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | 5 | import java.util.List; 6 | 7 | public abstract class PagedResult { 8 | 9 | private Integer startPage; 10 | 11 | protected List pages; 12 | 13 | @JsonProperty("start_page") 14 | public Integer getStartPage() { 15 | return startPage; 16 | } 17 | 18 | public void setStartPage(Integer startPage) { 19 | this.startPage = startPage; 20 | } 21 | 22 | public abstract List getPages(); 23 | 24 | public final void setPages(List pages) { 25 | this.pages = pages; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /squbs-ext/src/test/java/org/squbs/marshallers/json/XLangJsonSpecHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.squbs.marshallers.json; 17 | 18 | /** 19 | * Helper for calling Java APIs that need to be validated in Scala. 20 | */ 21 | public class XLangJsonSpecHelper { 22 | 23 | public static void registerNativeSerializer() { 24 | XLangJsonSupport.register(EmployeeBean.class, XLangJsonSupport.nativeSerialization()); 25 | } 26 | 27 | public static void registerJacksonSerializer() { 28 | XLangJsonSupport.register(EmployeeBean.class, XLangJsonSupport.jacksonSerialization()); 29 | } 30 | 31 | public static void addDefaultSerializer() { 32 | XLangJsonSupport.addDefaultSerializers(EmployeeBeanSerializer.getInstance()); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /squbs-ext/src/test/java/org/squbs/resolver/DummyLocalhostJavaResolver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.squbs.resolver; 17 | 18 | import org.squbs.env.DEV; 19 | import org.squbs.env.Default; 20 | import org.squbs.env.Environment; 21 | 22 | import java.net.URI; 23 | import java.util.Optional; 24 | 25 | public class DummyLocalhostJavaResolver extends AbstractResolver { 26 | 27 | @Override 28 | public String name() { 29 | return "DummyLocalhostJavaResolver"; 30 | } 31 | 32 | @Override 33 | public Optional resolve(String svcName, Environment env) { 34 | if (Default.value().equals(env) || DEV.value().equals(env)) { 35 | return Optional.of(URI.create("http://localhost:8080")); 36 | } else { 37 | return Optional.empty(); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /squbs-ext/src/test/scala/org/squbs/env/DummyEnvironmentResolver.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.env 18 | 19 | object DummyProdEnvironmentResolver extends EnvironmentResolver { 20 | override def resolve: Environment = PROD 21 | override def name: String = "DummyProdEnvironmentResolver" 22 | 23 | /** 24 | * Java API for obtaining the instance. 25 | * @return This instance 26 | */ 27 | def get: EnvironmentResolver = this 28 | } 29 | 30 | object DummyQAEnvironmentResolver extends EnvironmentResolver { 31 | override def resolve: Environment = QA 32 | override def name: String = "DummyQAEnvironmentResolver" 33 | 34 | /** 35 | * Java API for obtaining the instance. 36 | * @return This instance 37 | */ 38 | def get: EnvironmentResolver = this 39 | } 40 | 41 | object DummyNotResolveEnvironmentResolver extends EnvironmentResolver { 42 | override def resolve: Environment = Default 43 | override def name: String = "DummyNotResolveEnvironmentResolver" 44 | 45 | /** 46 | * Java API for obtaining the instance. 47 | * @return This instance 48 | */ 49 | def get: EnvironmentResolver = this 50 | } 51 | -------------------------------------------------------------------------------- /squbs-ext/src/test/scala/org/squbs/env/EnvTestHelper.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.squbs.env 17 | 18 | import org.apache.pekko.actor.ActorSystem 19 | 20 | /** 21 | * Test helper for Java tests. 22 | */ 23 | object EnvTestHelper { 24 | def clearRegistries(system: ActorSystem): Unit = { 25 | EnvironmentResolverRegistry(system).environmentResolvers = List.empty[EnvironmentResolver] 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /squbs-ext/src/test/scala/org/squbs/resolver/DummyEndpointResolver.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.resolver 18 | 19 | import java.net.URI 20 | 21 | import org.apache.pekko.actor.ActorSystem 22 | import org.squbs.env.{DEV, Default, Environment} 23 | 24 | class DummyServiceResolver(implicit system: ActorSystem) extends Resolver[URI] { 25 | 26 | override def resolve(svcName: String, env: Environment): Option[URI] = { 27 | if (svcName == name) Some(URI.create("http://www.google.com")) 28 | else None 29 | } 30 | 31 | override def name: String = "DummyService" 32 | } 33 | 34 | class DummyLocalhostResolver(implicit system: ActorSystem) extends Resolver[URI] { 35 | 36 | override def resolve(svcName: String, env: Environment = Default): Option[URI] = { 37 | require(svcName != null, "Service name cannot be null") 38 | require(svcName.length > 0, "Service name must not be blank") 39 | 40 | env match { 41 | case Default | DEV => Some(URI.create("http://localhost:8080")) 42 | case _ => throw new RuntimeException("DummyLocalhostResolver cannot support " + env + " environment") 43 | } 44 | } 45 | 46 | override def name: String = "DummyLocalhostResolver" 47 | } 48 | -------------------------------------------------------------------------------- /squbs-ext/src/test/scala/org/squbs/resolver/ResolverTestHelper.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.squbs.resolver 17 | 18 | import org.apache.pekko.actor.ActorSystem 19 | 20 | /** 21 | * Test helper for Java tests. 22 | */ 23 | object ResolverTestHelper { 24 | 25 | def clearRegistries(system: ActorSystem): Unit = 26 | ResolverRegistry(system).resolvers = List.empty[(Class[_], Resolver[_])] 27 | } 28 | -------------------------------------------------------------------------------- /squbs-httpclient/build.sbt: -------------------------------------------------------------------------------- 1 | import Versions._ 2 | 3 | name := "squbs-httpclient" 4 | 5 | Test / javaOptions += "-Xmx512m" 6 | 7 | libraryDependencies ++= Seq( 8 | "org.apache.pekko" %% "pekko-actor" % pekkoV, 9 | "org.apache.pekko" %% "pekko-slf4j" % pekkoV, 10 | "org.apache.pekko" %% "pekko-stream" % pekkoV, 11 | "org.apache.pekko" %% "pekko-http-core" % pekkoHttpV , 12 | "com.typesafe.scala-logging" %% "scala-logging" % scalaLoggingV, 13 | "org.scalatest" %% "scalatest" % scalatestV % Test, 14 | "org.apache.pekko" %% "pekko-testkit" % pekkoV % Test, 15 | "com.github.pjfanning" %% "pekko-http-json4s" % pjfanningAkkaHttpJsonV % Test, 16 | "com.github.pjfanning" %% "pekko-http-jackson" % pjfanningAkkaHttpJsonV % Test, 17 | "org.json4s" %% "json4s-jackson" % json4sV % Test, 18 | "com.fasterxml.jackson.module" %% "jackson-module-scala" % jacksonV % Test, 19 | "junit" % "junit" % junitV % Test, 20 | "com.novocode" % "junit-interface" % junitInterfaceV % Test, 21 | "com.vladsch.flexmark" % "flexmark-all" % flexmarkV % Test, 22 | "ch.qos.logback" % "logback-classic" % logbackInTestV % Test, 23 | "org.littleshoot" % "littleproxy" % "1.1.2" % Test 24 | ) 25 | 26 | javacOptions += "-parameters" 27 | 28 | Test / testOptions ++= Seq( 29 | Tests.Argument(TestFrameworks.ScalaTest, "-h", "report/squbs-httpclient"), 30 | Tests.Argument(TestFrameworks.JUnit, "-v", "-a") 31 | ) 32 | 33 | updateOptions := updateOptions.value.withCachedResolution(true) 34 | -------------------------------------------------------------------------------- /squbs-httpclient/src/main/scala/org/squbs/httpclient/DefaultHttpEndpointResolver.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.httpclient 18 | 19 | import org.apache.pekko.http.scaladsl.model.Uri 20 | import com.typesafe.scalalogging.LazyLogging 21 | import org.squbs.env.Environment 22 | import org.squbs.resolver.Resolver 23 | 24 | import scala.util.Try 25 | 26 | /** 27 | * A [[Resolver]] that resolves a valid HTTP [[Uri]] [[String]] to an [[HttpEndpoint]]. 28 | */ 29 | class DefaultHttpEndpointResolver extends Resolver[HttpEndpoint] with LazyLogging { 30 | 31 | override def name: String = getClass.getName 32 | 33 | override def resolve(name: String, env: Environment): Option[HttpEndpoint] = { 34 | Try(Uri(name)).toOption match { 35 | case Some(uri) if uri.scheme == "http" || uri.scheme == "https" => Some(HttpEndpoint(uri)) 36 | case _ => 37 | logger.debug(s"Could not resolve to an HttpEndpoint. Invalid http URI: $name") 38 | None 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /squbs-httpclient/src/main/scala/org/squbs/httpclient/HttpClientException.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.httpclient 18 | 19 | import org.squbs.env._ 20 | 21 | class HttpClientException(message: String) extends RuntimeException(message) with Serializable 22 | 23 | case class HttpClientMarkDownException(svcName: String, env: Environment = Default) 24 | extends HttpClientException(s"HttpClient:($svcName,$env) has been marked down!") 25 | 26 | case class HttpClientExistException(svcName: String, env: Environment = Default) 27 | extends HttpClientException(s"HttpClient:($svcName,$env) has been registered!") 28 | 29 | case class HttpClientNotExistException(svcName: String, env: Environment = Default) 30 | extends HttpClientException(s"HttpClient:($svcName,$env) has not been registered!") 31 | 32 | case class HttpClientEndpointNotExistException(svcName: String, env: Environment = Default) 33 | extends HttpClientException(s"HttpClient:($svcName,$env) endpoint cannot be resolved!") 34 | -------------------------------------------------------------------------------- /squbs-httpclient/src/main/scala/org/squbs/httpclient/SSLEngineProvider.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.squbs.httpclient 17 | 18 | import javax.net.ssl.{SSLContext, SSLEngine} 19 | 20 | trait SSLEngineProvider { 21 | def createSSLEngine(sslContext: SSLContext, hostname: String, port: Int): SSLEngine 22 | def createSSLEngine(hostname: String, port: Int): SSLEngine = createSSLEngine(SSLContext.getDefault, hostname, port) 23 | } 24 | -------------------------------------------------------------------------------- /squbs-httpclient/src/main/scala/org/squbs/httpclient/pipeline/HttpClientPipeline.scala.waiting: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.httpclient.pipeline 18 | 19 | import java.util.concurrent.TimeUnit 20 | import javax.net.ssl.SSLContext 21 | 22 | import org.apache.pekko.actor._ 23 | import org.apache.pekko.util.Timeout 24 | import com.typesafe.scalalogging.LazyLogging 25 | //import org.squbs.httpclient.{Status, _} 26 | import org.squbs.endpoint.Endpoint 27 | import org.squbs.pipeline._ 28 | import spray.can.Http 29 | import spray.http.{HttpRequest, HttpResponse} 30 | import spray.httpx.unmarshalling._ 31 | import spray.httpx.{PipelineException, UnsuccessfulResponseException} 32 | import spray.io.ClientSSLEngineProvider 33 | 34 | import scala.concurrent.Future 35 | import scala.language.implicitConversions 36 | import scala.util.Try 37 | 38 | object HttpClientUnmarshal{ 39 | 40 | implicit class HttpResponseUnmarshal(val response: HttpResponse) extends AnyVal { 41 | 42 | def unmarshalTo[T: FromResponseUnmarshaller]: Try[T] = { 43 | Try{ 44 | if (response.status.isSuccess && response.status.allowsEntity && response.entity.nonEmpty) 45 | response.as[T] match { 46 | case Right(value) ⇒ value 47 | case Left(error) ⇒ 48 | throw new PipelineException(error.toString, cause = new UnsuccessfulResponseException(response)) 49 | } 50 | else throw new UnsuccessfulResponseException(response) 51 | } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /squbs-httpclient/src/test/java/org/squbs/httpclient/JavaEndpointResolver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.squbs.httpclient; 17 | 18 | import org.squbs.resolver.AbstractResolver; 19 | import org.squbs.env.Environment; 20 | 21 | import java.util.Optional; 22 | 23 | public class JavaEndpointResolver extends AbstractResolver { 24 | 25 | private final String dummyServiceEndpoint; 26 | 27 | public JavaEndpointResolver(String dummyServiceEndpoint) { 28 | this.dummyServiceEndpoint = dummyServiceEndpoint; 29 | } 30 | 31 | @Override 32 | public String name() { 33 | return "DummyService"; 34 | } 35 | 36 | @Override 37 | public Optional resolve(String svcName, Environment env) { 38 | if (name().equals(svcName)) { 39 | return Optional.of(HttpEndpoint.create(dummyServiceEndpoint)); 40 | } else { 41 | return Optional.empty(); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /squbs-httpclient/src/test/java/org/squbs/httpclient/JavaEndpointResolver2.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.squbs.httpclient; 17 | 18 | import org.apache.pekko.http.javadsl.model.Uri; 19 | import org.squbs.env.Environment; 20 | import org.squbs.resolver.AbstractResolver; 21 | 22 | import java.util.Optional; 23 | 24 | public class JavaEndpointResolver2 extends AbstractResolver { 25 | 26 | private final String dummyServiceEndpoint; 27 | 28 | public JavaEndpointResolver2(String dummyServiceEndpoint) { 29 | this.dummyServiceEndpoint = dummyServiceEndpoint; 30 | } 31 | 32 | @Override 33 | public String name() { 34 | return "DummyService2"; 35 | } 36 | 37 | @Override 38 | public Optional resolve(String svcName, Environment env) { 39 | if (name().equals(svcName)) { 40 | return Optional.of( 41 | HttpEndpoint.create(Uri.create(dummyServiceEndpoint), Optional.empty(), 42 | Optional.empty(), Optional.empty())); 43 | } else { 44 | return Optional.empty(); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /squbs-httpclient/src/test/resources/ClientFlowHttpsSpec/example.com.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paypal/squbs/2569bf50c7510a4a0817e50978be0826f07b6dcd/squbs-httpclient/src/test/resources/ClientFlowHttpsSpec/example.com.jks -------------------------------------------------------------------------------- /squbs-httpclient/src/test/resources/ClientFlowHttpsSpec/exampletrust.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/paypal/squbs/2569bf50c7510a4a0817e50978be0826f07b6dcd/squbs-httpclient/src/test/resources/ClientFlowHttpsSpec/exampletrust.jks -------------------------------------------------------------------------------- /squbs-httpclient/src/test/resources/application.conf: -------------------------------------------------------------------------------- 1 | pekko { 2 | loglevel = "ERROR" 3 | } -------------------------------------------------------------------------------- /squbs-httpclient/src/test/scala/org/squbs/httpclient/dummy/DummyEndpointResolver.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.squbs.httpclient.dummy 17 | 18 | import org.apache.pekko.actor.ActorSystem 19 | import org.squbs.env.Environment 20 | import org.squbs.httpclient.HttpEndpoint 21 | import org.squbs.resolver.Resolver 22 | 23 | class DummyServiceResolver(dummyServiceEndpoint: String) 24 | (implicit system: ActorSystem) extends Resolver[HttpEndpoint] { 25 | 26 | override def resolve(svcName: String, env: Environment): Option[HttpEndpoint] = { 27 | if (svcName == name) { 28 | Some(HttpEndpoint(dummyServiceEndpoint)) 29 | } else { 30 | None 31 | } 32 | } 33 | 34 | override def name: String = "DummyService" 35 | } 36 | 37 | class NotExistingResolver(implicit system: ActorSystem) extends Resolver[HttpEndpoint] { 38 | 39 | override def resolve(svcName: String, env: Environment): Option[HttpEndpoint] = { 40 | if (svcName == name) { 41 | Some(HttpEndpoint("http://www.notexistingservice.com")) 42 | } else { 43 | None 44 | } 45 | } 46 | 47 | override def name: String = "NotExistingService" 48 | } 49 | -------------------------------------------------------------------------------- /squbs-httpclient/src/test/scala/org/squbs/httpclient/package.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.squbs 17 | 18 | import java.io.InputStream 19 | import java.security.{KeyStore, SecureRandom} 20 | 21 | import javax.net.ssl.{KeyManagerFactory, SSLContext, TrustManagerFactory} 22 | 23 | package object httpclient { 24 | 25 | def sslContext(store: String, pw: String) = { 26 | val password: Array[Char] = pw.toCharArray // do not store passwords in code, read them from somewhere safe! 27 | 28 | val ks: KeyStore = KeyStore.getInstance("JKS") 29 | val keystore: InputStream = getClass.getClassLoader.getResourceAsStream("ClientFlowHttpsSpec/" + store) 30 | 31 | require(keystore != null, "Keystore required!") 32 | ks.load(keystore, password) 33 | 34 | val keyManagerFactory: KeyManagerFactory = KeyManagerFactory.getInstance("SunX509") 35 | keyManagerFactory.init(ks, password) 36 | 37 | val tmf: TrustManagerFactory = TrustManagerFactory.getInstance("SunX509") 38 | tmf.init(ks) 39 | 40 | val sslContext: SSLContext = SSLContext.getInstance("TLS") 41 | sslContext.init(keyManagerFactory.getKeyManagers, tmf.getTrustManagers, new SecureRandom) 42 | sslContext 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /squbs-pattern/build.sbt: -------------------------------------------------------------------------------- 1 | import Versions._ 2 | 3 | name := "squbs-pattern" 4 | 5 | Test / testOptions ++= Seq( 6 | Tests.Argument(TestFrameworks.ScalaTest, "-l", "org.squbs.testkit.tags.SlowTest"), 7 | Tests.Argument(TestFrameworks.JUnit, "-v", "-a") 8 | ) 9 | 10 | Test / javaOptions ++= Seq("-Xmx512m", "-ea") 11 | 12 | libraryDependencies ++= Seq( 13 | "org.scala-lang" % "scala-reflect" % scalaVersion.value, 14 | "org.scala-lang.modules" %% "scala-collection-compat" % scalaCompatV, 15 | "com.typesafe.scala-logging" %% "scala-logging" % scalaLoggingV, 16 | "org.slf4j" % "slf4j-api" % slf4jV, 17 | "net.openhft" % "chronicle-queue" % chronicleQueueV % Optional, 18 | "org.scalatest" %% "scalatest" % scalatestV % Test, 19 | "junit" % "junit" % junitV % Test, 20 | "org.apache.commons" % "commons-math3" % "3.6.1" % Test, 21 | "com.novocode" % "junit-interface" % junitInterfaceV % Test, 22 | "com.wix" %% "accord-core" % accordV % Optional, 23 | "org.json4s" %% "json4s-jackson" % json4sV % Optional, 24 | "com.vladsch.flexmark" % "flexmark-all" % flexmarkV % Test, 25 | "com.fasterxml.jackson.module" %% "jackson-module-scala" % jacksonV % Optional, 26 | "com.fasterxml.jackson.module" % "jackson-module-parameter-names" % jacksonV % Optional, 27 | "ch.qos.logback" % "logback-classic" % logbackInTestV % Test 28 | ) ++ pekkoDependencies 29 | 30 | def pekkoDependencies = Seq( 31 | "org.apache.pekko" %% "pekko-actor" % pekkoV, 32 | "org.apache.pekko" %% "pekko-stream" % pekkoV, 33 | "org.apache.pekko" %% "pekko-testkit" % pekkoV % Test, 34 | "org.apache.pekko" %% "pekko-http" % pekkoHttpV % Optional, 35 | "org.apache.pekko" %% "pekko-http-spray-json" % pekkoHttpV % Test, 36 | "org.apache.pekko" %% "pekko-http-testkit" % pekkoHttpV % Test 37 | ) 38 | 39 | 40 | // Test / testOptions += Tests.Argument(TestFrameworks.ScalaTest, "-h", "report/squbs-pattern") 41 | 42 | updateOptions := updateOptions.value.withCachedResolution(true) 43 | -------------------------------------------------------------------------------- /squbs-pattern/src/main/boilerplate/org/squbs/pattern/orchestration/package.scala.template: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.pattern 18 | 19 | package object orchestration { 20 | 21 | implicit class OrchestrationStructure[A](val f: OFuture[A]) extends AnyVal { 22 | def >>[T](fn: A=>OFuture[T]): OFuture[T] = { 23 | f flatMap fn 24 | } 25 | } 26 | 27 | [2..22# implicit class OrchestrationStructure1[[#A1#]](val ft: ([#OFuture[A1]#])) extends AnyVal { 28 | def >>[T](fn: ([#A1#])=>OFuture[T]): OFuture[T] = { 29 | [#ft._1 flatMap (a1 =># ] fn([#a1#])[#)# ] 30 | } 31 | }# 32 | 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /squbs-pattern/src/main/java/org/squbs/pattern/timeoutpolicy/TimedFn.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.pattern.timeoutpolicy; 18 | 19 | import java.time.Duration; 20 | 21 | @FunctionalInterface 22 | public interface TimedFn { 23 | T get(Duration t) throws Exception; 24 | } 25 | -------------------------------------------------------------------------------- /squbs-pattern/src/main/java/org/squbs/pattern/timeoutpolicy/TimeoutPolicyType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.pattern.timeoutpolicy; 18 | 19 | public enum TimeoutPolicyType { 20 | FIXED, 21 | SIGMA, 22 | PERCENTILE 23 | } 24 | -------------------------------------------------------------------------------- /squbs-pattern/src/main/scala/org/squbs/pattern/orchestration/Orchestrator.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.pattern.orchestration 18 | 19 | import org.apache.pekko.actor.Actor 20 | 21 | import scala.concurrent.Future 22 | import scala.language.implicitConversions 23 | import scala.util.Try 24 | 25 | @deprecated("The Orchestration module is deprecated. Please use Pekko streams for safer orchestration instead.", 26 | since = "0.15.0") 27 | trait Orchestrator extends Aggregator { this: Actor => 28 | 29 | protected case class UniqueTryWrapper[T](id: Long, result: Try[T]) 30 | 31 | private[this] var _messageId = 0L 32 | protected def nextMessageId: Long = { _messageId += 1L; _messageId } 33 | 34 | implicit def toOFuture[T](future: Future[T]): OFuture[T] = { 35 | // Dragons here: DO NOT call nextMessageId from inside future.onComplete as that executes 36 | // outside the context of the actor. Instead, obtain the (val) id eagerly inside the actor and 37 | // give it to the function so it becomes pre-assigned. 38 | val nextId = nextMessageId 39 | 40 | val oPromise = OPromise[T]() 41 | import context.dispatcher 42 | future onComplete { self ! UniqueTryWrapper(nextId, _) } 43 | expectOnce { 44 | case UniqueTryWrapper(`nextId`, t: Try[_]) => oPromise complete t.asInstanceOf[Try[T]] 45 | } 46 | oPromise.future 47 | } 48 | 49 | implicit def toFuture[T](future: OFuture[T]): Future[T] = future.toFuture 50 | } 51 | 52 | -------------------------------------------------------------------------------- /squbs-pattern/src/main/scala/org/squbs/pattern/stream/PersistentQueueCloserActor.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.pattern.stream 18 | 19 | import org.apache.pekko.actor.{ActorLogging, Actor} 20 | 21 | class PersistentQueueCloserActor[T](queue: PersistentQueue[T]) extends Actor with ActorLogging { 22 | 23 | val pushIndex = Array.ofDim[Long](queue.totalOutputPorts) 24 | val commitIndex = Array.ofDim[Long](queue.totalOutputPorts) 25 | 26 | override def receive: Receive = { 27 | case PushedAndCommitted(outportId, pIndex, cIndex) => 28 | pushIndex(outportId) = pIndex 29 | if(cIndex > commitIndex(outportId)) commitIndex(outportId) = cIndex 30 | case Committed(outportId, index) => commitIndex(outportId) = index 31 | case UpstreamFailed => close() 32 | case UpstreamFinished => 33 | if(pushIndex.sameElements(commitIndex)) close() 34 | else { 35 | context.become({ 36 | case Committed(outportId, index) => 37 | commitIndex(outportId) = index 38 | if (pushIndex.sameElements(commitIndex)) close() 39 | }) 40 | } 41 | } 42 | 43 | private def close(): Unit = { 44 | queue.close() 45 | context.stop(self) 46 | } 47 | } 48 | 49 | case class PushedAndCommitted(outportId: Int, pushIndex: Long, commitIndex: Long) 50 | case class Committed(outportId: Int, index: Long) 51 | case object UpstreamFailed 52 | case object UpstreamFinished 53 | -------------------------------------------------------------------------------- /squbs-pattern/src/main/scala/org/squbs/pattern/timeoutpolicy/package.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.pattern 18 | 19 | package object timeoutpolicy { 20 | 21 | val fixedRule = FixedTimeoutRule 22 | 23 | trait TimeoutRuleConversions extends Any { 24 | 25 | /** 26 | * Timeout rule based on a given sigma (standard deviation) of previous response times. 27 | * @return the timeout rule 28 | */ 29 | def sigma: TimeoutRule 30 | 31 | /** 32 | * Timeout rule based on the 33 | */ 34 | def percentile: TimeoutRule 35 | 36 | /** 37 | * alias of sigma 38 | * @return 39 | */ 40 | def σ = sigma 41 | 42 | 43 | /** 44 | * alias of percentile 45 | * @return 46 | */ 47 | def percent = percentile 48 | 49 | /** 50 | * alias of percentile 51 | * @return 52 | */ 53 | def `%ile` = percentile 54 | } 55 | 56 | implicit final class TimeoutRuleInt(private val n: Int) extends AnyVal with TimeoutRuleConversions { 57 | override def sigma: TimeoutRule = SigmaTimeoutRule(n) 58 | 59 | override def percentile: TimeoutRule = PercentileTimeoutRule(n.toDouble) 60 | } 61 | 62 | implicit final class TimeoutRuleDouble(private val n: Double) extends AnyVal with TimeoutRuleConversions { 63 | override def sigma: TimeoutRule = SigmaTimeoutRule(n) 64 | 65 | override def percentile: TimeoutRule = PercentileTimeoutRule(n) 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /squbs-pattern/src/main/scala/org/squbs/pattern/validation/ValidationDirectives.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.pattern.validation 18 | 19 | import org.apache.pekko.http.scaladsl.server.Directives._ 20 | import org.apache.pekko.http.scaladsl.server.{Directive, ValidationRejection} 21 | import com.wix.accord.{Descriptions, Validator} 22 | import scala.language.implicitConversions 23 | 24 | trait ValidationDirectives { 25 | def validate(magnet: ValidationMagnet) = magnet() 26 | } 27 | 28 | object ValidationDirectives extends ValidationDirectives 29 | 30 | /** 31 | * @see Magnet Pattern 32 | */ 33 | sealed trait ValidationMagnet { 34 | def apply(): Directive[Unit] 35 | } 36 | 37 | object ValidationMagnet { 38 | implicit def fromObj[T](obj: T)(implicit validator: Validator[T]) = 39 | new ValidationMagnet { 40 | def apply() = { 41 | 42 | val result = com.wix.accord.validate(obj) 43 | 44 | result match { 45 | case com.wix.accord.Success => pass 46 | case com.wix.accord.Failure(violations) => reject( 47 | ValidationRejection(violations map { v => Descriptions.render(v.path) } mkString ", ")) 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /squbs-pattern/src/test/java/org/squbs/pattern/orchestration/japi/ServiceEmulator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.pattern.orchestration.japi; 18 | 19 | import org.apache.pekko.actor.AbstractActor; 20 | 21 | import static org.squbs.pattern.orchestration.japi.Messages.*; 22 | 23 | public class ServiceEmulator extends AbstractActor { 24 | 25 | @Override 26 | public Receive createReceive() { 27 | return receiveBuilder().match(ServiceRequest.class, request -> 28 | getContext().system().scheduler().scheduleOnce(request.delay, sender(), 29 | new ServiceResponse(request.id), getContext().dispatcher(), self()) 30 | ).build(); 31 | } 32 | } 33 | 34 | -------------------------------------------------------------------------------- /squbs-pattern/src/test/scala/org/squbs/pattern/timeoutpolicy/MathUtilSpec.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.pattern.timeoutpolicy 18 | 19 | import org.apache.commons.math3.special.Erf 20 | import org.scalactic.TolerantNumerics 21 | import org.scalatest.flatspec.AnyFlatSpecLike 22 | import org.scalatest.matchers.should.Matchers 23 | 24 | /** 25 | * see https://git-wip-us.apache.org/repos/asf?p=commons-math.git;a=blob_plain;f=src/test/java/org/apache/commons/math3/special/ErfTest.java;h=3e26662bd618d46e95b447ab538f4d45a473805e;hb=HEAD 26 | */ 27 | class MathUtilSpec extends AnyFlatSpecLike with Matchers{ 28 | 29 | it should "pass NaN cases" in { 30 | java.lang.Double.isNaN(MathUtil.erfInv(-1.001)) should be(true) 31 | java.lang.Double.isNaN(MathUtil.erfInv(1.001)) should be(true) 32 | } 33 | 34 | it should "pass Infinite case" in { 35 | MathUtil.erfInv(1) should be(Double.PositiveInfinity) 36 | MathUtil.erfInv(-1) should be(Double.NegativeInfinity) 37 | } 38 | 39 | it should "pass regular case" in { 40 | for (bx <- BigDecimal("-5.9") until 5.9 by 0.01) { 41 | val x = bx.toDouble 42 | val y = Erf.erf(x) 43 | val dydx = 2 * math.exp(-x * x) / math.sqrt(Math.PI) 44 | implicit val equality = TolerantNumerics.tolerantDoubleEquality(1.0e-15 / dydx) 45 | x shouldEqual(MathUtil.erfInv(y)) 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /squbs-pattern/src/test/scala/org/squbs/pattern/timeoutpolicy/TimeoutRuleConversionsSpec.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.pattern.timeoutpolicy 18 | 19 | import org.scalatest.flatspec.AnyFlatSpecLike 20 | import org.scalatest.matchers.should.Matchers 21 | 22 | class TimeoutRuleConversionsSpec extends AnyFlatSpecLike with Matchers{ 23 | 24 | "Implicit Conversions" should "work" in { 25 | 26 | (1.sigma).asInstanceOf[SigmaTimeoutRule].unit should be(1.0) 27 | (1.σ).asInstanceOf[SigmaTimeoutRule].unit should be(1.0) 28 | 29 | // around 2.99 30 | ((99.7.percent).asInstanceOf[SigmaTimeoutRule].unit * 10).round should be(30) 31 | ((99.7.`%ile`).asInstanceOf[SigmaTimeoutRule].unit * 10).round should be(30) 32 | ((99.7.percentile).asInstanceOf[SigmaTimeoutRule].unit * 10).round should be(30) 33 | 34 | fixedRule should be(FixedTimeoutRule) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /squbs-pattern/src/test/scala/org/squbs/pattern/validation/Person.scala: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright 2017 PayPal 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of 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, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package org.squbs.pattern.validation 19 | 20 | case class Person(firstName: String, lastName: String, middleName: Option[String] = None, age: Int) 21 | 22 | object SampleValidators { 23 | 24 | import com.wix.accord.dsl._ 25 | implicit val personValidator = com.wix.accord.dsl.validator[ Person ] { p => 26 | p.firstName as "First Name" is notEmpty 27 | p.lastName as "Last Name" is notEmpty 28 | p.middleName.each is notEmpty // If exists, should not be empty. 29 | p.age should be >= 0 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /squbs-pipeline/build.sbt: -------------------------------------------------------------------------------- 1 | import Versions._ 2 | 3 | name := "squbs-pipeline" 4 | 5 | libraryDependencies ++= Seq( 6 | "org.scala-lang.modules" %% "scala-collection-compat" % scalaCompatV, 7 | "org.scalatest" %% "scalatest" % scalatestV % Test, 8 | "org.apache.pekko" %% "pekko-actor" % pekkoV, 9 | "org.apache.pekko" %% "pekko-stream" % pekkoV, 10 | "org.apache.pekko" %% "pekko-http-core" % pekkoHttpV % Provided, 11 | "com.typesafe.scala-logging" %% "scala-logging" % scalaLoggingV, 12 | "org.apache.pekko" %% "pekko-testkit" % pekkoV % Test, 13 | "com.vladsch.flexmark" % "flexmark-all" % flexmarkV % Test, 14 | "ch.qos.logback" % "logback-classic" % logbackInTestV % Test 15 | ) 16 | 17 | //enablePlugins(de.johoop.testngplugin.TestNGPlugin) 18 | 19 | Test / testOptions ++= Seq( 20 | Tests.Argument(TestFrameworks.ScalaTest, "-h", "report/squbs-pipeline"), 21 | Tests.Argument(TestFrameworks.JUnit, "-v", "-a") 22 | ) 23 | 24 | updateOptions := updateOptions.value.withCachedResolution(true) -------------------------------------------------------------------------------- /squbs-pipeline/src/main/scala/org/squbs/pipeline/package.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs 18 | 19 | import org.apache.pekko.NotUsed 20 | import org.apache.pekko.stream.BidiShape 21 | import org.apache.pekko.stream.scaladsl.{BidiFlow, Broadcast, GraphDSL, Merge} 22 | 23 | package object pipeline { 24 | 25 | // (BidiFlow name, defaults on/off ) 26 | type PipelineSetting = (Option[String], Option[Boolean]) 27 | 28 | type PipelineFlow = BidiFlow[RequestContext, RequestContext, RequestContext, RequestContext, NotUsed] 29 | 30 | implicit class AbortableBidiFlow(val underlying: PipelineFlow) { 31 | 32 | def abortable: PipelineFlow = { 33 | underlying.atop(aborterFlow) 34 | } 35 | } 36 | 37 | val aborterFlow = BidiFlow.fromGraph(GraphDSL.create() { implicit b => 38 | import GraphDSL.Implicits._ 39 | 40 | val bCast = b.add(Broadcast[RequestContext](2)) 41 | val out1 = bCast.out(0).filter(_.response.isEmpty).outlet 42 | 43 | val merge = b.add(Merge[RequestContext](2)) 44 | bCast.out(1).filter(_.response.nonEmpty) ~> merge 45 | 46 | BidiShape(bCast.in, out1, merge.in(1), merge.out) 47 | }) 48 | } 49 | -------------------------------------------------------------------------------- /squbs-pipeline/src/test/java/org/squbs/pipeline/PostFlowJ.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.pipeline; 18 | 19 | import org.apache.pekko.NotUsed; 20 | import org.apache.pekko.actor.ActorSystem; 21 | import org.apache.pekko.http.javadsl.model.headers.RawHeader; 22 | import org.apache.pekko.stream.BidiShape; 23 | import org.apache.pekko.stream.FlowShape; 24 | import org.apache.pekko.stream.javadsl.BidiFlow; 25 | import org.apache.pekko.stream.javadsl.Flow; 26 | import org.apache.pekko.stream.javadsl.GraphDSL; 27 | import org.squbs.pipeline.japi.PipelineFlowFactory; 28 | 29 | public class PostFlowJ extends PipelineFlowFactory { 30 | @Override 31 | public BidiFlow 32 | create(Context context, ActorSystem system) { 33 | return BidiFlow.fromGraph(GraphDSL.create(b -> { 34 | final FlowShape inbound = b.add(Flow.of(RequestContext.class) 35 | .map(rc -> rc.withRequestHeader(RawHeader.create("keyPostInbound", "valPostInbound")))); 36 | final FlowShape outbound = b.add(Flow.of(RequestContext.class) 37 | .map(rc -> rc.withResponseHeader(RawHeader.create("keyPostOutbound", "valPostOutbound")))); 38 | return BidiShape.fromFlows(inbound, outbound); 39 | })); 40 | } 41 | } 42 | 43 | -------------------------------------------------------------------------------- /squbs-pipeline/src/test/java/org/squbs/pipeline/PreFlowJ.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.pipeline; 18 | 19 | import org.apache.pekko.NotUsed; 20 | import org.apache.pekko.actor.ActorSystem; 21 | import org.apache.pekko.http.javadsl.model.headers.RawHeader; 22 | import org.apache.pekko.stream.BidiShape; 23 | import org.apache.pekko.stream.FlowShape; 24 | import org.apache.pekko.stream.javadsl.BidiFlow; 25 | import org.apache.pekko.stream.javadsl.Flow; 26 | import org.apache.pekko.stream.javadsl.GraphDSL; 27 | import org.squbs.pipeline.japi.PipelineFlowFactory; 28 | 29 | public class PreFlowJ extends PipelineFlowFactory { 30 | @Override 31 | public BidiFlow 32 | create(Context context, ActorSystem system) { 33 | return BidiFlow.fromGraph(GraphDSL.create(b -> { 34 | final FlowShape inbound = b.add(Flow.of(RequestContext.class) 35 | .map(rc -> rc.withRequestHeader(RawHeader.create("keyPreInbound", "valPreInbound")))); 36 | final FlowShape outbound = b.add(Flow.of(RequestContext.class) 37 | .map(rc -> rc.withResponseHeader(RawHeader.create("keyPreOutbound", "valPreOutbound")))); 38 | return BidiShape.fromFlows(inbound, outbound); 39 | })); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /squbs-pipeline/src/test/resources/testng.yaml: -------------------------------------------------------------------------------- 1 | name: squbs-pipelineTests 2 | 3 | tests: 4 | - name: PipelineTests 5 | classes: 6 | - org.squbs.pipeline.PipelineExtensionTest 7 | - org.squbs.pipeline.AbortableBidiFlowTest 8 | - org.squbs.pipeline.RequestContextTest 9 | -------------------------------------------------------------------------------- /squbs-pipeline/src/test/scala/org/squbs/pipeline/Timeouts.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.pipeline 18 | 19 | import org.apache.pekko.util.Timeout 20 | 21 | import scala.concurrent.duration._ 22 | 23 | object Timeouts { 24 | 25 | implicit val askTimeout = Timeout(30.seconds) 26 | 27 | val awaitMax = 60.seconds 28 | } 29 | -------------------------------------------------------------------------------- /squbs-testkit/build.sbt: -------------------------------------------------------------------------------- 1 | import Versions._ 2 | 3 | name := "squbs-testkit" 4 | 5 | libraryDependencies ++= Seq( 6 | "org.scala-lang.modules" %% "scala-collection-compat" % scalaCompatV, 7 | "org.scalatest" %% "scalatest" % scalatestV, 8 | "org.scalatestplus" %% "testng-6-7" % scalatestplusV % Optional, 9 | "org.apache.pekko" %% "pekko-actor" % pekkoV, 10 | "org.apache.pekko" %% "pekko-testkit" % pekkoV, 11 | "org.apache.pekko" %% "pekko-http-testkit" % pekkoHttpV % Optional, 12 | "junit" % "junit" % junitV % Optional, 13 | "org.testng" % "testng" % testngV % Optional, 14 | "com.github.pjfanning" %% "pekko-http-jackson" % pjfanningAkkaHttpJsonV % Test, 15 | "com.novocode" % "junit-interface" % junitInterfaceV % Test, 16 | "com.vladsch.flexmark" % "flexmark-all" % flexmarkV % Test, 17 | "ch.qos.logback" % "logback-classic" % logbackInTestV % Test 18 | 19 | ) 20 | 21 | Test / testOptions += Tests.Argument(TestFrameworks.JUnit, "-v", "-a") 22 | 23 | Test / javaOptions += "-Xmx512m" 24 | 25 | updateOptions := updateOptions.value.withCachedResolution(true) 26 | 27 | -------------------------------------------------------------------------------- /squbs-testkit/src/main/resources/build.properties: -------------------------------------------------------------------------------- 1 | custom=true 2 | -------------------------------------------------------------------------------- /squbs-testkit/src/main/resources/default-test.conf: -------------------------------------------------------------------------------- 1 | pekko { 2 | loglevel = "DEBUG" 3 | stdout-loglevel = "DEBUG" 4 | log-config-on-start = off 5 | log-dead-letters = on 6 | } 7 | 8 | squbs { 9 | external-config-dir = squbsconfig 10 | } 11 | -------------------------------------------------------------------------------- /squbs-testkit/src/main/scala/org/squbs/testkit/DebugTiming.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.testkit 18 | 19 | import org.apache.pekko.testkit.TestKitBase 20 | 21 | import scala.concurrent.duration._ 22 | 23 | object DebugTiming { 24 | 25 | val debugMode = java.lang.management.ManagementFactory.getRuntimeMXBean. 26 | getInputArguments.toString.indexOf("jdwp") >= 0 27 | 28 | val debugTimeout = 10000.seconds 29 | 30 | if (debugMode) println( 31 | "\n##################\n" + 32 | s"IMPORTANT: Detected system running in debug mode. Test timeouts overridden to $debugTimeout.\n" + 33 | "##################\n\n") 34 | } 35 | 36 | trait DebugTiming extends TestKitBase { 37 | import DebugTiming._ 38 | override def receiveOne(max: Duration): AnyRef = 39 | if (debugMode) super.receiveOne(debugTimeout) 40 | else super.receiveOne(max) 41 | } 42 | -------------------------------------------------------------------------------- /squbs-testkit/src/main/scala/org/squbs/testkit/PortGetter.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.testkit 18 | 19 | import org.apache.pekko.actor.ActorSystem 20 | import org.squbs.testkit.Timeouts._ 21 | import org.squbs.unicomplex.{PortBindings, Unicomplex} 22 | 23 | import scala.concurrent.Await 24 | 25 | trait PortGetter { 26 | 27 | val system: ActorSystem 28 | lazy val port: Int = port(listener) 29 | 30 | import org.apache.pekko.pattern.ask 31 | def port(listener: String) = Await.result((Unicomplex(system).uniActor ? PortBindings).mapTo[Map[String, Int]], awaitMax)(listener) 32 | 33 | def listener: String = "default-listener" 34 | } 35 | -------------------------------------------------------------------------------- /squbs-testkit/src/main/scala/org/squbs/testkit/Tags.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.testkit 18 | 19 | import org.scalatest.Tag 20 | 21 | object SlowTest extends Tag("org.squbs.testkit.tags.SlowTest") 22 | object DbTest extends Tag("org.squbs.testkit.tags.DbTest") 23 | -------------------------------------------------------------------------------- /squbs-testkit/src/main/scala/org/squbs/testkit/Timeouts.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.testkit 18 | 19 | import org.apache.pekko.util.Timeout 20 | 21 | import scala.concurrent.duration._ 22 | 23 | object Timeouts { 24 | 25 | implicit val askTimeout = Timeout(30.seconds) 26 | 27 | val awaitMax = 240.seconds 28 | } 29 | -------------------------------------------------------------------------------- /squbs-testkit/src/main/scala/org/squbs/testkit/japi/DebugTimingTestKit.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.testkit.japi 18 | 19 | import org.apache.pekko.actor.ActorSystem 20 | import org.apache.pekko.testkit.javadsl 21 | import org.squbs.testkit.DebugTiming 22 | 23 | import scala.concurrent.duration.Duration 24 | 25 | class DebugTimingTestKit(actorSystem: ActorSystem) extends javadsl.TestKit(actorSystem) { 26 | override def receiveOne(max: Duration): AnyRef = 27 | if (DebugTiming.debugMode) super.receiveOne(java.time.Duration.ofNanos(DebugTiming.debugTimeout.toNanos)) 28 | else super.receiveOne(java.time.Duration.ofNanos(max.toNanos)) 29 | 30 | override def receiveOne(max: java.time.Duration): AnyRef = 31 | if (DebugTiming.debugMode) super.receiveOne(java.time.Duration.ofNanos(DebugTiming.debugTimeout.toNanos)) 32 | else super.receiveOne(max) 33 | } 34 | -------------------------------------------------------------------------------- /squbs-testkit/src/main/scala/org/squbs/testkit/japi/JUnitRouteTest.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.squbs.testkit.japi 17 | 18 | abstract class JUnitRouteTest extends org.apache.pekko.http.javadsl.testkit.JUnitRouteTest with RouteDefinitionTest 19 | -------------------------------------------------------------------------------- /squbs-testkit/src/main/scala/org/squbs/testkit/japi/Timeouts.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.testkit.japi 18 | 19 | import org.apache.pekko.util.Timeout 20 | import org.squbs.testkit.{Timeouts => STimeouts} 21 | 22 | import java.time.Duration 23 | 24 | object Timeouts { 25 | val askTimeout: Timeout = STimeouts.askTimeout 26 | val awaitMax: Duration = Duration.ofNanos(STimeouts.awaitMax.toNanos) 27 | } 28 | -------------------------------------------------------------------------------- /squbs-testkit/src/test/java/org/squbs/testkit/TestActorJ.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.testkit; 18 | 19 | import org.apache.pekko.actor.AbstractActor; 20 | 21 | public class TestActorJ extends AbstractActor { 22 | 23 | @Override 24 | public Receive createReceive() { 25 | return receiveBuilder() 26 | .matchEquals("Ping", s -> getSender().tell("Pong", getSelf())) 27 | .build(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /squbs-testkit/src/test/java/org/squbs/testkit/japi/CustomTestKitConfigAndResourcesTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.testkit.japi; 18 | 19 | import com.typesafe.config.ConfigFactory; 20 | import org.junit.After; 21 | import org.testng.Assert; 22 | import org.testng.annotations.Test; 23 | 24 | import java.util.Arrays; 25 | import java.util.List; 26 | 27 | public class CustomTestKitConfigAndResourcesTest extends CustomTestKit { 28 | 29 | CustomTestKitConfigAndResourcesTest() { 30 | super(ConfigFactory.parseString("squbs.actorsystem-name = CustomTestKitConfigAndResourcesTestInConfig"), 31 | TestConfig.resources, false); 32 | } 33 | 34 | @After 35 | public void tearDown() { 36 | shutdown(); 37 | } 38 | 39 | @Test 40 | public void testDefaultListenerStarted() { 41 | Assert.assertEquals(port(), port("default-listener")); 42 | } 43 | 44 | @Test 45 | public void testActorSystemName() { 46 | Assert.assertEquals(system().name(), "CustomTestKitConfigAndResourcesTestInConfig"); 47 | } 48 | 49 | private static class TestConfig { 50 | private static List resources = Arrays.asList( 51 | TestConfig.class.getClassLoader().getResource("").getPath() + "/CustomTestKitTest/META-INF/squbs-meta.conf" 52 | ); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /squbs-testkit/src/test/java/org/squbs/testkit/japi/CustomTestKitConfigTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.testkit.japi; 18 | 19 | import com.typesafe.config.ConfigFactory; 20 | import org.squbs.unicomplex.JMX; 21 | import org.testng.Assert; 22 | import org.testng.annotations.AfterClass; 23 | import org.testng.annotations.Test; 24 | 25 | public class CustomTestKitConfigTest extends CustomTestKit { 26 | 27 | CustomTestKitConfigTest() { 28 | super(ConfigFactory.parseString("squbs.actorsystem-name = CustomTestKitConfigTestInConfig")); 29 | } 30 | 31 | @AfterClass 32 | public void tearDown() { 33 | shutdown(); 34 | } 35 | 36 | @Test 37 | public void testDefaultListenerStarted() { 38 | Assert.assertEquals(port(), port("default-listener")); 39 | } 40 | 41 | @Test 42 | public void testActorSystemName() { 43 | Assert.assertEquals(system().name(), "CustomTestKitConfigTestInConfig"); 44 | } 45 | 46 | @Test 47 | public void testPriorityGivenToCustomConfig() { 48 | Assert.assertEquals(system().settings().config().getString("squbs.actorsystem-name"), "CustomTestKitConfigTestInConfig"); 49 | } 50 | 51 | @Test 52 | public void testCustomAndDefaultConfigurationAreMerged() { 53 | Assert.assertEquals(system().settings().config().getBoolean("squbs." + JMX.prefixConfig()), true); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /squbs-testkit/src/test/java/org/squbs/testkit/japi/CustomTestKitDefaultJUnitTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.testkit.japi; 18 | 19 | import org.junit.After; 20 | import org.junit.Assert; 21 | import org.junit.Test; 22 | import org.squbs.unicomplex.JMX; 23 | 24 | public class CustomTestKitDefaultJUnitTest extends CustomTestKit { 25 | 26 | @After 27 | public void tearDown() { 28 | shutdown(); 29 | } 30 | 31 | @Test 32 | public void testDefaultListenerStarted() { 33 | Assert.assertEquals(port("default-listener"), port()); 34 | } 35 | 36 | @Test 37 | public void testActorSystemName() { 38 | Assert.assertTrue(system().name().matches("org-squbs-testkit-japi-CustomTestKitDefaultJUnitTest-\\d+")); 39 | } 40 | 41 | @Test 42 | public void testDefaultConfigurationInUse() { 43 | Assert.assertEquals(0, system().settings().config().getInt("default-listener.bind-port")); 44 | Assert.assertEquals(true, system().settings().config().getBoolean("squbs." + JMX.prefixConfig())); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /squbs-testkit/src/test/java/org/squbs/testkit/japi/CustomTestKitDefaultWithActorSystemNameTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.testkit.japi; 18 | 19 | import org.squbs.unicomplex.JMX; 20 | import org.testng.Assert; 21 | import org.testng.annotations.AfterClass; 22 | import org.testng.annotations.Test; 23 | 24 | public class CustomTestKitDefaultWithActorSystemNameTest extends CustomTestKit { 25 | 26 | CustomTestKitDefaultWithActorSystemNameTest() { 27 | super("CustomTestKitDefaultWithActorSystemNameTest"); 28 | } 29 | 30 | @AfterClass 31 | public void tearDown() { 32 | shutdown(); 33 | } 34 | 35 | @Test 36 | public void testDefaultListenerStarted() { 37 | Assert.assertEquals(port(), port("default-listener")); 38 | } 39 | 40 | @Test 41 | public void testActorSystemName() { 42 | Assert.assertEquals(system().name(), "CustomTestKitDefaultWithActorSystemNameTest"); 43 | } 44 | 45 | @Test 46 | public void testDefaultConfigurationInUse() { 47 | Assert.assertEquals(system().settings().config().getInt("default-listener.bind-port"), 0); 48 | Assert.assertEquals(system().settings().config().getBoolean("squbs." + JMX.prefixConfig()), true); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /squbs-testkit/src/test/java/org/squbs/testkit/japi/CustomTestKitEmptyResourcesTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.testkit.japi; 18 | 19 | import org.testng.annotations.AfterClass; 20 | import org.testng.annotations.Test; 21 | 22 | import java.util.ArrayList; 23 | import java.util.NoSuchElementException; 24 | 25 | public class CustomTestKitEmptyResourcesTest extends CustomTestKit { 26 | 27 | CustomTestKitEmptyResourcesTest() { 28 | super(new ArrayList<>(), false); 29 | } 30 | 31 | @AfterClass 32 | public void tearDown() { 33 | shutdown(); 34 | } 35 | 36 | @Test(expectedExceptions = NoSuchElementException.class) 37 | public void testNotBindtoAnyPort() { 38 | port(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /squbs-testkit/src/test/java/org/squbs/testkit/japi/CustomTestKitNoClassPathTest.java: -------------------------------------------------------------------------------- 1 | package org.squbs.testkit.japi; 2 | 3 | 4 | import static org.junit.Assert.*; 5 | 6 | import org.junit.After; 7 | import org.junit.Test; 8 | 9 | public class CustomTestKitNoClassPathTest extends CustomTestKit { 10 | 11 | public CustomTestKitNoClassPathTest() { 12 | super(false); 13 | } 14 | 15 | @After 16 | public void tearDown() { 17 | shutdown(); 18 | } 19 | 20 | @Test 21 | public void testDefaultListenerStarted() { 22 | assertEquals(port("default-listener"), port()); 23 | } 24 | 25 | @Test 26 | public void testActorSystemName() { 27 | assertTrue(system().name().matches("org-squbs-testkit-japi-CustomTestKitNoClassPathTest-\\d+")); 28 | } 29 | 30 | @Test 31 | public void testDefaultResources() { 32 | assertEquals(1, boot().cubes().size()); 33 | assertEquals("CustomTestKitDefaultSpec", boot().cubes().head().info().name()); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /squbs-testkit/src/test/java/org/squbs/testkit/japi/CustomTestKitResourcesJUnitTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.testkit.japi; 18 | 19 | import org.junit.After; 20 | import org.junit.Assert; 21 | import org.junit.Test; 22 | 23 | import java.util.Arrays; 24 | import java.util.List; 25 | 26 | public class CustomTestKitResourcesJUnitTest extends CustomTestKit { 27 | 28 | public CustomTestKitResourcesJUnitTest() { 29 | super(TestConfig.resources, false); 30 | } 31 | 32 | @After 33 | public void tearDown() { 34 | shutdown(); 35 | } 36 | 37 | @Test 38 | public void testDefaultListenerStarted() { 39 | Assert.assertEquals(port("default-listener"), port()); 40 | } 41 | 42 | @Test 43 | public void testActorSystemName() { 44 | Assert.assertTrue(system().name().matches("org-squbs-testkit-japi-CustomTestKitResourcesJUnitTest-\\d+")); 45 | } 46 | 47 | private static class TestConfig { 48 | private static List resources = Arrays.asList( 49 | TestConfig.class.getClassLoader().getResource("").getPath() + "/CustomTestKitTest/META-INF/squbs-meta.conf" 50 | ); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /squbs-testkit/src/test/java/org/squbs/testkit/japi/CustomTestKitResourcesWithActorSystemNameTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.testkit.japi; 18 | 19 | import org.testng.Assert; 20 | import org.testng.annotations.AfterClass; 21 | import org.testng.annotations.Test; 22 | 23 | import java.util.Arrays; 24 | import java.util.List; 25 | 26 | public class CustomTestKitResourcesWithActorSystemNameTest extends CustomTestKit { 27 | 28 | CustomTestKitResourcesWithActorSystemNameTest() { 29 | super("CustomTestKitResourcesWithActorSystemNameTest", TestConfig.resources, false); 30 | } 31 | 32 | @AfterClass 33 | public void tearDown() { 34 | shutdown(); 35 | } 36 | 37 | @Test 38 | public void testDefaultListenerStarted() { 39 | Assert.assertEquals(port(), port("default-listener")); 40 | } 41 | 42 | @Test 43 | public void testActorSystemName() { 44 | Assert.assertEquals(system().name(), "CustomTestKitResourcesWithActorSystemNameTest"); 45 | } 46 | 47 | private static class TestConfig { 48 | private static List resources = Arrays.asList( 49 | TestConfig.class.getClassLoader().getResource("").getPath() + "/CustomTestKitTest/META-INF/squbs-meta.conf" 50 | ); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /squbs-testkit/src/test/java/org/squbs/testkit/japi/CustomTestKitWithClassPathTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.testkit.japi; 18 | 19 | import org.testng.Assert; 20 | import org.testng.annotations.AfterClass; 21 | import org.testng.annotations.Test; 22 | 23 | import java.util.ArrayList; 24 | 25 | public class CustomTestKitWithClassPathTest extends CustomTestKit { 26 | 27 | CustomTestKitWithClassPathTest() { 28 | super(new ArrayList<>(), true); 29 | } 30 | 31 | @AfterClass 32 | public void tearDown() { 33 | shutdown(); 34 | } 35 | 36 | @Test 37 | public void testDefaultListenerStarted() { 38 | Assert.assertEquals(port(), port("default-listener")); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /squbs-testkit/src/test/java/org/squbs/testkit/japi/DecrementActor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.squbs.testkit.japi; 17 | 18 | import org.apache.pekko.actor.AbstractActor; 19 | 20 | public class DecrementActor extends AbstractActor { 21 | 22 | @Override 23 | public Receive createReceive() { 24 | return receiveBuilder() 25 | .match(Integer.class, i -> sender().tell(i - 1, self())) 26 | .build(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /squbs-testkit/src/test/java/org/squbs/testkit/japi/IncrementActor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.squbs.testkit.japi; 17 | 18 | import org.apache.pekko.actor.AbstractActor; 19 | 20 | public class IncrementActor extends AbstractActor { 21 | 22 | @Override 23 | public Receive createReceive() { 24 | return receiveBuilder() 25 | .match(Integer.class, i -> sender().tell(i + 1, self())) 26 | .build(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /squbs-testkit/src/test/java/org/squbs/testkit/japi/InfoRoute.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.squbs.testkit.japi; 17 | 18 | import org.apache.pekko.http.javadsl.model.ContentTypes; 19 | import org.apache.pekko.http.javadsl.model.HttpEntities; 20 | import org.apache.pekko.http.javadsl.server.Route; 21 | import org.squbs.unicomplex.AbstractRouteDefinition; 22 | 23 | public class InfoRoute extends AbstractRouteDefinition { 24 | 25 | @Override 26 | public Route route() { 27 | return get(() -> 28 | path("context-info", () -> 29 | complete(HttpEntities.create(ContentTypes.APPLICATION_JSON, 30 | "{ \"webContext\": \"" + webContext() + 31 | "\" , \"actorPath\": \"" + context().self().path() + "\" }")) 32 | ) 33 | ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /squbs-testkit/src/test/java/org/squbs/testkit/japi/RouteInfo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.squbs.testkit.japi; 17 | 18 | public class RouteInfo { 19 | private String webContext; 20 | private String actorPath; 21 | 22 | public String getWebContext() { 23 | return webContext; 24 | } 25 | 26 | public void setWebContext(String webContext) { 27 | this.webContext = webContext; 28 | } 29 | 30 | public String getActorPath() { 31 | return actorPath; 32 | } 33 | 34 | public void setActorPath(String actorPath) { 35 | this.actorPath = actorPath; 36 | } 37 | } -------------------------------------------------------------------------------- /squbs-testkit/src/test/java/org/squbs/testkit/japi/RouteResultInfo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.squbs.testkit.japi; 17 | 18 | public class RouteResultInfo { 19 | private String webContext; 20 | private String actorPath; 21 | private int result; 22 | 23 | public String getWebContext() { 24 | return webContext; 25 | } 26 | 27 | public void setWebContext(String webContext) { 28 | this.webContext = webContext; 29 | } 30 | 31 | public String getActorPath() { 32 | return actorPath; 33 | } 34 | 35 | public void setActorPath(String actorPath) { 36 | this.actorPath = actorPath; 37 | } 38 | 39 | public int getResult() { 40 | return result; 41 | } 42 | 43 | public void setResult(int result) { 44 | this.result = result; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /squbs-testkit/src/test/java/org/squbs/testkit/japi/junit/CustomRouteTestKitWithClassPathTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.squbs.testkit.japi.junit; 17 | 18 | import org.apache.pekko.http.javadsl.marshallers.jackson.Jackson; 19 | import org.apache.pekko.http.javadsl.model.HttpRequest; 20 | import org.apache.pekko.http.javadsl.testkit.TestRoute; 21 | import org.junit.Test; 22 | import org.squbs.testkit.japi.InfoRouteWithActor; 23 | import org.squbs.testkit.japi.JUnitCustomRouteTestKit; 24 | import org.squbs.testkit.japi.RouteResultInfo; 25 | 26 | import static org.junit.Assert.assertEquals; 27 | import static org.junit.Assert.assertTrue; 28 | 29 | public class CustomRouteTestKitWithClassPathTest extends JUnitCustomRouteTestKit { 30 | 31 | public CustomRouteTestKitWithClassPathTest() { 32 | super(true); 33 | } 34 | 35 | @Test 36 | public void testSimpleRoute() { 37 | TestRoute simpleRoute = testRoute(InfoRouteWithActor.class); 38 | RouteResultInfo routeInfo = simpleRoute.run(HttpRequest.GET("/increment/10")) 39 | .assertStatusCode(200) 40 | .entity(Jackson.unmarshaller(RouteResultInfo.class)); 41 | assertEquals("", routeInfo.getWebContext()); 42 | assertTrue("ActorPath: " + routeInfo.getActorPath() + " does not start with pekko://", 43 | routeInfo.getActorPath().startsWith("pekko://")); 44 | assertEquals(11, routeInfo.getResult()); 45 | } 46 | 47 | } 48 | 49 | -------------------------------------------------------------------------------- /squbs-testkit/src/test/java/org/squbs/testkit/japi/testng/CustomRouteTestKitWithClassPathTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.squbs.testkit.japi.testng; 17 | 18 | import org.apache.pekko.http.javadsl.marshallers.jackson.Jackson; 19 | import org.apache.pekko.http.javadsl.model.HttpRequest; 20 | import org.apache.pekko.http.javadsl.testkit.TestRoute; 21 | import org.squbs.testkit.japi.InfoRouteWithActor; 22 | import org.squbs.testkit.japi.RouteResultInfo; 23 | import org.squbs.testkit.japi.TestNGCustomRouteTestKit; 24 | import org.testng.annotations.Test; 25 | 26 | import static org.testng.Assert.assertEquals; 27 | import static org.testng.Assert.assertTrue; 28 | 29 | public class CustomRouteTestKitWithClassPathTest extends TestNGCustomRouteTestKit { 30 | 31 | public CustomRouteTestKitWithClassPathTest() { 32 | super(true); 33 | } 34 | 35 | @Test 36 | public void testSimpleRoute() { 37 | TestRoute simpleRoute = testRoute(InfoRouteWithActor.class); 38 | RouteResultInfo routeInfo = simpleRoute.run(HttpRequest.GET("/increment/10")) 39 | .assertStatusCode(200) 40 | .entity(Jackson.unmarshaller(RouteResultInfo.class)); 41 | assertEquals(routeInfo.getWebContext(), ""); 42 | assertTrue(routeInfo.getActorPath().startsWith("pekko://"), 43 | "ActorPath: " + routeInfo.getActorPath() + " does not start with pekko://"); 44 | assertEquals(routeInfo.getResult(), 11); 45 | } 46 | 47 | } 48 | 49 | -------------------------------------------------------------------------------- /squbs-testkit/src/test/resources/CustomRouteTestKitSpec/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.testkit.CustomRouteTestKitSpec 2 | cube-version = "0.0.1" 3 | 4 | squbs-actors = [ 5 | { 6 | class-name = org.squbs.testkit.ReverserActor 7 | name = reverser 8 | } 9 | ] -------------------------------------------------------------------------------- /squbs-testkit/src/test/resources/CustomTestKitDefaultSpec/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.testkit.CustomTestKitDefaultSpec 2 | cube-version = "0.0.1" 3 | 4 | squbs-actors = [ 5 | { 6 | class-name = org.squbs.testkit.japi.DecrementActor 7 | name = decrementActor 8 | } 9 | ] -------------------------------------------------------------------------------- /squbs-testkit/src/test/resources/CustomTestKitTest/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.testkit.CustomTestKitSpec 2 | cube-version = "0.0.1" 3 | 4 | squbs-services = [ 5 | { 6 | class-name = org.squbs.testkit.Service 7 | web-context = test 8 | } 9 | ] -------------------------------------------------------------------------------- /squbs-testkit/src/test/resources/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.testkit.CustomTestKitDefaultSpec 2 | cube-version = "0.0.1" 3 | 4 | squbs-services = [ 5 | { 6 | class-name = org.squbs.testkit.Service 7 | web-context = test 8 | } 9 | ] 10 | 11 | squbs-actors = [ 12 | { 13 | class-name = org.squbs.testkit.japi.IncrementActor 14 | name = incrementActor 15 | } 16 | ] -------------------------------------------------------------------------------- /squbs-testkit/src/test/resources/PortGetterSpec/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.testkit.PortGetterSpec 2 | cube-version = "0.0.1" 3 | 4 | squbs-services = [ 5 | { 6 | class-name = org.squbs.testkit.Service 7 | web-context = test 8 | listeners = [ default-listener, my-listener] 9 | } 10 | ] -------------------------------------------------------------------------------- /squbs-testkit/src/test/resources/README: -------------------------------------------------------------------------------- 1 | Test resources shall be in this directory. 2 | -------------------------------------------------------------------------------- /squbs-testkit/src/test/resources/testng.yaml: -------------------------------------------------------------------------------- 1 | name: Testkit 2 | 3 | tests: 4 | - name: AbstractCustomTestKit 5 | classes: 6 | - org.squbs.testkit.japi.CustomTestKitConfigAndResourcesTest 7 | - org.squbs.testkit.japi.CustomTestKitConfigTest 8 | - org.squbs.testkit.japi.CustomTestKitDefaultWithActorSystemNameTest 9 | - org.squbs.testkit.japi.CustomTestKitEmptyResourcesTest 10 | - org.squbs.testkit.japi.CustomTestKitResourcesWithActorSystemNameTest 11 | - org.squbs.testkit.japi.CustomTestKitTest 12 | - org.squbs.testkit.japi.CustomTestKitWithClassPathTest 13 | - name: CustomRouteTestKit 14 | classes: 15 | - org.squbs.testkit.japi.testng.RouteTestTest 16 | - org.squbs.testkit.japi.testng.CustomRouteTestKitTest 17 | - org.squbs.testkit.japi.testng.CustomRouteTestKitConfigTest 18 | - org.squbs.testkit.japi.testng.CustomRouteTestKitResourcesTest 19 | - org.squbs.testkit.japi.testng.CustomRouteTestKitConfigResourcesTest 20 | 21 | -------------------------------------------------------------------------------- /squbs-testkit/src/test/scala/org/squbs/testkit/package.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs 18 | 19 | import org.apache.pekko.actor.ActorSystem 20 | import org.apache.pekko.http.scaladsl.Http 21 | import org.apache.pekko.http.scaladsl.model.{HttpRequest, HttpResponse, Uri} 22 | import org.apache.pekko.util.ByteString 23 | 24 | import scala.concurrent.Future 25 | 26 | package object testkit { 27 | case object TestPing 28 | case object TestPong 29 | 30 | def entityAsString(uri: String)(implicit system: ActorSystem): Future[String] = { 31 | import system.dispatcher 32 | get(uri) flatMap extractEntityAsString 33 | } 34 | 35 | def get(uri: String)(implicit system: ActorSystem): Future[HttpResponse] = 36 | Http().singleRequest(HttpRequest(uri = Uri(uri))) 37 | 38 | def extractEntityAsString(response: HttpResponse)(implicit system: ActorSystem): Future[String] = { 39 | import system.dispatcher 40 | response.entity.dataBytes.runFold(ByteString(""))(_ ++ _) map(_.utf8String) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /squbs-unicomplex/build.sbt: -------------------------------------------------------------------------------- 1 | import Versions._ 2 | 3 | name := "squbs-unicomplex" 4 | 5 | Test / javaOptions += "-Xmx512m" 6 | 7 | libraryDependencies ++= Seq( 8 | "org.scala-lang" % "scala-reflect" % scalaVersion.value, 9 | "org.scala-lang.modules" %% "scala-collection-compat" % scalaCompatV, 10 | "org.scalatest" %% "scalatest" % scalatestV % Test, 11 | "org.scalatestplus" %% "mockito-3-4" % scalatestplusV % Test, 12 | "org.mockito" % "mockito-core" % mockitoV % Test, 13 | "com.typesafe.scala-logging" %% "scala-logging" % scalaLoggingV, 14 | "com.vladsch.flexmark" % "flexmark-all" % flexmarkV % Test, 15 | "ch.qos.logback" % "logback-classic" % logbackInTestV % Test, 16 | "com.wix" %% "accord-core" % accordV % Test, 17 | "junit" % "junit" % junitV % Test, 18 | "com.novocode" % "junit-interface" % junitInterfaceV % Test 19 | ) ++ pekkoDependencies 20 | 21 | def pekkoDependencies = Seq( 22 | "org.apache.pekko" %% "pekko-actor" % pekkoV, 23 | "org.apache.pekko" %% "pekko-http" % pekkoHttpV, 24 | "org.apache.pekko" %% "pekko-testkit" % pekkoV % Test, 25 | "org.apache.pekko" %% "pekko-stream-testkit" % pekkoV % Test 26 | ) 27 | 28 | Test / testOptions ++= Seq( 29 | Tests.Argument(TestFrameworks.ScalaTest, "-h", "report/squbs-unicomplex"), 30 | Tests.Argument(TestFrameworks.JUnit, "-v", "-a") 31 | ) 32 | 33 | 34 | updateOptions := updateOptions.value.withCachedResolution(true) -------------------------------------------------------------------------------- /squbs-unicomplex/src/main/java/org/squbs/stream/TriggerEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.squbs.stream; 17 | 18 | public enum TriggerEvent { 19 | ENABLE(true), 20 | DISABLE(false); 21 | 22 | final public Boolean value; 23 | 24 | TriggerEvent(Boolean value) { 25 | this.value = value; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /squbs-unicomplex/src/main/resources/build.properties: -------------------------------------------------------------------------------- 1 | custom=true 2 | -------------------------------------------------------------------------------- /squbs-unicomplex/src/main/scala/org/squbs/lifecycle/ExtensionLifecycle.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.lifecycle 18 | 19 | import org.squbs.unicomplex.UnicomplexBoot 20 | 21 | object ExtensionLifecycle { 22 | 23 | private[lifecycle] val tlBoot = new ThreadLocal[Option[UnicomplexBoot]] { 24 | override def initialValue(): Option[UnicomplexBoot] = None 25 | } 26 | 27 | def apply[T](boot: UnicomplexBoot)(creator: ()=>T): T = { 28 | tlBoot.set(Option(boot)) 29 | val r = creator() 30 | tlBoot.set(None) 31 | r 32 | } 33 | } 34 | 35 | trait ExtensionLifecycle { 36 | 37 | protected implicit val boot = ExtensionLifecycle.tlBoot.get.get 38 | 39 | /** 40 | * Before the [[init]] phase, to let extensions to influence each other 41 | */ 42 | def preInit(): Unit = {} 43 | 44 | /** 45 | * Before unicomplex starts (actor system has not been created yet) 46 | */ 47 | def init(): Unit = {} 48 | 49 | /** 50 | * After unicomplex starts, but before any cubes are initialized 51 | */ 52 | def preCubesInit(): Unit = {} 53 | 54 | /** 55 | * After cubes are initialized 56 | */ 57 | def postInit(): Unit = {} 58 | 59 | /** 60 | * [[akka.actor.ActorSystem.registerOnTermination]] 61 | */ 62 | def shutdown(): Unit = {} 63 | } 64 | -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/java/org/squbs/stream/HttpFlowWithMergeHubJ.java: -------------------------------------------------------------------------------- 1 | package org.squbs.stream; 2 | 3 | import org.apache.pekko.NotUsed; 4 | import org.apache.pekko.http.javadsl.model.HttpRequest; 5 | import org.apache.pekko.http.javadsl.model.HttpResponse; 6 | import org.apache.pekko.http.javadsl.model.RequestEntity; 7 | import org.apache.pekko.http.javadsl.unmarshalling.Unmarshaller; 8 | import org.apache.pekko.stream.Materializer; 9 | import org.apache.pekko.stream.javadsl.Flow; 10 | import org.squbs.marshallers.MarshalUnmarshal; 11 | 12 | public class HttpFlowWithMergeHubJ extends FlowToPerpetualStream { 13 | 14 | private final Materializer mat = Materializer.createMaterializer(context()); 15 | private final MarshalUnmarshal mu = new MarshalUnmarshal(context().system().dispatcher(), mat); 16 | 17 | private final Unmarshaller unmarshaller = Unmarshaller.async(entity -> 18 | entity.toStrict(1000, mat).thenApply(e -> 19 | new MyMessage(Integer.parseInt(e.getData().utf8String())) 20 | ) 21 | ); 22 | 23 | @Override 24 | public Flow flow() { 25 | return Flow.create() 26 | .mapAsync(1, req -> mu.apply(unmarshaller, req.entity())) 27 | .alsoTo(matValue("/user/JavaPerpetualStreamMergeHubSpec/perpetualStreamWithMergeHub")) 28 | .map(myMessage -> HttpResponse.create().withEntity("Received Id: " + myMessage.id())); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/java/org/squbs/stream/PerpetualStreamWithMergeHubJ.java: -------------------------------------------------------------------------------- 1 | package org.squbs.stream; 2 | 3 | import org.apache.pekko.NotUsed; 4 | import org.apache.pekko.actor.ActorRef; 5 | import org.apache.pekko.actor.Props; 6 | import org.apache.pekko.stream.javadsl.MergeHub; 7 | import org.apache.pekko.stream.javadsl.RunnableGraph; 8 | import org.apache.pekko.stream.javadsl.Sink; 9 | import org.apache.pekko.stream.javadsl.Source; 10 | import org.squbs.unicomplex.Initializing; 11 | import org.squbs.unicomplex.LifecycleState; 12 | 13 | public class PerpetualStreamWithMergeHubJ extends AbstractPerpetualStream> { 14 | 15 | Source> source = MergeHub.of(MyMessage.class); 16 | 17 | ActorRef myMessageStorageActor = context().actorOf(Props.create(MyMessageStorageActor.class)); 18 | 19 | @Override 20 | public LifecycleState streamRunLifecycleState() { 21 | return Initializing.instance(); 22 | } 23 | 24 | /** 25 | * Describe your graph by implementing streamGraph 26 | * 27 | * @return The graph. 28 | */ 29 | @Override 30 | public RunnableGraph> streamGraph() { 31 | return source.to(Sink.actorRef(myMessageStorageActor, "Done")); 32 | } 33 | 34 | @Override 35 | public Receive createReceive() { 36 | return receiveBuilder() 37 | .matchEquals(RetrieveMyMessageStorageActorRef.instance(), 38 | ref -> getSender().tell(myMessageStorageActor, getSelf())) 39 | .build(); 40 | } 41 | } -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/java/org/squbs/stream/UnicomplexActorPublisherJ.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.squbs.stream; 17 | 18 | import org.apache.pekko.actor.ActorRef; 19 | import org.apache.pekko.actor.ActorSystem; 20 | import org.apache.pekko.japi.Pair; 21 | import org.apache.pekko.stream.ActorMaterializer; 22 | import org.apache.pekko.stream.Materializer; 23 | import org.apache.pekko.stream.javadsl.Keep; 24 | import org.apache.pekko.stream.javadsl.Source; 25 | import org.apache.pekko.stream.testkit.TestPublisher; 26 | import org.apache.pekko.stream.testkit.TestSubscriber; 27 | import org.apache.pekko.stream.testkit.javadsl.TestSink; 28 | import org.apache.pekko.stream.testkit.javadsl.TestSource; 29 | 30 | import java.util.function.Supplier; 31 | 32 | public class UnicomplexActorPublisherJ { 33 | private final ActorSystem system; 34 | 35 | private final Materializer materializer; 36 | 37 | public UnicomplexActorPublisherJ(ActorSystem system) { 38 | this.system = system; 39 | materializer = ActorMaterializer.create(system); 40 | } 41 | 42 | public Pair, Supplier>, TestSubscriber.Probe> runnableGraph() { 43 | Source> in = TestSource.probe(system); 44 | return new LifecycleManaged>().source(in).toMat(TestSink.probe(system), Keep.both()).run(materializer); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/java/org/squbs/stream/javasamples/HttpFlowWithMergeHub.java: -------------------------------------------------------------------------------- 1 | package org.squbs.stream.javasamples; 2 | 3 | import org.apache.pekko.NotUsed; 4 | import org.apache.pekko.http.javadsl.model.HttpRequest; 5 | import org.apache.pekko.http.javadsl.model.HttpResponse; 6 | import org.apache.pekko.stream.Materializer; 7 | import org.apache.pekko.stream.javadsl.Flow; 8 | import org.squbs.marshallers.MarshalUnmarshal; 9 | import org.squbs.stream.FlowToPerpetualStream; 10 | 11 | import static org.squbs.marshallers.json.JacksonMapperSupport.unmarshaller; 12 | 13 | class HttpFlowWithMergeHub extends FlowToPerpetualStream { 14 | 15 | private final Materializer mat = Materializer.createMaterializer(context()); 16 | private final MarshalUnmarshal mu = new MarshalUnmarshal(context().system().dispatcher(), mat); 17 | 18 | @Override 19 | public Flow flow() { 20 | return Flow.create() 21 | .mapAsync(1, req -> mu.apply(unmarshaller(MyMessage.class), req.entity())) 22 | .alsoTo(matValue("/user/mycube/perpetualStreamWithMergeHub")) 23 | .map(myMessage -> HttpResponse.create().withEntity("Received Id: " + myMessage.ip)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/java/org/squbs/unicomplex/javafailedroutesvc/JavaFailedRouteSvc.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.squbs.unicomplex.javafailedroutesvc; 17 | 18 | 19 | import org.apache.pekko.http.javadsl.server.Route; 20 | import org.squbs.unicomplex.AbstractRouteDefinition; 21 | 22 | public class JavaFailedRouteSvc extends AbstractRouteDefinition { 23 | 24 | private final String response; 25 | public JavaFailedRouteSvc(String response) { 26 | this.response = response; 27 | } 28 | 29 | @Override 30 | public Route route() { 31 | return path("ping", () -> 32 | complete(response) 33 | ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/java/org/squbs/unicomplex/javaroutenohandlersvc/JavaRouteNoHandlerSvc.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.squbs.unicomplex.javaroutenohandlersvc; 17 | 18 | 19 | import org.apache.pekko.http.javadsl.server.CustomRejection; 20 | import org.apache.pekko.http.javadsl.server.Route; 21 | import org.squbs.unicomplex.AbstractRouteDefinition; 22 | 23 | public class JavaRouteNoHandlerSvc extends AbstractRouteDefinition { 24 | 25 | @Override 26 | public Route route() { 27 | return route( 28 | path("ping", () -> 29 | complete("pong") 30 | ), 31 | path("reject", () -> 32 | reject(new ServiceRejection()) 33 | ), 34 | path("exception", () -> 35 | failWith(new ServiceException()) 36 | ) 37 | ); 38 | } 39 | } 40 | 41 | class ServiceRejection implements CustomRejection { } 42 | 43 | class ServiceException extends Exception { } 44 | -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | # This cube declaration is used for ScanResourceSpec to scan resources in the classpath. 2 | cube-name = org.squbs.unicomplex.test.ScanResourceCube 3 | cube-version = "0.0.1" 4 | squbs-actors = [ 5 | { 6 | class-name = org.squbs.unicomplex.dummycube.AppendActor 7 | name = Appender 8 | }, 9 | { 10 | class-name = org.squbs.unicomplex.dummycube.DummyPrependActor 11 | name = Prepender 12 | } 13 | ] -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/README: -------------------------------------------------------------------------------- 1 | Test resources shall be in this directory. 2 | -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/BadCube/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube = org.squbs.unicomplex.test.BadCube 2 | 3 | -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/BadCube1/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.test.BadCube1 2 | 3 | -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/BadCube2/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.test.BadCube2 2 | cube-version = "0.0.1" 3 | squbs-unknown = {{{{{{{} 4 | 5 | -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/BadUnicomplexBoot/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.test.BadUnicomplexBoot 2 | cube-version = "0.0.1" 3 | squbs-extensions = [ 4 | { 5 | class-name = org.squbs.unicomplex.dummyextensions.DummyExtensionC 6 | sequence = 300 7 | }, 8 | 9 | { 10 | class-name = org.squbs.unicomplex.dummyextensions.DummyExtensionD 11 | sequence = 300 12 | } 13 | 14 | ] 15 | 16 | squbs-services = [ 17 | { 18 | class-name = org.squbs.unicomplex.dummyextensions.DummyExtensionB 19 | listeners = [default-listener,bad-listener] 20 | web-context = "DummyExtB" 21 | }, 22 | 23 | { 24 | class-name = org.squbs.unicomplex.dummysvc.DummySvc 25 | web-context = "" 26 | }, 27 | { 28 | class-name = org.squbs.unicomplex.dummycubesvc.PingPongActor 29 | web-context = "" 30 | } 31 | 32 | ] 33 | 34 | squbs-actors = [ 35 | { 36 | class-name = org.squbs.unicomplex.dummycube.BadActor 37 | name = "BadActor" 38 | }, 39 | { 40 | class-name = org.squbs.unicomplex.dummycube.AppendActor 41 | }, 42 | { 43 | class-name = org.squbs.unicomplex.dummycube.DummyPrependActor 44 | name = Prepender 45 | with-router = true 46 | }, 47 | { 48 | class-name = org.squbs.unicomplex.cubeA.InitCubeActorA3 49 | name = InitCubeActorA3 50 | init-required = true 51 | } 52 | ] -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/ClassNotFoundCube/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.test.ClassNotFoundCube 2 | cube-version = "0.0.1" 3 | squbs-actors = [ 4 | { 5 | class-name = org.squbs.unicomplex.notfound.SomeInvalidClassName 6 | name = invalidactor 7 | } 8 | ] 9 | 10 | squbs-services = [ 11 | { 12 | class-name = org.squbs.unicomplex.notfound.SomeInvalidSvcClassName 13 | web-context = invalidservice 14 | } 15 | ] -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/ConnectionMetricsSpec/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.test.Metrics 2 | cube-version = "0.0.1" 3 | squbs-services = [ 4 | { 5 | class-name = org.squbs.unicomplex.ConnectionMetricsFlow 6 | listeners = [dev-listener, second-listener, third-listener] 7 | web-context = "sample" 8 | } 9 | { 10 | class-name = org.squbs.unicomplex.ConnectionMetricsFlow 11 | web-context = "sample2" 12 | } 13 | ] 14 | -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/CubeActorErrorStates/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.test.CubeActorErrorStates 2 | cube-version = "0.0.1" 3 | squbs-services = [ 4 | { 5 | class-name = org.squbs.unicomplex.CubeActorTest 6 | web-context = "test1" 7 | } 8 | { 9 | class-name = org.squbs.unicomplex.CubeActorTest 10 | web-context = "test2" 11 | } 12 | ] 13 | -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/DummyCube/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.test.DummyCube 2 | cube-version = "0.0.1" 3 | squbs-actors = [ 4 | 5 | { 6 | class-name = org.squbs.unicomplex.dummycube.AppendActor 7 | name = Appender 8 | }, 9 | { 10 | class-name = org.squbs.unicomplex.dummycube.DummyPrependActor 11 | name = Prepender 12 | } 13 | ] -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/DummyCubeSvc/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.test.DummyCubeSvc 2 | cube-version = "0.0.1" 3 | squbs-actors = [ 4 | { 5 | class-name = org.squbs.unicomplex.dummycubesvc.PingPongActor 6 | name = PingPongPlayer 7 | } 8 | ] 9 | 10 | squbs-services = [ 11 | { 12 | class-name = org.squbs.unicomplex.dummycubesvc.PingPongSvc 13 | web-context = pingpongsvc 14 | } 15 | ] -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/DummyExtensions/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.DummyExtensions 2 | cube-version = "0.0.1" 3 | squbs-extensions = [ 4 | { 5 | class-name = org.squbs.unicomplex.dummyextensions.DummyExtensionA 6 | sequence = 30 7 | }, 8 | 9 | { 10 | class-name = org.squbs.unicomplex.dummyextensions.DummyExtensionB 11 | sequence = 40 12 | } 13 | ] -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/DummyFailedExtensions/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.test.cubeinit.DummyFailedExtensions 2 | cube-version = "0.0.1" 3 | squbs-extensions = [ 4 | { 5 | class-name = org.squbs.unicomplex.dummyfailedextensions.DummyFailedExtensionA 6 | }, 7 | { 8 | class-name = org.squbs.unicomplex.dummyfailedextensions.DummyFailedExtensionB 9 | }, 10 | { 11 | class-name = org.squbs.unicomplex.dummyfailedextensions.DummyFailedExtensionC 12 | #This class does not exists. Load should fail as expected by test. 13 | } 14 | ] -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/DummyFailedFlowSvc1/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.test.DummyFailedFlowSvc1 2 | cube-version = "0.0.1" 3 | squbs-services = [ 4 | { 5 | class-name = org.squbs.unicomplex.dummyfailedflowsvc1.DummyFailedFlowSvc1 6 | web-context = dummyfailedflowsvc 7 | } 8 | ] -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/DummyFlowSvc/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.test.DummyFlowSvc 2 | cube-version = "0.0.1" 3 | squbs-services = [ 4 | { 5 | class-name = org.squbs.unicomplex.dummyflowsvc.DummyFlowSvc 6 | web-context = dummyflowsvc 7 | } 8 | ] -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/DummySvc/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.test.DummySvc 2 | cube-version = "0.0.1" 3 | squbs-services = [ 4 | { 5 | class-name = org.squbs.unicomplex.dummysvc.DummySvc 6 | web-context = dummysvc 7 | } 8 | { // Testing multiple-segment web contexts 9 | class-name = org.squbs.unicomplex.dummysvc.Dummy2VersionedSvc 10 | web-context = dummy2svc/v1 11 | } 12 | { // And deal with versioned and non-versioned at the same time 13 | class-name = org.squbs.unicomplex.dummysvc.Dummy2Svc 14 | web-context = dummy2svc 15 | } 16 | ] -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/DummySvcActor/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.test.DummySvcActor 2 | cube-version = "0.0.1" 3 | squbs-services = [ 4 | { 5 | class-name = org.squbs.unicomplex.dummysvcactor.DummySvcActor 6 | web-context = dummysvcactor 7 | 8 | } 9 | ] -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/FailedRouteSvc/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.test.FailedRouteSvc 2 | cube-version = "0.0.1" 3 | squbs-services = [ 4 | { 5 | class-name = org.squbs.unicomplex.FailedRouteSvc 6 | web-context = failedroutesvc 7 | } 8 | ] -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/FlowDefinitionSpec/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.test.FlowDefinitionSpec 2 | cube-version = "0.0.1" 3 | squbs-services = [ 4 | { 5 | class-name = org.squbs.unicomplex.TestFlowDefinition 6 | web-context = flowdef 7 | } 8 | ] 9 | -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/IllegalStateStream/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.stream.test.IllegalStateStream 2 | cube-version = "0.0.1" 3 | squbs-actors = [ 4 | { 5 | class-name = org.squbs.stream.IllegalStateStream 6 | name = IllegalStateStream 7 | init-required = true 8 | } 9 | ] -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/InitBlockCube/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.test.cubeinit.InitBlock 2 | cube-version = "0.0.1" 3 | squbs-actors = [ 4 | 5 | { 6 | class-name = org.squbs.unicomplex.initblock.InitBlockActor 7 | name = InitBlockActor 8 | init-required = true 9 | } 10 | ] -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/InitCubeA/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.test.cubeinit.CubeA 2 | cube-version = "0.0.1" 3 | squbs-actors = [ 4 | 5 | { 6 | class-name = org.squbs.unicomplex.cubeA.InitCubeActorA1 7 | name = InitCubeActorA1 8 | init-required = true 9 | }, 10 | { 11 | class-name = org.squbs.unicomplex.cubeA.InitCubeActorA2 12 | name = InitCubeActorA2 13 | init-required = true 14 | } 15 | ] -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/InitCubeB/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.test.cubeinit.CubeB 2 | cube-version = "0.0.1" 3 | squbs-actors = [ 4 | 5 | { 6 | class-name = org.squbs.unicomplex.cubeB.InitCubeActorB 7 | name = InitCubeActorB 8 | init-required = true 9 | } 10 | ] 11 | -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/InitFailCube/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.test.cubeinit.InitFail 2 | cube-version = "0.0.1" 3 | squbs-actors = [ 4 | 5 | { 6 | class-name = org.squbs.unicomplex.initfail.InitFailActor 7 | name = InitFailActor 8 | init-required = true 9 | } 10 | ] -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/InvalidPipelineFlowSvc/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.test.InvalidPipelineFlowSvc 2 | cube-version = "0.0.1" 3 | squbs-services = [ 4 | { 5 | class-name = org.squbs.unicomplex.dummyflowsvc.DummyFlowSvc 6 | web-context = dummyflowsvc 7 | pipeline = "notExists" 8 | } 9 | ] -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/JavaFailedFlowSvc/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.test.JavaFailedFlowSvc 2 | cube-version = "0.0.1" 3 | squbs-services = [ 4 | { 5 | class-name = org.squbs.unicomplex.javafailedflowsvc.JavaFailedFlowSvc 6 | web-context = javafailedflowsvc 7 | } 8 | ] -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/JavaFailedRouteSvc/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.test.JavaFailedRouteSvc 2 | cube-version = "0.0.1" 3 | squbs-services = [ 4 | { 5 | class-name = org.squbs.unicomplex.javafailedroutesvc.JavaFailedRouteSvc 6 | web-context = javafailedroutesvc 7 | } 8 | ] -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/JavaFlowSvc/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.test.JavaFlowSvc 2 | cube-version = "0.0.1" 3 | squbs-services = [ 4 | { 5 | class-name = org.squbs.unicomplex.javaflowsvc.JavaFlowSvc 6 | web-context = javaflowsvc 7 | } 8 | ] -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/JavaIllegalStateStream/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.stream.test.JavaIllegalStateStream 2 | cube-version = "0.0.1" 3 | squbs-actors = [ 4 | { 5 | class-name = org.squbs.stream.IllegalStateStreamJ 6 | name = IllegalStateStreamJ 7 | init-required = true 8 | } 9 | ] -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/JavaKillSwitchMatStream/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.stream.test.JavaKillSwitchMatStream 2 | cube-version = "0.0.1" 3 | squbs-actors = [ 4 | { 5 | class-name = org.squbs.stream.KillSwitchMatStreamJ 6 | name = KillSwitchMatStreamJ 7 | } 8 | ] -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/JavaKillSwitchStream/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.stream.test.JavaKillSwitchStream 2 | cube-version = "0.0.1" 3 | squbs-actors = [ 4 | { 5 | class-name = org.squbs.stream.KillSwitchStreamJ 6 | name = KillSwitchStreamJ 7 | } 8 | ] -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/JavaKillSwitchWithChildActorStream/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.stream.test.JavaKillSwitchWithChildActorStream 2 | cube-version = "0.0.1" 3 | squbs-actors = [ 4 | { 5 | class-name = org.squbs.stream.KillSwitchWithChildActorStreamJ 6 | name = KillSwitchWithChildActorStreamJ 7 | } 8 | ] -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/JavaPerpetualStreamMergeHubSpec/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.stream.test.JavaPerpetualStreamMergeHubSpec 2 | cube-version = "0.0.1" 3 | squbs-services = [ 4 | { 5 | class-name = org.squbs.stream.HttpFlowWithMergeHubJ 6 | web-context = mergehub 7 | } 8 | ] 9 | squbs-actors = [ 10 | { 11 | class-name = org.squbs.stream.PerpetualStreamWithMergeHubJ 12 | name = perpetualStreamWithMergeHub 13 | } 14 | ] -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/JavaProperShutdownStream/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.stream.test.JavaProperShutdownStream 2 | cube-version = "0.0.1" 3 | squbs-actors = [ 4 | { 5 | class-name = org.squbs.stream.ProperShutdownStreamJ 6 | name = ProperShutdownStreamJ 7 | } 8 | ] -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/JavaRootSvc/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.test.JavaRootSvc 2 | cube-version = "0.0.1" 3 | squbs-services = [ 4 | { 5 | class-name = org.squbs.unicomplex.javaroutesvc.JavaRouteSvc 6 | web-context = "" 7 | } 8 | ] -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/JavaRouteNoHandlerSvc/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.test.JavaRouteNoHandlerSvc 2 | cube-version = "0.0.1" 3 | squbs-services = [ 4 | { 5 | class-name = org.squbs.unicomplex.javaroutenohandlersvc.JavaRouteNoHandlerSvc 6 | web-context = javaroutenohandlersvc 7 | } 8 | ] -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/JavaRouteSvc/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.test.JavaRouteSvc 2 | cube-version = "0.0.1" 3 | squbs-services = [ 4 | { 5 | class-name = org.squbs.unicomplex.javaroutesvc.JavaRouteSvc 6 | web-context = javaroutesvc 7 | } 8 | ] -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/JavaThrowExceptionStream/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.stream.test.JavaThrowExceptionStream 2 | cube-version = "0.0.1" 3 | squbs-actors = [ 4 | { 5 | class-name = org.squbs.stream.ThrowExceptionStreamJ 6 | name = ThrowExceptionStreamJ 7 | } 8 | ] -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/KillSwitchMatStream/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.stream.test.KillSwitchMatStream 2 | cube-version = "0.0.1" 3 | squbs-actors = [ 4 | { 5 | class-name = org.squbs.stream.KillSwitchMatStream 6 | name = KillSwitchMatStream 7 | } 8 | ] -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/KillSwitchStream/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.stream.test.KillSwitchStream 2 | cube-version = "0.0.1" 3 | squbs-actors = [ 4 | { 5 | class-name = org.squbs.stream.KillSwitchStream 6 | name = KillSwitchStream 7 | } 8 | ] -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/KillSwitchWithChildActorStream/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.stream.test.KillSwitchWithChildActorStream 2 | cube-version = "0.0.1" 3 | squbs-actors = [ 4 | { 5 | class-name = org.squbs.stream.KillSwitchWithChildActorStream 6 | name = KillSwitchWithChildActorStream 7 | } 8 | ] -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/ListenerState/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.test.ListenerState 2 | cube-version = "0.0.1" 3 | squbs-services = [ 4 | { 5 | class-name = org.squbs.unicomplex.ListenerStateService 6 | listeners = [ default-listener, port-conflict-listener, ssl-context-not-exist-listener ] 7 | web-context = "listenerState" 8 | } 9 | ] -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/LocalPortListener/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.test.LocalPortListenerService 2 | cube-version = "0.0.1" 3 | squbs-services = [ 4 | { 5 | class-name = org.squbs.unicomplex.LocalPortListenerService 6 | listeners = [ default-listener, second-listener, third-listener, fourth-listener] 7 | web-context = localport 8 | } 9 | ] -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/MaterializerSpec/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.test.MaterializerSpec 2 | cube-version = "0.0.1" 3 | squbs-services = [ 4 | { 5 | class-name = org.squbs.unicomplex.ResumeFlowDefinition 6 | web-context = custommaterializer 7 | listeners = [ default-listener, test-listener ] 8 | } 9 | ] 10 | -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/MultiListeners/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.test.MultiListener 2 | cube-version = "0.0.1" 3 | squbs-services = [ 4 | { 5 | class-name = org.squbs.unicomplex.MultiListenerService 6 | listeners = [ default-listener, second-listener, third-listener ] 7 | web-context = multi 8 | } 9 | ] -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/PerpetualStreamMergeHubSpec/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.stream.test.PerpetualStreamMergeHubSpec 2 | cube-version = "0.0.1" 3 | squbs-services = [ 4 | { 5 | class-name = org.squbs.stream.HttpFlowWithMergeHub 6 | web-context = mergehub 7 | } 8 | ] 9 | squbs-actors = [ 10 | { 11 | class-name = org.squbs.stream.PerpetualStreamWithMergeHub 12 | name = perpetualStreamWithMergeHub 13 | } 14 | ] -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/ProperShutdownStream/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.stream.test.ProperShutdownStream 2 | cube-version = "0.0.1" 3 | squbs-actors = [ 4 | { 5 | class-name = org.squbs.stream.ProperShutdownStream 6 | name = ProperShutdownStream 7 | } 8 | ] -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/RootCtxFlowSpec/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.test.RootCtxFlowSpec 2 | cube-version = "0.0.1" 3 | squbs-services = [ 4 | { 5 | class-name = org.squbs.unicomplex.dummyflowsvc.DummyFlowSvc 6 | web-context = "" 7 | } 8 | ] -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/RootCtxRoute/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.test.RootRoute 2 | cube-version = "0.0.1" 3 | squbs-services = [ 4 | { 5 | class-name = org.squbs.unicomplex.RootRoute 6 | web-context = "" 7 | } 8 | ] 9 | -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/RouteActorHandler/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.test.Service 2 | cube-version = "0.0.1" 3 | squbs-services = [ 4 | { 5 | class-name = org.squbs.unicomplex.Service 6 | web-context = "ctx" 7 | } 8 | ] 9 | -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/RouteDefinitionSpec/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.test.RouteDefinitionSpec 2 | cube-version = "0.0.1" 3 | squbs-services = [ 4 | { 5 | class-name = org.squbs.unicomplex.TestRouteDefinition 6 | web-context = routedef 7 | } 8 | ] 9 | 10 | -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/StashCube/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.test.StashCube 2 | cube-version = "0.0.1" 3 | squbs-services = [ 4 | { 5 | class-name = org.squbs.unicomplex.stashcube.StashCubeSvc 6 | web-context = withstash 7 | } 8 | ] -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/StreamSvc/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.test.StreamSvc 2 | cube-version = "0.0.1" 3 | squbs-services = [ 4 | { 5 | class-name = org.squbs.unicomplex.streamSvc.StreamSvc 6 | listeners = [default-listener] 7 | web-context = streamsvc 8 | 9 | } 10 | ] 11 | 12 | -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/ThrowExceptionStream/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.stream.test.ThrowExceptionStream 2 | cube-version = "0.0.1" 3 | squbs-actors = [ 4 | { 5 | class-name = org.squbs.stream.ThrowExceptionStream 6 | name = ThrowExceptionStream 7 | } 8 | ] -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/UnicomplexBootTimeouts/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.test.ConfigurableInitTimeActor 2 | cube-version = "0.0.1" 3 | squbs-services = [ 4 | { 5 | class-name = org.squbs.unicomplex.timeout.ConfigurableInitTimeActor 6 | web-context = timeout 7 | listeners = [default-listener] 8 | } 9 | ] -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/pipeline/BadPipelineFactorySpec/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.pipeline.test.BadPipelineFactory 2 | cube-version = "0.0.1" 3 | squbs-services = [ 4 | { 5 | class-name = org.squbs.unicomplex.pipeline.DummyRoute 6 | web-context = "/bad" 7 | } 8 | ] 9 | -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/pipeline/BadPipelineNameSpec/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.pipeline.test.BadPipelineName 2 | cube-version = "0.0.1" 3 | squbs-services = [ 4 | { 5 | class-name = org.squbs.unicomplex.pipeline.DummyRoute 6 | web-context = "/bad" 7 | pipeline = notExists 8 | } 9 | ] 10 | -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/pipeline/MetricsFlowSpec/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.pipeline.test.Metrics 2 | cube-version = "0.0.1" 3 | squbs-services = [ 4 | { 5 | class-name = org.squbs.unicomplex.pipeline.MetricsRoute 6 | web-context = "" 7 | } 8 | { 9 | class-name = org.squbs.unicomplex.pipeline.MetricsRoute 10 | web-context = "sample" 11 | } 12 | { 13 | class-name = org.squbs.unicomplex.pipeline.MetricsRoute 14 | web-context = "sample2" 15 | } 16 | { 17 | class-name = org.squbs.unicomplex.pipeline.MetricsRoute 18 | web-context = "sample3" 19 | } 20 | { 21 | class-name = org.squbs.unicomplex.pipeline.MetricsRoute 22 | web-context = "sample4" 23 | } 24 | { 25 | class-name = org.squbs.unicomplex.pipeline.MetricsRoute 26 | web-context = "sample5" 27 | } 28 | { 29 | class-name = org.squbs.unicomplex.pipeline.MetricsRoute 30 | web-context = "sample6" 31 | } 32 | { 33 | class-name = org.squbs.unicomplex.pipeline.MetricsRoute 34 | web-context = "sample7" 35 | } 36 | { 37 | class-name = org.squbs.unicomplex.pipeline.MetricsDummyFlow 38 | listeners = [second-listener] 39 | web-context = "sample8" 40 | } 41 | 42 | ] 43 | -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/pipeline/PipelineChunkingSpec/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.pipeline.test.Pipeline 2 | cube-version = "0.0.1" 3 | squbs-services = [ 4 | { 5 | class-name = org.squbs.unicomplex.pipeline.FileUploadRoute 6 | web-context = "fileuploadroute" 7 | pipeline = dummyFlow 8 | } 9 | { 10 | class-name = org.squbs.unicomplex.pipeline.ChunkingActor 11 | web-context = "chunkingactor" 12 | pipeline = dummyFlow 13 | } 14 | ] 15 | -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/classpaths/pipeline/PipelineSpec/META-INF/squbs-meta.conf: -------------------------------------------------------------------------------- 1 | cube-name = org.squbs.unicomplex.pipeline.test.Pipeline 2 | cube-version = "0.0.1" 3 | squbs-services = [ 4 | { 5 | class-name = org.squbs.unicomplex.pipeline.DummyRoute 6 | web-context = "1" 7 | pipeline = dummyFlow 8 | } 9 | { 10 | class-name = org.squbs.unicomplex.pipeline.DummyRoute 11 | web-context = "2" 12 | } 13 | { 14 | class-name = org.squbs.unicomplex.pipeline.DummyRoute 15 | web-context = "3" 16 | pipeline = dummyFlow 17 | defaultPipeline = off 18 | } 19 | { 20 | class-name = org.squbs.unicomplex.pipeline.DummyRoute 21 | web-context = "4" 22 | defaultPipeline = off 23 | } 24 | { 25 | class-name = org.squbs.unicomplex.pipeline.DummyActor 26 | web-context = "5" 27 | pipeline = dummyFlow 28 | } 29 | ] 30 | -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/resources/reference.conf: -------------------------------------------------------------------------------- 1 | pekko { 2 | loglevel = WARNING 3 | } 4 | 5 | squbs { 6 | 7 | # Name of the actor system for squbs to create. 8 | actorsystem-name = "squbs" 9 | 10 | # If the application wants to take over Pekko HTTP altogether, services should not be started by squbs. 11 | start-service = true 12 | 13 | # An external configuration directory to supply external application.conf. The location of this directory 14 | # is relative to the working directory of the squbs process. 15 | external-config-dir = squbsconfig 16 | } 17 | 18 | default-listener { 19 | type = squbs.listener 20 | aliases = [] 21 | 22 | # Service bind to particular address/interface. The default is 0.0.0.0 which is any address/interface. 23 | bind-address = "0.0.0.0" 24 | 25 | # Whether or not using full host name for address binding 26 | full-address = false 27 | 28 | # Service bind to particular port. 8080 is the default. 29 | bind-port = 13000 30 | 31 | # Listener uses HTTPS? 32 | secure = false 33 | 34 | # HTTPS needs client authorization? This configuration is not read if secure is false. 35 | need-client-auth = false 36 | 37 | # Any custom SSLContext provider? Setting to "default" means platform default. 38 | ssl-context = default 39 | } 40 | 41 | blocking-dispatcher { 42 | # Dispatcher is the name of the event-based dispatcher 43 | type = Dispatcher 44 | # What kind of ExecutionService to use 45 | executor = "fork-join-executor" 46 | # Configuration for the fork join pool 47 | fork-join-executor { 48 | # Min number of threads to cap factor-based parallelism number to 49 | parallelism-min = 2 50 | # Parallelism (threads) ... ceil(available processors * factor) 51 | parallelism-factor = 3.0 52 | # Max number of threads to cap factor-based parallelism number to 53 | parallelism-max = 24 54 | } 55 | # Throughput defines the maximum number of messages to be 56 | # processed per actor before the thread jumps to the next actor. 57 | # Set to 1 for as fair as possible. 58 | throughput = 2 59 | } 60 | -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/scala/org/squbs/stream/IllegalStateStream.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.squbs.stream 17 | 18 | import org.apache.pekko.{Done, NotUsed} 19 | import org.apache.pekko.actor.ActorContext 20 | import org.apache.pekko.stream.ClosedShape 21 | import org.apache.pekko.stream.scaladsl.GraphDSL.Implicits._ 22 | import org.apache.pekko.stream.scaladsl._ 23 | import org.squbs.unicomplex.Initialized 24 | 25 | import scala.concurrent.Future 26 | import scala.language.postfixOps 27 | import scala.util.Try 28 | 29 | class IllegalStateStream extends PerpetualStream[Future[Int]] { 30 | def streamGraph = RunnableGraph.fromGraph(GraphDSL.createGraph(endSink) {implicit builder => 31 | sink => startSource ~> sink 32 | ClosedShape 33 | }) 34 | 35 | // By accessing matValue here, it should generate an IllegalStateException. 36 | // Reporting it to the parent would cause the cube and the system to be at state Failed. 37 | val t = Try { Option(matValue.toString) } 38 | context.parent ! Initialized(t) 39 | 40 | private def startSource(implicit context: ActorContext): Source[Int, NotUsed] = Source(1 to 10).map(_ * 1) 41 | 42 | private def endSink(implicit context: ActorContext): Sink[Int, Future[Int]] = { 43 | val sink = Sink.fold[Int, Int](0)(_ + _) 44 | sink 45 | } 46 | override def shutdown() = { 47 | print("Neo Stream Result " + matValue.value.get.get + "\n\n") 48 | Future.successful(Done) 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/scala/org/squbs/unicomplex/TestMsg.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.unicomplex 18 | 19 | object Constants { 20 | 21 | val SUFFIX = "$" 22 | val PREFIX = "^" 23 | } 24 | 25 | case class EchoMsg(msg: String) 26 | 27 | case class AppendedMsg(msg: String) 28 | 29 | case class PrependedMsg(msg: String) 30 | 31 | case object Ping 32 | 33 | case object Pong 34 | -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/scala/org/squbs/unicomplex/Timeouts.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.unicomplex 18 | 19 | import org.apache.pekko.util.Timeout 20 | 21 | import scala.concurrent.duration._ 22 | import scala.language.postfixOps 23 | 24 | object Timeouts { 25 | 26 | implicit val askTimeout = Timeout(30.seconds) 27 | 28 | val awaitMax = 60.seconds 29 | 30 | // This is used for tests that would keep the startup waiting, and expect a startup timeout anyway. Set it low. 31 | val startupTimeout = Timeout(5.seconds) 32 | } 33 | -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/scala/org/squbs/unicomplex/cubeB/CubeB.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.unicomplex.cubeB 18 | 19 | import org.apache.pekko.actor.{Actor, ActorLogging} 20 | import org.squbs.lifecycle.{GracefulStop, GracefulStopHelper} 21 | import org.squbs.unicomplex.Initialized 22 | import org.squbs.unicomplex.Unicomplex.InitReport 23 | 24 | import scala.util.Try 25 | 26 | class InitCubeActorB extends Actor with ActorLogging with GracefulStopHelper { 27 | 28 | // do initialization 29 | def init: InitReport = { 30 | log.info("initializing") 31 | Try { 32 | // do some tasks 33 | Some("InitCubeActorB") 34 | } 35 | } 36 | 37 | context.parent ! (Initialized(init)) 38 | 39 | def receive = { 40 | case GracefulStop => defaultLeafActorStop 41 | 42 | case other => sender() ! other 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/scala/org/squbs/unicomplex/dummycube/DummyCube.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.unicomplex.dummycube 18 | 19 | import org.apache.pekko.actor.{Props, ActorLogging, Actor} 20 | import org.squbs.unicomplex.{PrependedMsg, Constants, AppendedMsg, EchoMsg} 21 | import org.squbs.lifecycle.{GracefulStop, GracefulStopHelper} 22 | 23 | class AppendActor extends Actor with ActorLogging with GracefulStopHelper { 24 | 25 | def receive = { 26 | case EchoMsg(msg) => sender() ! AppendedMsg(msg + Constants.SUFFIX) 27 | 28 | case GracefulStop => defaultLeafActorStop 29 | } 30 | } 31 | 32 | class DummyPrependActor extends Actor with ActorLogging with GracefulStopHelper { 33 | 34 | def receive = { 35 | 36 | case echoMsg @ EchoMsg(msg) => context.actorOf(Props[ActualPrependActor]()) forward echoMsg 37 | 38 | case GracefulStop => defaultMidActorStop(context.children) 39 | } 40 | } 41 | 42 | private class ActualPrependActor extends Actor with ActorLogging with GracefulStopHelper { 43 | 44 | def receive = { 45 | 46 | case EchoMsg(msg) => sender() ! PrependedMsg(Constants.PREFIX + msg) 47 | 48 | case GracefulStop => defaultLeafActorStop 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/scala/org/squbs/unicomplex/dummyextensions/DummyExtensions.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.unicomplex.dummyextensions 18 | 19 | import org.squbs.lifecycle.ExtensionLifecycle 20 | 21 | trait DummyExtension extends ExtensionLifecycle { 22 | 23 | private[dummyextensions] var _state = "start" 24 | 25 | def state: String 26 | 27 | override def preInit(): Unit = { 28 | _state += "preInit" 29 | } 30 | 31 | override def init(): Unit = { 32 | _state += "init" 33 | } 34 | 35 | override def preCubesInit(): Unit = { 36 | _state += "preCubesInit" 37 | } 38 | 39 | override def postInit(): Unit = { 40 | _state += "postInit" 41 | } 42 | } 43 | 44 | class DummyExtensionA extends DummyExtension { 45 | 46 | def state = "A" + _state 47 | } 48 | 49 | class DummyExtensionB extends DummyExtension { 50 | 51 | def state = "B" + _state 52 | } 53 | 54 | class DummyExtensionC extends DummyExtension { 55 | 56 | def state = "C" + _state 57 | 58 | override def init(): Unit = { 59 | throw new RuntimeException("BadInit", new RuntimeException("BadInitRootCause")) 60 | } 61 | 62 | override def shutdown(): Unit = { 63 | println("DummyExtensionC shutdown...") 64 | throw new RuntimeException("BadShutdown") 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/scala/org/squbs/unicomplex/dummyfailedextensions/DummyFailedExtensions.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.unicomplex.dummyfailedextensions 18 | 19 | import org.squbs.lifecycle.ExtensionLifecycle 20 | 21 | trait DummyFailedExtension extends ExtensionLifecycle { 22 | 23 | private[dummyfailedextensions] var _state = "start" 24 | 25 | def state: String 26 | 27 | override def preInit(): Unit = { 28 | _state += "preInit" 29 | } 30 | 31 | override def init(): Unit = { 32 | _state += "init" 33 | } 34 | 35 | override def postInit(): Unit = { 36 | _state += "postInit" 37 | } 38 | } 39 | class DummyFailedExtensionA extends DummyFailedExtension{ 40 | 41 | def state = "A" + _state 42 | 43 | override def preInit(): Unit = { 44 | throw new IllegalStateException("Test failing preInit()") 45 | } 46 | } 47 | 48 | class DummyFailedExtensionB extends DummyFailedExtension{ 49 | 50 | def state = "B" + _state 51 | 52 | override def postInit(): Unit = { 53 | throw new IllegalStateException("Test failing postInit()") 54 | } 55 | } 56 | 57 | -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/scala/org/squbs/unicomplex/dummyfailedflowsvc1/DummyFailedFlowSvc1.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.squbs.unicomplex.dummyfailedflowsvc1 17 | 18 | import org.apache.pekko.http.scaladsl.model.Uri.Path 19 | import org.apache.pekko.http.scaladsl.model._ 20 | import org.apache.pekko.stream.scaladsl.Flow 21 | import org.squbs.unicomplex.{FlowDefinition, WebContext} 22 | 23 | /** 24 | * A FlowDefinition must be a no-arg constructor. This is intended to test a failure path. 25 | * @param name Some bogus name. 26 | */ 27 | class DummyFailedFlowSvc1(name: String) extends FlowDefinition with WebContext { 28 | 29 | val pingPath = s"/$webContext/ping" 30 | 31 | def flow = Flow[HttpRequest].map { 32 | case HttpRequest(_, Uri(_, _, Path(`pingPath`), _, _), _, _, _) => 33 | HttpResponse(StatusCodes.OK, entity = "pong") 34 | 35 | case _ => HttpResponse(StatusCodes.NotFound, entity = "Path not found!") 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/scala/org/squbs/unicomplex/initblock/InitBlockActor.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.unicomplex.initblock 18 | 19 | import org.squbs.unicomplex.Unicomplex._ 20 | import scala.util.Try 21 | import org.squbs.lifecycle.{GracefulStopHelper, GracefulStop} 22 | import org.apache.pekko.actor.{Actor, ActorLogging} 23 | 24 | class InitBlockActor extends Actor with ActorLogging with GracefulStopHelper{ 25 | 26 | // do initialization 27 | def init: InitReport = { 28 | log.info("initializing") 29 | Try { 30 | // do some tasks 31 | throw new Exception("Init blocked") 32 | } 33 | } 34 | 35 | // never send the the report 36 | //context.parent ! Initialized(init) 37 | 38 | def receive = { 39 | case GracefulStop => defaultLeafActorStop 40 | 41 | case other => sender() ! other 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/scala/org/squbs/unicomplex/initfail/InitFailActor.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.unicomplex.initfail 18 | 19 | import org.squbs.lifecycle.{GracefulStop, GracefulStopHelper} 20 | import org.squbs.unicomplex.Unicomplex._ 21 | import scala.util.Try 22 | import org.squbs.unicomplex.Initialized 23 | import org.apache.pekko.actor.{Actor, ActorLogging} 24 | 25 | class InitFailActor extends Actor with ActorLogging with GracefulStopHelper { 26 | 27 | // do initialization 28 | def init: InitReport = { 29 | log.info("initializing") 30 | Try { 31 | // do some tasks 32 | throw new Exception("Init failed") 33 | } 34 | } 35 | 36 | context.parent ! Initialized(init) 37 | 38 | def receive = { 39 | case GracefulStop => defaultLeafActorStop 40 | 41 | case other => sender() ! other 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/scala/org/squbs/unicomplex/streamSvc/StreamSvc.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.unicomplex.streamSvc 18 | 19 | import org.apache.pekko.http.scaladsl.server._ 20 | import org.squbs.unicomplex.RouteDefinition 21 | 22 | class StreamSvc extends RouteDefinition { 23 | 24 | def route: Route = 25 | extractRequestContext { ctx => 26 | implicit val materializer = ctx.materializer 27 | implicit val ec = ctx.executionContext 28 | 29 | path("file-upload") { 30 | 31 | var chunkCount = 0L 32 | var byteCount = 0L 33 | 34 | val future = ctx.request.entity.dataBytes.runForeach { b => 35 | chunkCount += 1 36 | byteCount += b.length 37 | } 38 | 39 | onSuccess(future) { _ => complete(s"Chunk Count: $chunkCount ByteCount: $byteCount") } 40 | } 41 | } 42 | } 43 | 44 | -------------------------------------------------------------------------------- /squbs-unicomplex/src/test/scala/org/squbs/unicomplex/timeout/ConfigurableInitTimeActor.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.squbs.unicomplex.timeout 17 | 18 | import org.apache.pekko.NotUsed 19 | import org.apache.pekko.http.scaladsl.model.{HttpRequest, HttpResponse, StatusCodes} 20 | import org.apache.pekko.stream.scaladsl.Flow 21 | import org.slf4j.LoggerFactory 22 | import org.squbs.unicomplex.FlowDefinition 23 | 24 | object ConfigurableInitTimeActor { 25 | def log = LoggerFactory.getLogger(classOf[ConfigurableInitTimeActor]) 26 | } 27 | 28 | class ConfigurableInitTimeActor extends FlowDefinition { 29 | import ConfigurableInitTimeActor.log 30 | 31 | override def flow: Flow[HttpRequest, HttpResponse, NotUsed] = { 32 | val system = this.context.system 33 | 34 | val initTime = Option(system.settings.config.getDuration("squbs.test.actor-init-time")) 35 | .get 36 | 37 | log.info(s"I'll be ready to go in $initTime") 38 | Thread.sleep(initTime.toMillis) 39 | log.info("Ready to work!") 40 | 41 | Flow[HttpRequest].map { r => HttpResponse(StatusCodes.OK, entity = "Hello") } 42 | } 43 | } 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /squbs-zkcluster/.gitignore: -------------------------------------------------------------------------------- 1 | zookeeper/ 2 | -------------------------------------------------------------------------------- /squbs-zkcluster/build.sbt: -------------------------------------------------------------------------------- 1 | import Versions._ 2 | 3 | name := "squbs-zkcluster" 4 | 5 | libraryDependencies ++= Seq( 6 | "org.scala-lang.modules" %% "scala-collection-compat" % scalaCompatV, 7 | "org.apache.pekko" %% "pekko-actor" % pekkoV, 8 | "org.apache.pekko" %% "pekko-remote" % pekkoV, 9 | "org.apache.pekko" %% "pekko-slf4j" % pekkoV, 10 | "org.apache.curator" % "curator-recipes" % curatorV, 11 | "org.apache.curator" % "curator-framework" % curatorV exclude("org.jboss.netty", "netty"), 12 | "io.altoo" %% "pekko-kryo-serialization" % akkaKryoV, 13 | "com.typesafe.scala-logging" %% "scala-logging" % scalaLoggingV, 14 | "org.apache.pekko" %% "pekko-testkit" % pekkoV % Test, 15 | "org.scalatest" %% "scalatest" % scalatestV % Test, 16 | "org.scalatestplus" %% "mockito-3-4" % scalatestplusV % Test, 17 | "org.mockito" % "mockito-core" % mockitoV % Test, 18 | "org.apache.curator" % "curator-test" % curatorV % Test, 19 | "com.vladsch.flexmark" % "flexmark-all" % flexmarkV % Test, 20 | "ch.qos.logback" % "logback-classic" % logbackInTestV % Test, 21 | "commons-io" % "commons-io" % "2.6" % Test 22 | ) 23 | 24 | Test / testOptions += Tests.Argument(TestFrameworks.ScalaTest, "-h", "report/squbs-zkcluster") 25 | 26 | parallelExecution := false 27 | 28 | cleanFiles += baseDirectory.value / "zookeeper" 29 | 30 | updateOptions := updateOptions.value.withCachedResolution(true) 31 | -------------------------------------------------------------------------------- /squbs-zkcluster/src/main/resources/build.properties: -------------------------------------------------------------------------------- 1 | custom=true 2 | -------------------------------------------------------------------------------- /squbs-zkcluster/src/main/resources/reference.conf: -------------------------------------------------------------------------------- 1 | pekko { 2 | actor { 3 | provider = "org.apache.pekko.remote.RemoteActorRefProvider" 4 | serializers { 5 | kryo = "io.altoo.serialization.kryo.pekko.PekkoKryoSerializer" 6 | } 7 | serialization-bindings { 8 | "org.squbs.cluster.ZkMessages" = kryo 9 | } 10 | } 11 | } 12 | 13 | ZkMembershipMonitor-dispatcher { 14 | type = PinnedDispatcher 15 | executor = "thread-pool-executor" 16 | } -------------------------------------------------------------------------------- /squbs-zkcluster/src/main/scala/org/squbs/cluster/RemoteGuardian.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.cluster 18 | 19 | import org.apache.pekko.actor._ 20 | import org.apache.pekko.remote.QuarantinedEvent 21 | 22 | /** 23 | * Created by zhuwang on 2/8/15. 24 | */ 25 | 26 | /** 27 | * The RemoteGuardian subscribe to QuarantinedEvent 28 | * If a QuarantinedEvent arrives, it will close the connection to Zookeeper and exit the JVM using code 99 29 | * External monitor tool like JSW can be configured to restart the app according to the exist code 30 | */ 31 | @deprecated("zkcluster is deprecated in lieu of maturity of Pekko cluster and more modern cluster coordinators", 32 | since = "0.15.0") 33 | class RemoteGuardian extends Actor with ActorLogging { 34 | 35 | val zkCluster= ZkCluster(context.system) 36 | 37 | override def preStart(): Unit = context.system.eventStream.subscribe(self, classOf[QuarantinedEvent]) 38 | 39 | val EXIT_CODE = 99 40 | 41 | override def receive: Receive = { 42 | case QuarantinedEvent(remote, uid) => // first QuarantinedEvent arrived 43 | log.error("[RemoteGuardian] get Quarantined event for remote {} uid {}. Performing a suicide ...", remote, uid) 44 | zkCluster.addShutdownListener((_) => context.system.terminate()) 45 | zkCluster.addShutdownListener((_) => System.exit(EXIT_CODE)) 46 | zkCluster.zkClusterActor ! PoisonPill 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /squbs-zkcluster/src/test/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /squbs-zkcluster/src/test/resources/reference.conf: -------------------------------------------------------------------------------- 1 | 2 | ZkMembershipMonitor-dispatcher { 3 | type = PinnedDispatcher 4 | executor = "thread-pool-executor" 5 | } 6 | 7 | pekko { 8 | loggers = ["org.apache.pekko.event.slf4j.Slf4jLogger", "org.apache.pekko.event.Logging$DefaultLogger"] 9 | loglevel = ERROR 10 | log-dead-letters-during-shutdown = off 11 | } -------------------------------------------------------------------------------- /squbs-zkcluster/src/test/resources/zoo.cfg: -------------------------------------------------------------------------------- 1 | # The number of milliseconds of each tick 2 | tickTime=1000 3 | # The number of ticks that the initial 4 | # synchronization phase can take 5 | initLimit=600 6 | # The number of ticks that can pass between 7 | # sending a request and getting an acknowledgement 8 | syncLimit=30 9 | # the directory where the snapshot is stored. 10 | # do not use /tmp for storage, /tmp here is just 11 | # example sakes. 12 | dataDir=zookeeper 13 | # the port at which the clients will connect 14 | clientPort=8085 15 | # the maximum number of client connections. 16 | # increase this if you need to handle more clients 17 | maxClientCnxns=1024 18 | # 19 | # Be sure to read the maintenance section of the 20 | # administrator guide before turning on autopurge. 21 | # 22 | # http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance 23 | # 24 | # The number of snapshots to retain in dataDir 25 | #autopurge.snapRetainCount=3 26 | # Purge task interval in hours 27 | # Set to "0" to disable auto purge feature 28 | #autopurge.purgeInterval=1 -------------------------------------------------------------------------------- /squbs-zkcluster/src/test/scala/org/squbs/cluster/SessionExpirationTest.scala: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 PayPal 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of 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, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.squbs.cluster 18 | 19 | import org.apache.curator.test.KillSession 20 | import org.squbs.cluster.test.{ZkClusterMultiActorSystemTestKit, ZkClusterTestHelper} 21 | 22 | import scala.concurrent.duration._ 23 | import scala.language.postfixOps 24 | 25 | class SessionExpirationTest extends ZkClusterMultiActorSystemTestKit("SessionExpirationTest") 26 | with ZkClusterTestHelper { 27 | 28 | override val timeout: FiniteDuration = 60 seconds 29 | override val clusterSize: Int = 1 30 | 31 | 32 | "ZkCluster" should "response to session expiration" in { 33 | val cluster = zkClusterExts.values.head 34 | 35 | cluster.zkClusterActor ! ZkQueryLeadership 36 | val leader = expectMsgType[ZkLeadership](timeout) 37 | 38 | cluster.zkClusterActor ! ZkMonitorClient 39 | KillSession.kill(cluster.curatorFwkWithNs().getZookeeperClient.getZooKeeper) 40 | expectMsgType[ZkClientUpdated](timeout).zkClient 41 | 42 | cluster.zkClusterActor ! ZkQueryLeadership 43 | expectMsgType[ZkLeadership](timeout) should be (leader) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /version.sbt: -------------------------------------------------------------------------------- 1 | ThisBuild / version := "1.0.2-SNAPSHOT" 2 | --------------------------------------------------------------------------------