From 5ef8625fb7e26e6b3e901f3b03fc42f730dfaec9 Mon Sep 17 00:00:00 2001
From: seeflood <349895584@qq.com>
Date: Mon, 6 Dec 2021 17:52:18 +0800
Subject: [PATCH 1/2] move code into new repo
---
.gitignore | 24 +
LICENSE | 201 -
README-zh.md | 155 +
README.md | 98 +
examples/pom.xml | 60 +
.../io/mosn/layotto/examples/file/File.java | 133 +
.../layotto/examples/helloworld/Hello.java | 34 +
.../examples/pubsub/publisher/Publisher.java | 31 +
.../pubsub/subscriber/Subscriber.java | 56 +
.../pubsub/subscriber/impl/EventListener.java | 22 +
.../pubsub/subscriber/impl/RawSubscriber.java | 87 +
.../layotto/examples/state/RedisCRUD.java | 131 +
img.png | Bin 0 -> 31279 bytes
pom.xml | 263 +
sdk-reactor/pom.xml | 53 +
.../mosn/layotto/v1/client/package-info.java | 18 +
.../reactor/AbstractLayottoReactorClient.java | 300 +
.../client/reactor/LayottoReactorClient.java | 171 +
.../reactor/LayottoReactorClientBuilder.java | 148 +
.../reactor/LayottoReactorClientGrpc.java | 624 +
.../layotto/v1/config/BooleanProperty.java | 36 +
.../layotto/v1/config/GenericProperty.java | 41 +
.../layotto/v1/config/IntegerProperty.java | 36 +
.../io/mosn/layotto/v1/config/Properties.java | 89 +
.../io/mosn/layotto/v1/config/Property.java | 109 +
.../layotto/v1/config/StringProperty.java | 36 +
.../io/mosn/layotto/v1/domain/CloudEvent.java | 306 +
.../layotto/v1/exceptions/LayottoError.java | 83 +
.../v1/exceptions/LayottoException.java | 203 +
.../serializer/DefaultObjectSerializer.java | 49 +
.../serializer/LayottoObjectSerializer.java | 52 +
.../v1/serializer/ObjectSerializer.java | 205 +
.../io/mosn/layotto/v1/utils/GrpcWrapper.java | 77 +
.../mosn/layotto/v1/utils/NetworkUtils.java | 87 +
.../io/mosn/layotto/v1/value/Headers.java | 31 +
.../layotto/v1/value/LayottoApiProtocol.java | 23 +
.../sdk/reactor/v1/CoreCloudRuntimes.java | 32 +
.../sdk/reactor/v1/EnhancedCloudRuntimes.java | 24 +
.../main/java/spec/sdk/reactor/v1/README.md | 1 +
.../v1/client/CloudRuntimesClient.java | 40 +
.../v1/domain/core/ConfigurationRuntimes.java | 69 +
.../v1/domain/core/InvocationRuntimes.java | 184 +
.../v1/domain/core/PubSubRuntimes.java | 55 +
.../reactor/v1/domain/core/StateRuntimes.java | 229 +
.../core/configuration/ConfigurationItem.java | 94 +
.../ConfigurationRequestItem.java | 98 +
.../ConfigurationRequestItemBuilder.java | 77 +
.../SaveConfigurationRequest.java | 72 +
.../configuration/SubConfigurationResp.java | 59 +
.../domain/core/invocation/HttpExtension.java | 162 +
.../core/invocation/InvokeMethodRequest.java | 83 +
.../v1/domain/core/invocation/Metadata.java | 28 +
.../core/pubsub/PublishEventRequest.java | 78 +
.../domain/core/state/DeleteStateRequest.java | 74 +
.../state/ExecuteStateTransactionRequest.java | 63 +
.../core/state/GetBulkStateRequest.java | 70 +
.../v1/domain/core/state/GetStateRequest.java | 63 +
.../domain/core/state/SaveStateRequest.java | 51 +
.../reactor/v1/domain/core/state/State.java | 276 +
.../v1/domain/core/state/StateOptions.java | 101 +
.../state/TransactionalStateOperation.java | 80 +
.../core/state/TransactionalStateRequest.java | 51 +
.../v1/domain/enhanced/MetricsRuntimes.java | 24 +
.../sdk/reactor/v1/domain/package-info.java | 19 +
.../spec/sdk/reactor/v1/utils/TypeRef.java | 162 +
sdk/pom.xml | 106 +
.../layotto/v1/AbstractRuntimeClient.java | 300 +
.../mosn/layotto/v1/RuntimeClientBuilder.java | 198 +
.../io/mosn/layotto/v1/RuntimeClientGrpc.java | 993 +
.../io/mosn/layotto/v1/RuntimeServerGrpc.java | 105 +
.../v1/callback/GrpcAppCallbackImpl.java | 87 +
.../v1/callback/component/Component.java | 20 +
.../callback/component/pubsub/Subscriber.java | 32 +
.../component/pubsub/SubscriberRegistry.java | 26 +
.../pubsub/SubscriberRegistryImpl.java | 55 +
.../layotto/v1/config/RuntimeProperties.java | 46 +
.../mosn/layotto/v1/domain/ApiProtocol.java | 25 +
.../v1/exceptions/RuntimeClientException.java | 95 +
.../layotto/v1/exceptions/RuntimeError.java | 47 +
.../layotto/v1/grpc/ExceptionHandler.java | 74 +
.../layotto/v1/grpc/GrpcRuntimeClient.java | 34 +
.../mosn/layotto/v1/grpc/PubsubConverter.java | 112 +
.../v1/grpc/stub/PooledStubManager.java | 135 +
.../io/mosn/layotto/v1/grpc/stub/RRPool.java | 68 +
.../v1/grpc/stub/SingleStubManager.java | 77 +
.../layotto/v1/grpc/stub/StubCreator.java | 27 +
.../layotto/v1/grpc/stub/StubManager.java | 33 +
.../v1/serializer/AbstractSerializer.java | 59 +
.../layotto/v1/serializer/JSONSerializer.java | 46 +
.../v1/serializer/ObjectSerializer.java | 50 +
.../sdk/runtime/v1/client/RuntimeClient.java | 37 +
.../v1/domain/ConfigurationRuntime.java | 18 +
.../sdk/runtime/v1/domain/FileRuntime.java | 66 +
.../sdk/runtime/v1/domain/HelloRuntime.java | 22 +
.../runtime/v1/domain/InvocationRuntime.java | 37 +
.../sdk/runtime/v1/domain/LockRuntime.java | 18 +
.../sdk/runtime/v1/domain/PubSubRuntime.java | 52 +
.../runtime/v1/domain/SequencerRuntime.java | 18 +
.../sdk/runtime/v1/domain/StateRuntime.java | 196 +
.../v1/domain/file/DelFileRequest.java | 56 +
.../v1/domain/file/DelFileResponse.java | 18 +
.../sdk/runtime/v1/domain/file/FileInfo.java | 69 +
.../v1/domain/file/GetFileRequest.java | 55 +
.../v1/domain/file/GetFileResponse.java | 34 +
.../v1/domain/file/GetMetaRequest.java | 55 +
.../v1/domain/file/GetMeteResponse.java | 53 +
.../v1/domain/file/ListFileRequest.java | 73 +
.../v1/domain/file/ListFileResponse.java | 52 +
.../v1/domain/file/PutFileRequest.java | 66 +
.../v1/domain/file/PutFileResponse.java | 18 +
.../v1/domain/invocation/InvokeResponse.java | 56 +
.../v1/domain/lock/TryLockRequest.java | 22 +
.../v1/domain/lock/TryLockResponse.java | 19 +
.../runtime/v1/domain/lock/UnlockRequest.java | 21 +
.../v1/domain/lock/UnlockResponse.java | 31 +
.../v1/domain/pubsub/PublishEventRequest.java | 125 +
.../v1/domain/pubsub/TopicEventRequest.java | 214 +
.../v1/domain/pubsub/TopicEventResponse.java | 37 +
.../pubsub/TopicEventResponseStatus.java | 40 +
.../v1/domain/pubsub/TopicSubscription.java | 82 +
.../v1/domain/state/DeleteStateRequest.java | 110 +
.../state/ExecuteStateTransactionRequest.java | 91 +
.../v1/domain/state/GetBulkStateRequest.java | 98 +
.../v1/domain/state/GetStateRequest.java | 90 +
.../v1/domain/state/SaveStateRequest.java | 53 +
.../sdk/runtime/v1/domain/state/State.java | 207 +
.../runtime/v1/domain/state/StateOptions.java | 76 +
.../state/TransactionalStateOperation.java | 52 +
.../state/TransactionalStateRequest.java | 61 +
.../java/io/mosn/layotto/v1/FileTest.java | 360 +
.../layotto/v1/FileTestWithRealServer.java | 366 +
.../io/mosn/layotto/v1/PublishEventTest.java | 69 +
.../v1/PublishEventTestWithRealServer.java | 74 +
.../layotto/v1/RuntimeClientBuilderTest.java | 62 +
.../java/io/mosn/layotto/v1/SayHelloTest.java | 84 +
.../v1/SayHelloTestWithRealServer.java | 73 +
.../java/io/mosn/layotto/v1/StateTest.java | 221 +
.../layotto/v1/StateTestWithRealServer.java | 227 +
.../io/mosn/layotto/v1/SubscriberTest.java | 141 +
.../v1/SubscriberTestWithRealServer.java | 139 +
.../mosn/layotto/v1/grpc/stub/RRPoolTest.java | 52 +
.../mosn/layotto/v1/mock/MyFileService.java | 143 +
.../mosn/layotto/v1/mock/MyHelloService.java | 32 +
.../layotto/v1/mock/MyPublishService.java | 40 +
.../mosn/layotto/v1/mock/MyStateService.java | 116 +
.../io/mosn/layotto/v1/mock/MySubscriber.java | 62 +
.../v1/serializer/JSONSerializerTest.java | 464 +
spec/pom.xml | 101 +
.../proto/runtime/v1/AppCallbackGrpc.java | 411 +
.../proto/runtime/v1/AppCallbackProto.java | 5202 ++
.../spec/proto/runtime/v1/RuntimeGrpc.java | 2048 +
.../spec/proto/runtime/v1/RuntimeProto.java | 53700 ++++++++++++++++
tools/codestyle/HEADER | 13 +
tools/codestyle/formatter.xml | 279 +
154 files changed, 76117 insertions(+), 201 deletions(-)
create mode 100644 .gitignore
delete mode 100644 LICENSE
create mode 100644 README-zh.md
create mode 100644 README.md
create mode 100644 examples/pom.xml
create mode 100644 examples/src/test/java/io/mosn/layotto/examples/file/File.java
create mode 100644 examples/src/test/java/io/mosn/layotto/examples/helloworld/Hello.java
create mode 100644 examples/src/test/java/io/mosn/layotto/examples/pubsub/publisher/Publisher.java
create mode 100644 examples/src/test/java/io/mosn/layotto/examples/pubsub/subscriber/Subscriber.java
create mode 100644 examples/src/test/java/io/mosn/layotto/examples/pubsub/subscriber/impl/EventListener.java
create mode 100644 examples/src/test/java/io/mosn/layotto/examples/pubsub/subscriber/impl/RawSubscriber.java
create mode 100644 examples/src/test/java/io/mosn/layotto/examples/state/RedisCRUD.java
create mode 100644 img.png
create mode 100644 pom.xml
create mode 100644 sdk-reactor/pom.xml
create mode 100644 sdk-reactor/src/main/java/io/mosn/layotto/v1/client/package-info.java
create mode 100644 sdk-reactor/src/main/java/io/mosn/layotto/v1/client/reactor/AbstractLayottoReactorClient.java
create mode 100644 sdk-reactor/src/main/java/io/mosn/layotto/v1/client/reactor/LayottoReactorClient.java
create mode 100644 sdk-reactor/src/main/java/io/mosn/layotto/v1/client/reactor/LayottoReactorClientBuilder.java
create mode 100644 sdk-reactor/src/main/java/io/mosn/layotto/v1/client/reactor/LayottoReactorClientGrpc.java
create mode 100644 sdk-reactor/src/main/java/io/mosn/layotto/v1/config/BooleanProperty.java
create mode 100644 sdk-reactor/src/main/java/io/mosn/layotto/v1/config/GenericProperty.java
create mode 100644 sdk-reactor/src/main/java/io/mosn/layotto/v1/config/IntegerProperty.java
create mode 100644 sdk-reactor/src/main/java/io/mosn/layotto/v1/config/Properties.java
create mode 100644 sdk-reactor/src/main/java/io/mosn/layotto/v1/config/Property.java
create mode 100644 sdk-reactor/src/main/java/io/mosn/layotto/v1/config/StringProperty.java
create mode 100644 sdk-reactor/src/main/java/io/mosn/layotto/v1/domain/CloudEvent.java
create mode 100644 sdk-reactor/src/main/java/io/mosn/layotto/v1/exceptions/LayottoError.java
create mode 100644 sdk-reactor/src/main/java/io/mosn/layotto/v1/exceptions/LayottoException.java
create mode 100644 sdk-reactor/src/main/java/io/mosn/layotto/v1/serializer/DefaultObjectSerializer.java
create mode 100644 sdk-reactor/src/main/java/io/mosn/layotto/v1/serializer/LayottoObjectSerializer.java
create mode 100644 sdk-reactor/src/main/java/io/mosn/layotto/v1/serializer/ObjectSerializer.java
create mode 100644 sdk-reactor/src/main/java/io/mosn/layotto/v1/utils/GrpcWrapper.java
create mode 100644 sdk-reactor/src/main/java/io/mosn/layotto/v1/utils/NetworkUtils.java
create mode 100644 sdk-reactor/src/main/java/io/mosn/layotto/v1/value/Headers.java
create mode 100644 sdk-reactor/src/main/java/io/mosn/layotto/v1/value/LayottoApiProtocol.java
create mode 100644 sdk-reactor/src/main/java/spec/sdk/reactor/v1/CoreCloudRuntimes.java
create mode 100644 sdk-reactor/src/main/java/spec/sdk/reactor/v1/EnhancedCloudRuntimes.java
create mode 100644 sdk-reactor/src/main/java/spec/sdk/reactor/v1/README.md
create mode 100644 sdk-reactor/src/main/java/spec/sdk/reactor/v1/client/CloudRuntimesClient.java
create mode 100644 sdk-reactor/src/main/java/spec/sdk/reactor/v1/domain/core/ConfigurationRuntimes.java
create mode 100644 sdk-reactor/src/main/java/spec/sdk/reactor/v1/domain/core/InvocationRuntimes.java
create mode 100644 sdk-reactor/src/main/java/spec/sdk/reactor/v1/domain/core/PubSubRuntimes.java
create mode 100644 sdk-reactor/src/main/java/spec/sdk/reactor/v1/domain/core/StateRuntimes.java
create mode 100644 sdk-reactor/src/main/java/spec/sdk/reactor/v1/domain/core/configuration/ConfigurationItem.java
create mode 100644 sdk-reactor/src/main/java/spec/sdk/reactor/v1/domain/core/configuration/ConfigurationRequestItem.java
create mode 100644 sdk-reactor/src/main/java/spec/sdk/reactor/v1/domain/core/configuration/ConfigurationRequestItemBuilder.java
create mode 100644 sdk-reactor/src/main/java/spec/sdk/reactor/v1/domain/core/configuration/SaveConfigurationRequest.java
create mode 100644 sdk-reactor/src/main/java/spec/sdk/reactor/v1/domain/core/configuration/SubConfigurationResp.java
create mode 100644 sdk-reactor/src/main/java/spec/sdk/reactor/v1/domain/core/invocation/HttpExtension.java
create mode 100644 sdk-reactor/src/main/java/spec/sdk/reactor/v1/domain/core/invocation/InvokeMethodRequest.java
create mode 100644 sdk-reactor/src/main/java/spec/sdk/reactor/v1/domain/core/invocation/Metadata.java
create mode 100644 sdk-reactor/src/main/java/spec/sdk/reactor/v1/domain/core/pubsub/PublishEventRequest.java
create mode 100644 sdk-reactor/src/main/java/spec/sdk/reactor/v1/domain/core/state/DeleteStateRequest.java
create mode 100644 sdk-reactor/src/main/java/spec/sdk/reactor/v1/domain/core/state/ExecuteStateTransactionRequest.java
create mode 100644 sdk-reactor/src/main/java/spec/sdk/reactor/v1/domain/core/state/GetBulkStateRequest.java
create mode 100644 sdk-reactor/src/main/java/spec/sdk/reactor/v1/domain/core/state/GetStateRequest.java
create mode 100644 sdk-reactor/src/main/java/spec/sdk/reactor/v1/domain/core/state/SaveStateRequest.java
create mode 100644 sdk-reactor/src/main/java/spec/sdk/reactor/v1/domain/core/state/State.java
create mode 100644 sdk-reactor/src/main/java/spec/sdk/reactor/v1/domain/core/state/StateOptions.java
create mode 100644 sdk-reactor/src/main/java/spec/sdk/reactor/v1/domain/core/state/TransactionalStateOperation.java
create mode 100644 sdk-reactor/src/main/java/spec/sdk/reactor/v1/domain/core/state/TransactionalStateRequest.java
create mode 100644 sdk-reactor/src/main/java/spec/sdk/reactor/v1/domain/enhanced/MetricsRuntimes.java
create mode 100644 sdk-reactor/src/main/java/spec/sdk/reactor/v1/domain/package-info.java
create mode 100644 sdk-reactor/src/main/java/spec/sdk/reactor/v1/utils/TypeRef.java
create mode 100644 sdk/pom.xml
create mode 100644 sdk/src/main/java/io/mosn/layotto/v1/AbstractRuntimeClient.java
create mode 100644 sdk/src/main/java/io/mosn/layotto/v1/RuntimeClientBuilder.java
create mode 100644 sdk/src/main/java/io/mosn/layotto/v1/RuntimeClientGrpc.java
create mode 100644 sdk/src/main/java/io/mosn/layotto/v1/RuntimeServerGrpc.java
create mode 100644 sdk/src/main/java/io/mosn/layotto/v1/callback/GrpcAppCallbackImpl.java
create mode 100644 sdk/src/main/java/io/mosn/layotto/v1/callback/component/Component.java
create mode 100644 sdk/src/main/java/io/mosn/layotto/v1/callback/component/pubsub/Subscriber.java
create mode 100644 sdk/src/main/java/io/mosn/layotto/v1/callback/component/pubsub/SubscriberRegistry.java
create mode 100644 sdk/src/main/java/io/mosn/layotto/v1/callback/component/pubsub/SubscriberRegistryImpl.java
create mode 100644 sdk/src/main/java/io/mosn/layotto/v1/config/RuntimeProperties.java
create mode 100644 sdk/src/main/java/io/mosn/layotto/v1/domain/ApiProtocol.java
create mode 100644 sdk/src/main/java/io/mosn/layotto/v1/exceptions/RuntimeClientException.java
create mode 100644 sdk/src/main/java/io/mosn/layotto/v1/exceptions/RuntimeError.java
create mode 100644 sdk/src/main/java/io/mosn/layotto/v1/grpc/ExceptionHandler.java
create mode 100644 sdk/src/main/java/io/mosn/layotto/v1/grpc/GrpcRuntimeClient.java
create mode 100644 sdk/src/main/java/io/mosn/layotto/v1/grpc/PubsubConverter.java
create mode 100644 sdk/src/main/java/io/mosn/layotto/v1/grpc/stub/PooledStubManager.java
create mode 100644 sdk/src/main/java/io/mosn/layotto/v1/grpc/stub/RRPool.java
create mode 100644 sdk/src/main/java/io/mosn/layotto/v1/grpc/stub/SingleStubManager.java
create mode 100644 sdk/src/main/java/io/mosn/layotto/v1/grpc/stub/StubCreator.java
create mode 100644 sdk/src/main/java/io/mosn/layotto/v1/grpc/stub/StubManager.java
create mode 100644 sdk/src/main/java/io/mosn/layotto/v1/serializer/AbstractSerializer.java
create mode 100644 sdk/src/main/java/io/mosn/layotto/v1/serializer/JSONSerializer.java
create mode 100644 sdk/src/main/java/io/mosn/layotto/v1/serializer/ObjectSerializer.java
create mode 100644 sdk/src/main/java/spec/sdk/runtime/v1/client/RuntimeClient.java
create mode 100644 sdk/src/main/java/spec/sdk/runtime/v1/domain/ConfigurationRuntime.java
create mode 100644 sdk/src/main/java/spec/sdk/runtime/v1/domain/FileRuntime.java
create mode 100644 sdk/src/main/java/spec/sdk/runtime/v1/domain/HelloRuntime.java
create mode 100644 sdk/src/main/java/spec/sdk/runtime/v1/domain/InvocationRuntime.java
create mode 100644 sdk/src/main/java/spec/sdk/runtime/v1/domain/LockRuntime.java
create mode 100644 sdk/src/main/java/spec/sdk/runtime/v1/domain/PubSubRuntime.java
create mode 100644 sdk/src/main/java/spec/sdk/runtime/v1/domain/SequencerRuntime.java
create mode 100644 sdk/src/main/java/spec/sdk/runtime/v1/domain/StateRuntime.java
create mode 100644 sdk/src/main/java/spec/sdk/runtime/v1/domain/file/DelFileRequest.java
create mode 100644 sdk/src/main/java/spec/sdk/runtime/v1/domain/file/DelFileResponse.java
create mode 100644 sdk/src/main/java/spec/sdk/runtime/v1/domain/file/FileInfo.java
create mode 100644 sdk/src/main/java/spec/sdk/runtime/v1/domain/file/GetFileRequest.java
create mode 100644 sdk/src/main/java/spec/sdk/runtime/v1/domain/file/GetFileResponse.java
create mode 100644 sdk/src/main/java/spec/sdk/runtime/v1/domain/file/GetMetaRequest.java
create mode 100644 sdk/src/main/java/spec/sdk/runtime/v1/domain/file/GetMeteResponse.java
create mode 100644 sdk/src/main/java/spec/sdk/runtime/v1/domain/file/ListFileRequest.java
create mode 100644 sdk/src/main/java/spec/sdk/runtime/v1/domain/file/ListFileResponse.java
create mode 100644 sdk/src/main/java/spec/sdk/runtime/v1/domain/file/PutFileRequest.java
create mode 100644 sdk/src/main/java/spec/sdk/runtime/v1/domain/file/PutFileResponse.java
create mode 100644 sdk/src/main/java/spec/sdk/runtime/v1/domain/invocation/InvokeResponse.java
create mode 100644 sdk/src/main/java/spec/sdk/runtime/v1/domain/lock/TryLockRequest.java
create mode 100644 sdk/src/main/java/spec/sdk/runtime/v1/domain/lock/TryLockResponse.java
create mode 100644 sdk/src/main/java/spec/sdk/runtime/v1/domain/lock/UnlockRequest.java
create mode 100644 sdk/src/main/java/spec/sdk/runtime/v1/domain/lock/UnlockResponse.java
create mode 100644 sdk/src/main/java/spec/sdk/runtime/v1/domain/pubsub/PublishEventRequest.java
create mode 100644 sdk/src/main/java/spec/sdk/runtime/v1/domain/pubsub/TopicEventRequest.java
create mode 100644 sdk/src/main/java/spec/sdk/runtime/v1/domain/pubsub/TopicEventResponse.java
create mode 100644 sdk/src/main/java/spec/sdk/runtime/v1/domain/pubsub/TopicEventResponseStatus.java
create mode 100644 sdk/src/main/java/spec/sdk/runtime/v1/domain/pubsub/TopicSubscription.java
create mode 100644 sdk/src/main/java/spec/sdk/runtime/v1/domain/state/DeleteStateRequest.java
create mode 100644 sdk/src/main/java/spec/sdk/runtime/v1/domain/state/ExecuteStateTransactionRequest.java
create mode 100644 sdk/src/main/java/spec/sdk/runtime/v1/domain/state/GetBulkStateRequest.java
create mode 100644 sdk/src/main/java/spec/sdk/runtime/v1/domain/state/GetStateRequest.java
create mode 100644 sdk/src/main/java/spec/sdk/runtime/v1/domain/state/SaveStateRequest.java
create mode 100644 sdk/src/main/java/spec/sdk/runtime/v1/domain/state/State.java
create mode 100644 sdk/src/main/java/spec/sdk/runtime/v1/domain/state/StateOptions.java
create mode 100644 sdk/src/main/java/spec/sdk/runtime/v1/domain/state/TransactionalStateOperation.java
create mode 100644 sdk/src/main/java/spec/sdk/runtime/v1/domain/state/TransactionalStateRequest.java
create mode 100644 sdk/src/test/java/io/mosn/layotto/v1/FileTest.java
create mode 100644 sdk/src/test/java/io/mosn/layotto/v1/FileTestWithRealServer.java
create mode 100644 sdk/src/test/java/io/mosn/layotto/v1/PublishEventTest.java
create mode 100644 sdk/src/test/java/io/mosn/layotto/v1/PublishEventTestWithRealServer.java
create mode 100644 sdk/src/test/java/io/mosn/layotto/v1/RuntimeClientBuilderTest.java
create mode 100644 sdk/src/test/java/io/mosn/layotto/v1/SayHelloTest.java
create mode 100644 sdk/src/test/java/io/mosn/layotto/v1/SayHelloTestWithRealServer.java
create mode 100644 sdk/src/test/java/io/mosn/layotto/v1/StateTest.java
create mode 100644 sdk/src/test/java/io/mosn/layotto/v1/StateTestWithRealServer.java
create mode 100644 sdk/src/test/java/io/mosn/layotto/v1/SubscriberTest.java
create mode 100644 sdk/src/test/java/io/mosn/layotto/v1/SubscriberTestWithRealServer.java
create mode 100644 sdk/src/test/java/io/mosn/layotto/v1/grpc/stub/RRPoolTest.java
create mode 100644 sdk/src/test/java/io/mosn/layotto/v1/mock/MyFileService.java
create mode 100644 sdk/src/test/java/io/mosn/layotto/v1/mock/MyHelloService.java
create mode 100644 sdk/src/test/java/io/mosn/layotto/v1/mock/MyPublishService.java
create mode 100644 sdk/src/test/java/io/mosn/layotto/v1/mock/MyStateService.java
create mode 100644 sdk/src/test/java/io/mosn/layotto/v1/mock/MySubscriber.java
create mode 100644 sdk/src/test/java/io/mosn/layotto/v1/serializer/JSONSerializerTest.java
create mode 100644 spec/pom.xml
create mode 100644 spec/src/main/java/spec/proto/runtime/v1/AppCallbackGrpc.java
create mode 100644 spec/src/main/java/spec/proto/runtime/v1/AppCallbackProto.java
create mode 100644 spec/src/main/java/spec/proto/runtime/v1/RuntimeGrpc.java
create mode 100644 spec/src/main/java/spec/proto/runtime/v1/RuntimeProto.java
create mode 100644 tools/codestyle/HEADER
create mode 100644 tools/codestyle/formatter.xml
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..72806b4
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,24 @@
+# Maven (examples)
+target
+dependency-reduced-pom.xml
+
+# IntelliJ IDEA
+.idea
+*.iml
+
+# Eclipse
+.classpath
+.project
+.settings
+bin
+
+# OS X
+.DS_Store
+
+# log
+logs/
+*.log
+
+#protobuf
+example/build/*
+test/test-integration/build/*
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index 261eeb9..0000000
--- a/LICENSE
+++ /dev/null
@@ -1,201 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
diff --git a/README-zh.md b/README-zh.md
new file mode 100644
index 0000000..1f72620
--- /dev/null
+++ b/README-zh.md
@@ -0,0 +1,155 @@
+## 如何使用java sdk
+### 1. import sdk
+对于 Maven 项目,将以下配置添加进 `pom.xml` 文件:
+```xml
+
+ ...
+
+ ...
+
+ io.mosn.layotto
+ runtime-sdk-parent
+ 1.0.0
+
+ ...
+
+ ...
+
+```
+
+### 2. 运行 examples 示例
+可以本地部署redis和Layotto,然后运行java应用示例,通过java sdk调Layotto,Layotto转发给redis
+
+#### 第一步:部署redis
+
+1. 取最新版的 Redis 镜像。
+ 这里我们拉取官方的最新版本的镜像:
+
+```shell
+docker pull redis:latest
+```
+
+2. 查看本地镜像
+ 使用以下命令来查看是否已安装了 redis:
+
+```shell
+docker images
+```
+
+3. 运行容器
+
+安装完成后,我们可以使用以下命令来运行 redis 容器:
+
+```shell
+docker run -itd --name redis-test -p 6380:6379 redis
+```
+
+参数说明:
+
+-p 6380:6379:映射容器服务的 6379 端口到宿主机的 6380 端口。外部可以直接通过宿主机ip:6380 访问到 Redis 的服务。
+
+#### 第二步:构建并运行Layotto
+
+clone仓库到本地:
+
+```sh
+git clone https://github.com/mosn/layotto.git
+```
+
+构建并运行Layotto:
+
+```bash
+# make sure you replace this` ${projectpath}` with your own project path.
+cd ${projectpath}/cmd/layotto
+go build
+./layotto start -c ../../configs/config_redis.json
+```
+
+构建java-sdk [Maven](https://maven.apache.org/install.html) (Apache Maven version 3.x) 项目:
+
+```sh
+# make sure you replace this` ${projectpath}` with your own project path.
+cd ${projectpath}/sdk/java-sdk
+mvn clean install
+```
+
+#### 第三步:运行java sdk示例
+通过以下Examples示例来了解如何使用SDK:
+* [Hello world](./examples/src/test/java/io/mosn/layotto/examples/helloworld)
+* [State management](./examples/src/test/java/io/mosn/layotto/examples/state)
+* [Pubsub API](./examples/src/test/java/io/mosn/layotto/examples/pubsub)
+* [File API](./examples/src/test/java/io/mosn/layotto/examples/file)
+
+## java sdk开发指南
+### java sdk职责
+1. sdk负责对Layotto的grpc API进行封装、不应该有任何中间件的定制逻辑,比如不应该出现redis、rocketmq等产品相关的逻辑。
+
+2. sdk需要把所有跟通信协议相关的东西(比如proto编译出来的stub类)屏蔽掉,请勿让public方法暴露出任何跟协议相关的东西,最好protected方法也不暴露proto相关的东西。
+ 这么做是因为将来可能改grpc API的package路径,甚至哪天不用grpc了(谁知道呢)。总之请让用户不用关心协议。
+
+举个例子, state API对应有个`deleteState`方法,需要传`DeleteStateRequest`对象。
+```java
+
+ /**
+ * Delete a state.
+ *
+ * @param request Request to delete a state.
+ */
+ void deleteState(DeleteStateRequest request);
+
+```
+这个`DeleteStateRequest`是sdk定义的,其实sdk会把它转成 `RuntimeProto.DeleteStateRequest` (proto编译出来的类) 。
+
+你可能会问:为什么不能直接传`RuntimeProto.DeleteStateRequest` 呢?
+
+这就是上面说的原因,sdk需要封装掉协议相关的东西
+
+### 想为某个grpc API提供java sdk,需要做哪些事情?
+举个例子,grpc API里添加了file API,现在想为java sdk开发file API相关功能,需要做哪些事情?
+
+1. 先找个java sdk的demo跑起来,然后看懂java sdk是怎么创建对象、怎么调用的。其实java sdk就是把grpc包了一层,封装掉grpc的一些stub类,逻辑不多。
+
+2. 参考pr [feat(java-sdk): java sdk support File API](https://github.com/mosn/layotto/pull/325) . 这个pr 给java sdk添加了file API相关功能
+
+### 如何格式化 java sdk 代码
+提交pull request之前先用maven编译一下
+
+```shell
+mvn clean compile
+```
+会自动格式化您的代码
+
+### 如何将proto文件编译成java代码
+
+#### 1. 下载编译工具 [protoc](https://github.com/protocolbuffers/protobuf/releases)
+my protoc version:
+```shell
+$ protoc --version
+libprotoc 3.11.2
+```
+
+#### 2. 修改对应`proto`文件生成类名包名等信息
+(需先修改文件内部service名)
+`spec/proto/runtime/v1/appcallback.proto` :
+```protobuf
+option java_outer_classname = "AppCallbackProto";
+option java_package = "spec.proto.runtime.v1";
+```
+`spec/proto/runtime/v1/runtime.proto` :
+```protobuf
+option java_outer_classname = "RuntimeProto";
+option java_package = "spec.proto.runtime.v1";
+```
+
+#### 3. 编译其对应`JAVA`文件
+```shell
+cd ${your PROJECT path}/spec/proto/runtime/v1
+protoc -I=. --java_out=../../../../sdk/java-sdk/sdk/src/main/java/ runtime.proto
+protoc -I=. --java_out=../../../../sdk/java-sdk/sdk/src/main/java/ appcallback.proto
+```
+
+PS: 建议用maven插件`protoc-gen-grpc-java`生成protobuf和grpc的java代码
+
+如果您在使用 [IntelliJ IDEA](https://www.jetbrains.com/help/idea/discover-intellij-idea.html) ,双击 Maven插件中的 `compile` , IDE 会自动帮你编译 proto 文件:
+
+
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..7ee55ef
--- /dev/null
+++ b/README.md
@@ -0,0 +1,98 @@
+[中文](./README-zh.md)
+## How to use java sdk
+### 1. import sdk
+For a Maven project, add the following to your `pom.xml` file:
+```xml
+
+ ...
+
+ ...
+
+ io.mosn.layotto
+ runtime-sdk-parent
+ 1.0.0
+
+ ...
+
+ ...
+
+```
+
+### 2. Run the examples
+Clone this repository including the submodules:
+
+```sh
+git clone https://github.com/mosn/layotto.git
+```
+
+Build and run Layotto:
+
+```bash
+# make sure you replace this` ${projectpath}` with your own project path.
+cd ${projectpath}/cmd/layotto
+go build
+./layotto start -c ../../configs/config_redis.json
+```
+
+Then head over to build the java-sdk [Maven](https://maven.apache.org/install.html) (Apache Maven version 3.x) project:
+
+```sh
+# make sure you replace this` ${projectpath}` with your own project path.
+cd ${projectpath}/sdk/java-sdk
+mvn clean install
+```
+
+
+
+
+Try the following examples to learn more about this SDK:
+* [Hello world](./examples/src/test/java/io/mosn/layotto/examples/helloworld)
+* [State management](./examples/src/test/java/io/mosn/layotto/examples/state)
+* [Pubsub API](./examples/src/test/java/io/mosn/layotto/examples/pubsub)
+* [File API](./examples/src/test/java/io/mosn/layotto/examples/file)
+
+## java sdk developer guide
+### How to format java sdk code
+Compile before submit your pull request:
+
+```shell
+mvn clean compile
+```
+It will format your code automatically.
+
+### How to generate a Java PROTO file
+
+#### 1. Download proto compiler [protoc](https://github.com/protocolbuffers/protobuf/releases)
+my protoc version:
+```shell
+$ protoc --version
+libprotoc 3.11.2
+```
+
+#### 2. Check `option` fields in these proto files
+Make sure these `option` fields have been configurated.
+
+spec/proto/runtime/v1/appcallback.proto :
+```protobuf
+option java_outer_classname = "AppCallbackProto";
+option java_package = "spec.proto.runtime.v1";
+```
+
+spec/proto/runtime/v1/runtime.proto :
+```protobuf
+option java_outer_classname = "RuntimeProto";
+option java_package = "spec.proto.runtime.v1";
+```
+
+#### 3. Compile them into corresponding `JAVA` files
+```shell
+# make sure you replace this `${your PROJECT path}` with your own project path.
+cd ${your PROJECT path}/spec/proto/runtime/v1
+protoc -I=. --java_out=../../../../sdk/java-sdk/sdk/src/main/java/ runtime.proto
+protoc -I=. --java_out=../../../../sdk/java-sdk/sdk/src/main/java/ appcallback.proto
+```
+
+PS: We recommend that you use the maven plugin `protoc-gen-grpc-java` to generate these protobuf and grpc related java code.
+If you are using [IntelliJ IDEA](https://www.jetbrains.com/help/idea/discover-intellij-idea.html) ,just double click `compile` in the Maven tab and the IDE will generate proto files automatically:
+
+
diff --git a/examples/pom.xml b/examples/pom.xml
new file mode 100644
index 0000000..015e86b
--- /dev/null
+++ b/examples/pom.xml
@@ -0,0 +1,60 @@
+
+
+ 4.0.0
+
+
+ runtime-sdk-parent
+ io.mosn.layotto
+ 1.1.0-SNAPSHOT
+
+
+ examples
+
+
+
+ io.mosn.layotto
+ runtime-sdk
+
+
+
+
+ src/main/java
+
+
+ src/main/resources
+ false
+
+ **/**
+
+
+
+ src/test/java
+
+
+ src/test/resources
+ false
+
+ **/**
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+ 3.0.1
+
+
+ attach-sources
+
+ jar
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/src/test/java/io/mosn/layotto/examples/file/File.java b/examples/src/test/java/io/mosn/layotto/examples/file/File.java
new file mode 100644
index 0000000..43f2fc1
--- /dev/null
+++ b/examples/src/test/java/io/mosn/layotto/examples/file/File.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2021 Layotto Authors
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mosn.layotto.examples.file;
+
+import io.mosn.layotto.v1.RuntimeClientBuilder;
+import io.mosn.layotto.v1.config.RuntimeProperties;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import spec.sdk.runtime.v1.client.RuntimeClient;
+import spec.sdk.runtime.v1.domain.file.DelFileRequest;
+import spec.sdk.runtime.v1.domain.file.FileInfo;
+import spec.sdk.runtime.v1.domain.file.GetFileRequest;
+import spec.sdk.runtime.v1.domain.file.GetFileResponse;
+import spec.sdk.runtime.v1.domain.file.GetMetaRequest;
+import spec.sdk.runtime.v1.domain.file.GetMeteResponse;
+import spec.sdk.runtime.v1.domain.file.ListFileRequest;
+import spec.sdk.runtime.v1.domain.file.ListFileResponse;
+import spec.sdk.runtime.v1.domain.file.PutFileRequest;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Specially
+ *
+ * 1. add `"local:{}` to "files" node in layotto/configs/config_file.json
+ * 2. start server by `./layotto start -c ../../configs/config_file.json`
+ */
+public class File {
+
+ private static final Logger logger = LoggerFactory.getLogger(File.class.getName());
+
+ static String storeName = "local";
+ static String fileName = "/tmp/test.log";
+
+ public static void main(String[] args) throws Exception {
+
+ RuntimeClient client = new RuntimeClientBuilder()
+ .withPort(RuntimeProperties.DEFAULT_PORT)
+ .build();
+
+ putFile(client);
+ getFile(client);
+ listFile(client);
+ getFileMeta(client);
+ delFile(client);
+ }
+
+ public static void putFile(RuntimeClient client) throws Exception {
+
+ PutFileRequest request = new PutFileRequest();
+ request.setStoreName(storeName);
+ request.setFileName(fileName);
+
+ Map meta = new HashMap<>();
+ meta.put("FileMode", "521");
+ meta.put("FileFlag", "0777");
+ request.setMetaData(meta);
+
+ request.setIn(new ByteArrayInputStream("hello world".getBytes()));
+
+ client.putFile(request, 3000);
+ }
+
+ public static void getFile(RuntimeClient client) throws Exception {
+
+ GetFileRequest request = new GetFileRequest();
+ request.setStoreName(storeName);
+ request.setFileName(fileName);
+
+ Map meta = new HashMap<>();
+ meta.put("k1", "v1");
+ request.setMetaData(meta);
+
+ GetFileResponse resp = client.getFile(request, 3000);
+
+ InputStream reader = resp.getIn();
+
+ byte[] buf = new byte[128];
+ for (int len = reader.read(buf); len > 0; len = reader.read(buf)) {
+ logger.info(new String(buf, 0, len));
+ }
+ }
+
+ public static void delFile(RuntimeClient client) throws Exception {
+
+ DelFileRequest request = new DelFileRequest();
+ request.setStoreName(storeName);
+ request.setFileName(fileName);
+
+ client.delFile(request, 3000);
+ }
+
+ public static void listFile(RuntimeClient client) throws Exception {
+
+ ListFileRequest request = new ListFileRequest();
+ request.setStoreName(storeName);
+ request.setMarker("test.log");
+ request.setName("/tmp");
+ request.setPageSize(10);
+
+ ListFileResponse resp = client.listFile(request, 3000);
+
+ for (FileInfo f : resp.getFiles()) {
+ logger.info(f.getFileName());
+ }
+ }
+
+ public static void getFileMeta(RuntimeClient client) throws Exception {
+
+ GetMetaRequest request = new GetMetaRequest();
+ request.setStoreName(storeName);
+ request.setFileName(fileName);
+
+ GetMeteResponse response = client.getFileMeta(request, 3000);
+ logger.info(response.getLastModified());
+ logger.info("" + response.getMeta().size());
+ }
+}
diff --git a/examples/src/test/java/io/mosn/layotto/examples/helloworld/Hello.java b/examples/src/test/java/io/mosn/layotto/examples/helloworld/Hello.java
new file mode 100644
index 0000000..da35ec3
--- /dev/null
+++ b/examples/src/test/java/io/mosn/layotto/examples/helloworld/Hello.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2021 Layotto Authors
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mosn.layotto.examples.helloworld;
+
+import io.mosn.layotto.v1.RuntimeClientBuilder;
+import io.mosn.layotto.v1.config.RuntimeProperties;
+import spec.sdk.runtime.v1.client.RuntimeClient;
+
+public class Hello {
+
+ public static void main(String[] args) {
+ RuntimeClient client = new RuntimeClientBuilder()
+ .withPort(RuntimeProperties.DEFAULT_PORT)
+ .build();
+
+ String resp = client.sayHello("helloworld");
+ if (!"greeting, helloworld".equals(resp)) {
+ throw new RuntimeException("Unexpected result:" + resp);
+ }
+ System.out.println(resp);
+ }
+}
diff --git a/examples/src/test/java/io/mosn/layotto/examples/pubsub/publisher/Publisher.java b/examples/src/test/java/io/mosn/layotto/examples/pubsub/publisher/Publisher.java
new file mode 100644
index 0000000..e7b14d9
--- /dev/null
+++ b/examples/src/test/java/io/mosn/layotto/examples/pubsub/publisher/Publisher.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2021 Layotto Authors
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mosn.layotto.examples.pubsub.publisher;
+
+import io.mosn.layotto.v1.RuntimeClientBuilder;
+import io.mosn.layotto.v1.config.RuntimeProperties;
+import spec.sdk.runtime.v1.client.RuntimeClient;
+
+public class Publisher {
+
+ public static void main(String[] args) {
+ RuntimeClient client = new RuntimeClientBuilder()
+ .withPort(RuntimeProperties.DEFAULT_PORT)
+ .build();
+
+ client.publishEvent("redis", "hello", "world".getBytes());
+ client.publishEvent("redis", "topic1", "message1".getBytes());
+ }
+}
diff --git a/examples/src/test/java/io/mosn/layotto/examples/pubsub/subscriber/Subscriber.java b/examples/src/test/java/io/mosn/layotto/examples/pubsub/subscriber/Subscriber.java
new file mode 100644
index 0000000..887a64a
--- /dev/null
+++ b/examples/src/test/java/io/mosn/layotto/examples/pubsub/subscriber/Subscriber.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2021 Layotto Authors
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mosn.layotto.examples.pubsub.subscriber;
+
+import com.alibaba.fastjson.JSON;
+import io.mosn.layotto.examples.pubsub.subscriber.impl.RawSubscriber;
+import io.mosn.layotto.v1.RuntimeServerGrpc;
+
+import java.util.concurrent.Semaphore;
+
+public class Subscriber {
+
+ /**
+ * This is the entry point for this example app, which subscribes to a topic.
+ *
+ * @throws Exception An Exception on startup.
+ */
+ public static void main(String[] args) throws Exception {
+ RuntimeServerGrpc srv = new RuntimeServerGrpc(9999);
+ RawSubscriber pubsub = new RawSubscriber("redis");
+ pubsub.subscribe("hello", request -> {
+ String value = new String(request.getData());
+ assertEquals(value, "world");
+ System.out.println(JSON.toJSONString(request));
+ });
+ pubsub.subscribe("topic1", request -> {
+ String value = new String(request.getData());
+ assertEquals(value, "message1");
+ System.out.println(JSON.toJSONString(request));
+ });
+ srv.registerPubSubCallback(pubsub.getComponentName(), pubsub);
+ Semaphore sm = new Semaphore(0);
+ srv.start();
+ sm.acquire();
+ }
+
+ private static void assertEquals(Object actualResult, Object expected) {
+ if (actualResult == expected || actualResult.equals(expected)) {
+ return;
+ }
+ String msg = "Unexpected result:" + actualResult;
+ throw new RuntimeException(msg);
+ }
+}
\ No newline at end of file
diff --git a/examples/src/test/java/io/mosn/layotto/examples/pubsub/subscriber/impl/EventListener.java b/examples/src/test/java/io/mosn/layotto/examples/pubsub/subscriber/impl/EventListener.java
new file mode 100644
index 0000000..8f1c523
--- /dev/null
+++ b/examples/src/test/java/io/mosn/layotto/examples/pubsub/subscriber/impl/EventListener.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2021 Layotto Authors
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mosn.layotto.examples.pubsub.subscriber.impl;
+
+import spec.sdk.runtime.v1.domain.pubsub.TopicEventRequest;
+
+public interface EventListener {
+
+ void onEvent(TopicEventRequest request) throws Exception;
+}
diff --git a/examples/src/test/java/io/mosn/layotto/examples/pubsub/subscriber/impl/RawSubscriber.java b/examples/src/test/java/io/mosn/layotto/examples/pubsub/subscriber/impl/RawSubscriber.java
new file mode 100644
index 0000000..3121c4e
--- /dev/null
+++ b/examples/src/test/java/io/mosn/layotto/examples/pubsub/subscriber/impl/RawSubscriber.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2021 Layotto Authors
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mosn.layotto.examples.pubsub.subscriber.impl;
+
+import io.mosn.layotto.v1.callback.component.pubsub.Subscriber;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import spec.sdk.runtime.v1.domain.pubsub.TopicEventRequest;
+import spec.sdk.runtime.v1.domain.pubsub.TopicEventResponse;
+import spec.sdk.runtime.v1.domain.pubsub.TopicEventResponseStatus;
+import spec.sdk.runtime.v1.domain.pubsub.TopicSubscription;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Raw pubsub client.
+ */
+public class RawSubscriber implements Subscriber {
+
+ private static final Logger LOG = LoggerFactory.getLogger(RawSubscriber.class);
+
+ private final Map listeners = new ConcurrentHashMap<>();
+ private final String componentName;
+
+ public RawSubscriber(String pubsubName) {
+ componentName = pubsubName;
+ }
+
+ @Override
+ public String getComponentName() {
+ return componentName;
+ }
+
+ public void subscribe(String topic, EventListener listener) {
+ if (listeners.putIfAbsent(topic, listener) != null) {
+ throw new IllegalArgumentException("Listener for topic " + topic + " already exists!");
+ }
+ }
+
+ @Override
+ public Set listTopicSubscriptions() {
+ final HashSet subscriptions = new HashSet<>();
+ for (String topic : listeners.keySet()) {
+ final TopicSubscription subscription = new TopicSubscription();
+ subscription.setTopic(topic);
+ subscription.setPubsubName(componentName);
+ subscriptions.add(subscription);
+ }
+ return subscriptions;
+ }
+
+ @Override
+ public TopicEventResponse onTopicEvent(TopicEventRequest request) {
+ final String topic = request.getTopic();
+ final EventListener eventListener = listeners.get(topic);
+ if (eventListener == null) {
+ LOG.error("Cannot find listener for topic:[{}]", topic);
+ TopicEventResponse resp = new TopicEventResponse();
+ resp.setStatus(TopicEventResponseStatus.DROP);
+ }
+ try {
+ eventListener.onEvent(request);
+ final TopicEventResponse response = new TopicEventResponse();
+ response.setStatus(TopicEventResponseStatus.SUCCESS);
+ return response;
+ } catch (Exception e) {
+ final TopicEventResponse response = new TopicEventResponse();
+ response.setStatus(TopicEventResponseStatus.RETRY);
+ return response;
+ }
+ }
+}
diff --git a/examples/src/test/java/io/mosn/layotto/examples/state/RedisCRUD.java b/examples/src/test/java/io/mosn/layotto/examples/state/RedisCRUD.java
new file mode 100644
index 0000000..34e4b13
--- /dev/null
+++ b/examples/src/test/java/io/mosn/layotto/examples/state/RedisCRUD.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2021 Layotto Authors
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.mosn.layotto.examples.state;
+
+import io.mosn.layotto.v1.RuntimeClientBuilder;
+import io.mosn.layotto.v1.config.RuntimeProperties;
+import spec.sdk.runtime.v1.client.RuntimeClient;
+import spec.sdk.runtime.v1.domain.state.GetBulkStateRequest;
+import spec.sdk.runtime.v1.domain.state.State;
+import spec.sdk.runtime.v1.domain.state.TransactionalStateOperation;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class RedisCRUD {
+ static String storeName = "redis";
+ static String key1 = "key1";
+ static String key2 = "key2";
+ static String key3 = "key3";
+
+ public static void main(String[] args) {
+ // build RuntimeClient
+ RuntimeClient client = new RuntimeClientBuilder()
+ .withPort(RuntimeProperties.DEFAULT_PORT)
+ .build();
+ // saveState
+ client.saveState(storeName, key1, "v11");
+ // getState
+ State state = client.getState(storeName, key1, String.class);
+ assertEquals(state.getKey(), key1);
+ assertEquals(state.getValue(), "v11");
+ System.out.println("get state key:" + state.getKey() + " value:" + state.getValue());
+
+ // deleteState
+ client.deleteState(storeName, key1);
+
+ // getState
+ state = client.getState(storeName, key1, String.class);
+ assertEquals(state.getKey(), key1);
+ // TODO: currently Redis component can't tell the difference between null and 'non exist'
+ //assertEquals(state.getValue(), null);
+ assertEquals(state.getValue(), "");
+ System.out.println("get state after delete. key:" + state.getKey() + " value:" + state.getValue());
+
+ // saveBulkState
+ List> list = new ArrayList<>();
+ State> state1 = new State<>(key1, "v1", null, null);
+ State> state2 = new State<>(key2, "v2", null, null);
+ list.add(state2);
+ list.add(state1);
+ client.saveBulkState(storeName, list);
+
+ // execute transaction
+ List> operationList = new ArrayList<>();
+ operationList.add(new TransactionalStateOperation<>(TransactionalStateOperation.OperationType.UPSERT,
+ new State<>(key2, new TestClass(key2), "")));
+
+ operationList.add(new TransactionalStateOperation<>(TransactionalStateOperation.OperationType.UPSERT,
+ new State<>(key3, "v3", "")));
+
+ client.executeStateTransaction(storeName, operationList);
+
+ // getBulkState
+ List keys = new ArrayList<>();
+ keys.add(key3);
+ keys.add(key1);
+ GetBulkStateRequest req = new GetBulkStateRequest(storeName, keys);
+ List> bulkState = client.getBulkState(req, String.class);
+ assertTrue(bulkState.size() == 2);
+ for (State st : bulkState) {
+ String key = st.getKey();
+ if (key.equals(key1)) {
+ assertEquals(st.getValue(), "v1");
+ } else if (key.equals(key3)) {
+ assertEquals(st.getValue(), "v3");
+ } else {
+ throw new RuntimeException("Unexpected key:" + key);
+ }
+ }
+
+ keys = new ArrayList<>();
+ keys.add(key2);
+ req = new GetBulkStateRequest(storeName, keys);
+ List> resp = client.getBulkState(req, TestClass.class);
+ assertTrue(resp.size() == 1);
+ assertEquals(resp.get(0).getValue().name, key2);
+
+ }
+
+ private static void assertTrue(boolean b) {
+ if (!b) {
+ throw new RuntimeException("Assertion fail");
+ }
+ }
+
+ private static void assertEquals(String actualResult, String expected) {
+ if (actualResult == expected || actualResult.equals(expected)) {
+ return;
+ }
+ throw new RuntimeException("Unexpected result:" + actualResult);
+ }
+
+ public static class TestClass {
+ String name;
+
+ public TestClass(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Getter method for property name.
+ *
+ * @return property value of name
+ */
+ public String getName() {
+ return name;
+ }
+ }
+}
diff --git a/img.png b/img.png
new file mode 100644
index 0000000000000000000000000000000000000000..a826585294b2ae170104bf73a2665a758d43db06
GIT binary patch
literal 31279
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