├── .editorconfig ├── .github └── workflows │ ├── build.yaml │ ├── ci.yaml │ └── publish.yaml ├── .gitignore ├── BUILD.md ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── auth-api ├── pom.xml └── src │ └── main │ └── java │ └── tech │ └── ydb │ └── auth │ ├── AuthIdentity.java │ ├── AuthProvider.java │ ├── AuthRpcProvider.java │ ├── NopAuthProvider.java │ └── TokenAuthProvider.java ├── auth-providers └── oauth2-provider │ ├── pom.xml │ └── src │ ├── main │ └── java │ │ └── tech │ │ └── ydb │ │ └── auth │ │ ├── OAuth2AuthHelper.java │ │ ├── OAuth2TokenExchangeProvider.java │ │ └── OAuth2TokenSource.java │ └── test │ └── java │ └── tech │ └── ydb │ └── auth │ ├── OAuth2TokenExchangeProviderTest.java │ └── OAuth2TokenTest.java ├── bom └── pom.xml ├── common ├── pom.xml └── src │ ├── main │ └── java │ │ └── tech │ │ └── ydb │ │ └── common │ │ ├── retry │ │ ├── ErrorPolicy.java │ │ ├── ExponentialBackoffRetry.java │ │ ├── RetryForever.java │ │ ├── RetryNTimes.java │ │ ├── RetryPolicy.java │ │ └── RetryUntilElapsed.java │ │ └── transaction │ │ ├── TxMode.java │ │ ├── YdbTransaction.java │ │ └── impl │ │ └── YdbTransactionImpl.java │ └── test │ ├── java │ └── tech │ │ └── ydb │ │ └── common │ │ └── retry │ │ └── RetryPoliciesTest.java │ └── resources │ └── log4j2.xml ├── config ├── ydb.checkstyle.xml └── ydb.suppressions.xml ├── coordination ├── pom.xml └── src │ ├── main │ └── java │ │ └── tech │ │ └── ydb │ │ └── coordination │ │ ├── CoordinationClient.java │ │ ├── CoordinationSession.java │ │ ├── SemaphoreLease.java │ │ ├── description │ │ ├── NodeConfig.java │ │ ├── SemaphoreChangedEvent.java │ │ ├── SemaphoreDescription.java │ │ └── SemaphoreWatcher.java │ │ ├── impl │ │ ├── ClientImpl.java │ │ ├── CoordinationServiceImpl.java │ │ ├── LeaseImpl.java │ │ ├── Rpc.java │ │ ├── RpcImpl.java │ │ ├── SessionImpl.java │ │ ├── SessionState.java │ │ ├── Stream.java │ │ └── StreamMsg.java │ │ └── settings │ │ ├── CoordinationNodeSettings.java │ │ ├── CoordinationSessionSettings.java │ │ ├── DescribeCoordinationNodeSettings.java │ │ ├── DescribeSemaphoreMode.java │ │ ├── DropCoordinationNodeSettings.java │ │ └── WatchSemaphoreMode.java │ └── test │ ├── java │ └── tech │ │ └── ydb │ │ └── coordination │ │ ├── CoordinationServiceTest.java │ │ └── impl │ │ ├── ClientTest.java │ │ ├── GrpcStreamMock.java │ │ └── StreamTest.java │ └── resources │ └── log4j2.xml ├── core ├── pom.xml └── src │ ├── main │ ├── java │ │ └── tech │ │ │ └── ydb │ │ │ └── core │ │ │ ├── Constants.java │ │ │ ├── Issue.java │ │ │ ├── Result.java │ │ │ ├── Status.java │ │ │ ├── StatusCode.java │ │ │ ├── UnexpectedResultException.java │ │ │ ├── auth │ │ │ ├── AuthIdentity.java │ │ │ ├── AuthProvider.java │ │ │ ├── AuthRpc.java │ │ │ ├── BackgroundIdentity.java │ │ │ ├── EnvironAuthProvider.java │ │ │ ├── JwtUtils.java │ │ │ ├── NopAuthProvider.java │ │ │ ├── StaticCredentials.java │ │ │ └── TokenAuthProvider.java │ │ │ ├── grpc │ │ │ ├── BalancingSettings.java │ │ │ ├── GrpcCompression.java │ │ │ ├── GrpcReadStream.java │ │ │ ├── GrpcReadWriteStream.java │ │ │ ├── GrpcRequestSettings.java │ │ │ ├── GrpcStatuses.java │ │ │ ├── GrpcTransport.java │ │ │ ├── GrpcTransportBuilder.java │ │ │ └── YdbHeaders.java │ │ │ ├── impl │ │ │ ├── BaseGrpcTransport.java │ │ │ ├── FixedCallOptionsTransport.java │ │ │ ├── MultiChannelTransport.java │ │ │ ├── SingleChannelTransport.java │ │ │ ├── YdbDiscovery.java │ │ │ ├── YdbSchedulerFactory.java │ │ │ ├── YdbTransportImpl.java │ │ │ ├── auth │ │ │ │ ├── AuthCallOptions.java │ │ │ │ ├── GrpcAuthRpc.java │ │ │ │ └── YdbCallCredentials.java │ │ │ ├── call │ │ │ │ ├── EmptyStream.java │ │ │ │ ├── GrpcStatusHandler.java │ │ │ │ ├── ProxyReadStream.java │ │ │ │ ├── ReadStreamCall.java │ │ │ │ ├── ReadWriteStreamCall.java │ │ │ │ └── UnaryCall.java │ │ │ └── pool │ │ │ │ ├── ChannelFactoryLoader.java │ │ │ │ ├── EndpointPool.java │ │ │ │ ├── EndpointRecord.java │ │ │ │ ├── GrpcChannel.java │ │ │ │ ├── GrpcChannelPool.java │ │ │ │ ├── ManagedChannelFactory.java │ │ │ │ ├── NettyChannelFactory.java │ │ │ │ ├── PriorityPicker.java │ │ │ │ └── ShadedNettyChannelFactory.java │ │ │ ├── operation │ │ │ ├── AsyncOperation.java │ │ │ ├── FailedOperation.java │ │ │ ├── Operation.java │ │ │ ├── OperationBinder.java │ │ │ ├── OperationImpl.java │ │ │ ├── OperationTray.java │ │ │ ├── StatusExtractor.java │ │ │ └── StatusMapper.java │ │ │ ├── settings │ │ │ ├── BaseRequestSettings.java │ │ │ └── OperationSettings.java │ │ │ ├── ssl │ │ │ ├── MultiX509TrustManager.java │ │ │ ├── X509TrustManagerWrapper.java │ │ │ ├── YandexTrustManagerFactory.java │ │ │ └── YandexTrustManagersProvider.java │ │ │ └── utils │ │ │ ├── FutureTools.java │ │ │ ├── ProtobufUtils.java │ │ │ ├── Results.java │ │ │ ├── URITools.java │ │ │ └── Version.java │ └── resources │ │ ├── certificates │ │ └── YandexAllCAs.pkcs │ │ └── ydb_sdk_version.properties │ └── test │ ├── java │ └── tech │ │ └── ydb │ │ └── core │ │ ├── IssueTest.java │ │ ├── ResultTest.java │ │ ├── StatusCodeTest.java │ │ ├── StatusTest.java │ │ ├── UnexpectedResultExceptionTest.java │ │ ├── auth │ │ ├── CredentialsAuthProviderTest.java │ │ ├── JwtBuilder.java │ │ └── JwtUtilsTest.java │ │ ├── grpc │ │ └── GrpcStatusesTest.java │ │ ├── impl │ │ ├── MockedCall.java │ │ ├── MockedClock.java │ │ ├── MockedScheduler.java │ │ ├── YdbDiscoveryTest.java │ │ ├── YdbTransportImplTest.java │ │ └── pool │ │ │ ├── DefaultChannelFactoryTest.java │ │ │ ├── EndpointPoolTest.java │ │ │ ├── GrpcChannelPoolTest.java │ │ │ ├── GrpcChannelTest.java │ │ │ ├── ManagedChannelMock.java │ │ │ └── PriorityPickerTest.java │ │ ├── operation │ │ ├── OperationBinderTest.java │ │ ├── OperationImplTest.java │ │ ├── OperationSettingsTest.java │ │ └── OperationTrayTest.java │ │ ├── timer │ │ └── TestTicker.java │ │ └── utils │ │ └── ResultTests.java │ └── resources │ └── log4j2.xml ├── export ├── pom.xml └── src │ └── main │ └── java │ └── tech │ └── ydb │ └── export │ ├── ExportClient.java │ ├── ExportRpc.java │ ├── impl │ ├── ExportClientImpl.java │ └── GrpcExportRpcImpl.java │ ├── result │ ├── ExportToS3Result.java │ └── ExportToYtResult.java │ └── settings │ ├── ExportToS3Settings.java │ ├── ExportToYtSettings.java │ └── FindExportSettings.java ├── pom.xml ├── query ├── pom.xml └── src │ ├── main │ └── java │ │ └── tech │ │ └── ydb │ │ └── query │ │ ├── QueryClient.java │ │ ├── QuerySession.java │ │ ├── QueryStream.java │ │ ├── QueryTransaction.java │ │ ├── impl │ │ ├── QueryClientImpl.java │ │ ├── QueryServiceRpc.java │ │ ├── SessionImpl.java │ │ ├── SessionPool.java │ │ ├── TableClientImpl.java │ │ └── TxControl.java │ │ ├── result │ │ ├── QueryInfo.java │ │ ├── QueryResultPart.java │ │ └── QueryStats.java │ │ ├── settings │ │ ├── AttachSessionSettings.java │ │ ├── BeginTransactionSettings.java │ │ ├── CommitTransactionSettings.java │ │ ├── CreateSessionSettings.java │ │ ├── DeleteSessionSettings.java │ │ ├── ExecuteQuerySettings.java │ │ ├── QueryExecMode.java │ │ ├── QueryStatsMode.java │ │ └── RollbackTransactionSettings.java │ │ └── tools │ │ ├── QueryReader.java │ │ └── SessionRetryContext.java │ └── test │ ├── java │ └── tech │ │ └── ydb │ │ └── query │ │ ├── QueryExampleTest.java │ │ ├── TableExampleTest.java │ │ ├── TestExampleData.java │ │ ├── impl │ │ ├── QueryIntegrationTest.java │ │ └── ResourcePoolTest.java │ │ └── tools │ │ └── QueryReaderTest.java │ └── resources │ └── log4j2.xml ├── scheme ├── pom.xml └── src │ ├── main │ └── java │ │ └── tech │ │ └── ydb │ │ └── scheme │ │ ├── SchemeClient.java │ │ ├── description │ │ ├── DescribePathResult.java │ │ ├── Entry.java │ │ ├── EntryType.java │ │ └── ListDirectoryResult.java │ │ └── impl │ │ ├── GrpcSchemeRpc.java │ │ ├── SchemeClientBuilderImpl.java │ │ ├── SchemeClientImpl.java │ │ └── SchemeRpc.java │ └── test │ ├── java │ └── tech │ │ └── ydb │ │ └── scheme │ │ └── BaseIntegrationTest.java │ └── resources │ └── log4j2.xml ├── table ├── pom.xml └── src │ ├── main │ └── java │ │ └── tech │ │ └── ydb │ │ └── table │ │ ├── Session.java │ │ ├── SessionPoolStats.java │ │ ├── SessionRetryContext.java │ │ ├── SessionRetryHandler.java │ │ ├── SessionSupplier.java │ │ ├── TableClient.java │ │ ├── description │ │ ├── ChangefeedDescription.java │ │ ├── ColumnFamily.java │ │ ├── KeyBound.java │ │ ├── KeyRange.java │ │ ├── StoragePool.java │ │ ├── TableColumn.java │ │ ├── TableDescription.java │ │ ├── TableIndex.java │ │ ├── TableOptionDescription.java │ │ └── TableTtl.java │ │ ├── impl │ │ ├── BaseSession.java │ │ ├── DataQueryImpl.java │ │ ├── PooledTableClient.java │ │ ├── SimpleTableClient.java │ │ ├── TxControlToPb.java │ │ └── pool │ │ │ ├── SessionPool.java │ │ │ ├── SessionPoolOptions.java │ │ │ ├── StatefulSession.java │ │ │ └── WaitingQueue.java │ │ ├── query │ │ ├── DataQuery.java │ │ ├── DataQueryResult.java │ │ ├── ExplainDataQueryResult.java │ │ ├── Params.java │ │ ├── ParamsImmutableMap.java │ │ ├── ParamsMutableMap.java │ │ ├── ReadRowsResult.java │ │ ├── ReadTablePart.java │ │ └── stats │ │ │ ├── CompilationStats.java │ │ │ ├── OperationStats.java │ │ │ ├── QueryPhaseStats.java │ │ │ ├── QueryStats.java │ │ │ ├── QueryStatsCollectionMode.java │ │ │ └── TableAccessStats.java │ │ ├── result │ │ ├── DictReader.java │ │ ├── ListReader.java │ │ ├── OptionalReader.java │ │ ├── PrimitiveReader.java │ │ ├── ResultSetReader.java │ │ ├── StructReader.java │ │ ├── TupleReader.java │ │ ├── ValueReader.java │ │ ├── VariantReader.java │ │ └── impl │ │ │ ├── AbstractValueReader.java │ │ │ ├── ProtoDictValueReader.java │ │ │ ├── ProtoListValueReader.java │ │ │ ├── ProtoNullValueReader.java │ │ │ ├── ProtoOptionalValueReader.java │ │ │ ├── ProtoPrimitiveValueReader.java │ │ │ ├── ProtoResultSetReader.java │ │ │ ├── ProtoStructValueReader.java │ │ │ ├── ProtoTupleValueReader.java │ │ │ ├── ProtoValueReaders.java │ │ │ ├── ProtoVariantValueReader.java │ │ │ └── ProtoVoidValueReader.java │ │ ├── rpc │ │ ├── TableRpc.java │ │ └── grpc │ │ │ └── GrpcTableRpc.java │ │ ├── settings │ │ ├── AlterTableSettings.java │ │ ├── AutoPartitioningPolicy.java │ │ ├── BeginTxSettings.java │ │ ├── BulkUpsertSettings.java │ │ ├── Changefeed.java │ │ ├── CommitTxSettings.java │ │ ├── CopyTableSettings.java │ │ ├── CopyTablesSettings.java │ │ ├── CreateSessionSettings.java │ │ ├── CreateTableSettings.java │ │ ├── DeleteSessionSettings.java │ │ ├── DescribeTableOptionsSettings.java │ │ ├── DescribeTableSettings.java │ │ ├── DropTableSettings.java │ │ ├── ExecuteDataQuerySettings.java │ │ ├── ExecuteScanQuerySettings.java │ │ ├── ExecuteSchemeQuerySettings.java │ │ ├── ExplainDataQuerySettings.java │ │ ├── KeepAliveSessionSettings.java │ │ ├── PartitioningPolicy.java │ │ ├── PartitioningSettings.java │ │ ├── PrepareDataQuerySettings.java │ │ ├── ReadRowsSettings.java │ │ ├── ReadTableSettings.java │ │ ├── RenameTablesSettings.java │ │ ├── ReplicationPolicy.java │ │ ├── RequestSettings.java │ │ ├── RollbackTxSettings.java │ │ ├── StoragePolicy.java │ │ └── TtlSettings.java │ │ ├── transaction │ │ ├── TableTransaction.java │ │ ├── Transaction.java │ │ └── TxControl.java │ │ ├── utils │ │ ├── Arrays2.java │ │ ├── Hex.java │ │ └── LittleEndian.java │ │ └── values │ │ ├── DecimalType.java │ │ ├── DecimalValue.java │ │ ├── DictType.java │ │ ├── DictValue.java │ │ ├── ListType.java │ │ ├── ListValue.java │ │ ├── NullType.java │ │ ├── NullValue.java │ │ ├── OptionalType.java │ │ ├── OptionalValue.java │ │ ├── PgType.java │ │ ├── PrimitiveType.java │ │ ├── PrimitiveValue.java │ │ ├── StructType.java │ │ ├── StructValue.java │ │ ├── TupleType.java │ │ ├── TupleValue.java │ │ ├── Type.java │ │ ├── Value.java │ │ ├── VariantType.java │ │ ├── VariantValue.java │ │ ├── VoidType.java │ │ ├── VoidValue.java │ │ └── proto │ │ ├── ProtoType.java │ │ └── ProtoValue.java │ └── test │ ├── java │ └── tech │ │ └── ydb │ │ └── table │ │ ├── GrpcTransportStub.java │ │ ├── SessionRetryContextTest.java │ │ ├── SessionStub.java │ │ ├── TableRpcStub.java │ │ ├── impl │ │ ├── DataQueryImplTest.java │ │ ├── PooledTableClientTest.java │ │ ├── SimpleTableClientTest.java │ │ └── pool │ │ │ ├── FutureHelper.java │ │ │ ├── MockedClock.java │ │ │ ├── MockedScheduler.java │ │ │ ├── MockedTableRpc.java │ │ │ ├── SessionPoolTest.java │ │ │ └── WaitingQueueTest.java │ │ ├── integration │ │ ├── AlterTableTest.java │ │ ├── ChangefeedTableTest.java │ │ ├── DescribeTableTest.java │ │ ├── ReadRowsTest.java │ │ ├── RenameTablesTest.java │ │ ├── TableOptionTest.java │ │ ├── TablePartitioningSettingsTest.java │ │ ├── TtlTableTest.java │ │ └── ValuesReadTest.java │ │ ├── query │ │ └── ParamsTest.java │ │ ├── result │ │ ├── ResultSetReaderTest.java │ │ └── impl │ │ │ ├── OptionalReaderTest.java │ │ │ └── TupleReaderTest.java │ │ ├── transaction │ │ └── TxControlTest.java │ │ ├── utils │ │ ├── Arrays2Test.java │ │ ├── HexTest.java │ │ ├── LittleEndianTest.java │ │ └── TtlModeMappingTest.java │ │ └── values │ │ ├── DecimalValueTest.java │ │ ├── PrimitiveValueTest.java │ │ ├── StructValueTest.java │ │ └── proto │ │ └── ProtoValueTest.java │ └── resources │ └── log4j2.xml ├── tests ├── common │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── tech │ │ │ └── ydb │ │ │ └── test │ │ │ └── integration │ │ │ ├── YdbEnvironment.java │ │ │ ├── YdbHelper.java │ │ │ ├── YdbHelperFactory.java │ │ │ ├── docker │ │ │ ├── DiscoveryServiceProxy.java │ │ │ ├── DockerHelperFactory.java │ │ │ ├── GrpcProxyServer.java │ │ │ ├── ProxedDockerHelperFactory.java │ │ │ └── YdbDockerContainer.java │ │ │ ├── external │ │ │ └── ExternalHelperFactory.java │ │ │ └── utils │ │ │ ├── PortsGenerator.java │ │ │ ├── ProxyGrpcTransport.java │ │ │ └── ProxyYdbHelper.java │ │ └── test │ │ ├── java │ │ └── tech │ │ │ └── ydb │ │ │ └── test │ │ │ └── integration │ │ │ ├── DockerHelperFactoryTest.java │ │ │ ├── DockerMock.java │ │ │ ├── GrpcTransportMock.java │ │ │ ├── ProxyDockerTest.java │ │ │ ├── YdbEnvironmentMock.java │ │ │ ├── YdbEnvironmentTest.java │ │ │ └── YdbHelperFactoryTest.java │ │ └── resources │ │ └── log4j2.xml ├── junit4-support │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── tech │ │ └── ydb │ │ └── test │ │ └── junit4 │ │ ├── GrpcTransportRule.java │ │ └── YdbHelperRule.java └── junit5-support │ ├── pom.xml │ └── src │ └── main │ └── java │ └── tech │ └── ydb │ └── test │ └── junit5 │ ├── GrpcTransportExtension.java │ └── YdbHelperExtension.java └── topic ├── pom.xml └── src ├── main └── java │ └── tech │ └── ydb │ └── topic │ ├── TopicClient.java │ ├── TopicRpc.java │ ├── description │ ├── Codec.java │ ├── Consumer.java │ ├── ConsumerDescription.java │ ├── ConsumerPartitionInfo.java │ ├── ConsumerStats.java │ ├── MetadataItem.java │ ├── MeteringMode.java │ ├── MultipleWindowsStat.java │ ├── OffsetsRange.java │ ├── PartitionInfo.java │ ├── PartitionLocation.java │ ├── PartitionStats.java │ ├── SupportedCodecs.java │ ├── TopicDescription.java │ └── TopicStats.java │ ├── impl │ ├── GrpcStreamRetrier.java │ ├── GrpcTopicRpc.java │ ├── Session.java │ ├── SessionBase.java │ ├── TopicClientBuilderImpl.java │ └── TopicClientImpl.java │ ├── read │ ├── AsyncReader.java │ ├── DecompressionException.java │ ├── DeferredCommitter.java │ ├── Message.java │ ├── MessageAccumulator.java │ ├── PartitionOffsets.java │ ├── PartitionSession.java │ ├── SyncReader.java │ ├── TransactionMessageAccumulator.java │ ├── events │ │ ├── AbstractReadEventHandler.java │ │ ├── CommitOffsetAcknowledgementEvent.java │ │ ├── DataReceivedEvent.java │ │ ├── PartitionSessionClosedEvent.java │ │ ├── PartitionSessionStatusEvent.java │ │ ├── ReadEventHandler.java │ │ ├── ReaderClosedEvent.java │ │ ├── StartPartitionSessionEvent.java │ │ └── StopPartitionSessionEvent.java │ └── impl │ │ ├── AsyncReaderImpl.java │ │ ├── Batch.java │ │ ├── BatchMeta.java │ │ ├── CommitterImpl.java │ │ ├── DeferredCommitterImpl.java │ │ ├── DisjointOffsetRangeSet.java │ │ ├── MessageImpl.java │ │ ├── OffsetsRangeImpl.java │ │ ├── PartitionSessionImpl.java │ │ ├── ReadSession.java │ │ ├── ReaderImpl.java │ │ ├── SyncReaderImpl.java │ │ ├── TransactionMessageAccumulatorImpl.java │ │ └── events │ │ ├── CommitOffsetAcknowledgementEventImpl.java │ │ ├── DataReceivedEventImpl.java │ │ ├── PartitionSessionClosedEventImpl.java │ │ ├── SessionStartedEvent.java │ │ ├── StartPartitionSessionEventImpl.java │ │ └── StopPartitionSessionEventImpl.java │ ├── settings │ ├── AlterAutoPartitioningWriteStrategySettings.java │ ├── AlterConsumerSettings.java │ ├── AlterPartitioningSettings.java │ ├── AlterTopicSettings.java │ ├── AutoPartitioningStrategy.java │ ├── AutoPartitioningWriteStrategySettings.java │ ├── CommitOffsetSettings.java │ ├── CreateTopicSettings.java │ ├── DescribeConsumerSettings.java │ ├── DescribeTopicSettings.java │ ├── DropTopicSettings.java │ ├── PartitioningSettings.java │ ├── ReadEventHandlersSettings.java │ ├── ReaderSettings.java │ ├── ReceiveSettings.java │ ├── SendSettings.java │ ├── StartPartitionSessionSettings.java │ ├── TopicReadSettings.java │ ├── UpdateOffsetsInTransactionSettings.java │ └── WriterSettings.java │ ├── utils │ ├── Encoder.java │ └── ProtoUtils.java │ └── write │ ├── AsyncWriter.java │ ├── InitResult.java │ ├── Message.java │ ├── QueueOverflowException.java │ ├── SyncWriter.java │ ├── WriteAck.java │ └── impl │ ├── AsyncWriterImpl.java │ ├── EnqueuedMessage.java │ ├── MessageSender.java │ ├── SyncWriterImpl.java │ ├── WriteSession.java │ └── WriterImpl.java └── test ├── java └── tech │ └── ydb │ └── topic │ └── impl │ ├── DisjointOffsetRangeSetTest.java │ └── YdbTopicsIntegrationTest.java └── resources └── log4j2.xml /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | indent_style = space 3 | insert_final_newline = true 4 | max_line_length = 120 5 | trim_trailing_whitespace = true 6 | 7 | [*.java] 8 | ij_java_block_brace_style = end_of_line 9 | ij_java_class_brace_style = end_of_line 10 | ij_java_class_count_to_use_import_on_demand = 9000 11 | ij_java_do_while_brace_force = always 12 | ij_java_doc_enable_formatting = false 13 | ij_java_for_brace_force = always 14 | ij_java_if_brace_force = always 15 | ij_java_imports_layout = java.**, |, javax.**, |, *, |, yandex.**, |, ru.yandex.**, |, tech.ydb.**, |, $* 16 | ij_java_insert_override_annotation = true 17 | ij_java_lambda_brace_style = end_of_line 18 | ij_java_method_brace_style = end_of_line 19 | ij_java_names_count_to_use_import_on_demand = 9000 20 | ij_java_space_after_colon = true 21 | ij_java_space_before_colon = true 22 | ij_java_spaces_around_additive_operators = true 23 | ij_java_spaces_around_annotation_eq = true 24 | ij_java_spaces_around_assignment_operators = true 25 | ij_java_spaces_around_bitwise_operators = true 26 | ij_java_spaces_around_equality_operators = true 27 | ij_java_spaces_around_lambda_arrow = true 28 | ij_java_spaces_around_logical_operators = true 29 | ij_java_spaces_around_method_ref_dbl_colon = false 30 | ij_java_spaces_around_multiplicative_operators = true 31 | ij_java_spaces_around_relational_operators = true 32 | ij_java_spaces_around_shift_operators = true 33 | ij_java_spaces_around_type_bounds_in_type_parameters = true 34 | ij_java_spaces_around_unary_operator = false 35 | ij_java_use_single_class_imports = true 36 | ij_java_while_brace_force = always 37 | -------------------------------------------------------------------------------- /.github/workflows/build.yaml: -------------------------------------------------------------------------------- 1 | name: Build YDB Java SDK 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | - develop 8 | - release* 9 | pull_request: 10 | type: [opened, reopened, edited, synchronize] 11 | 12 | jobs: 13 | build: 14 | name: Build YDB Java SDK 15 | runs-on: ubuntu-latest 16 | 17 | strategy: 18 | matrix: 19 | java: [ '8', '11', '17', '21'] 20 | 21 | env: 22 | MAVEN_ARGS: --batch-mode --update-snapshots -Dstyle.color=always -DYDB_DOCKER_ISOLATION=true 23 | 24 | steps: 25 | - uses: actions/checkout@v4 26 | 27 | - name: Set up JDK 28 | uses: actions/setup-java@v4 29 | with: 30 | java-version: ${{ matrix.java }} 31 | distribution: 'temurin' 32 | cache: 'maven' 33 | 34 | - name: Build with Maven 35 | run: mvn $MAVEN_ARGS verify 36 | 37 | coverage: 38 | if: github.repository == 'ydb-platform/ydb-java-sdk' 39 | name: Coverage YDB Java SDK 40 | runs-on: ubuntu-latest 41 | needs: build 42 | 43 | env: 44 | MAVEN_ARGS: --batch-mode --update-snapshots -Dstyle.color=always -DYDB_DOCKER_ISOLATION=true 45 | 46 | steps: 47 | - uses: actions/checkout@v4 48 | 49 | - name: Set up JDK 50 | uses: actions/setup-java@v4 51 | with: 52 | java-version: 8 53 | distribution: 'temurin' 54 | cache: 'maven' 55 | 56 | - name: Build with Maven 57 | run: mvn $MAVEN_ARGS test 58 | 59 | - name: Upload coverage to Codecov 60 | uses: codecov/codecov-action@v4 61 | with: 62 | token: ${{ secrets.CODECOV_TOKEN }} 63 | 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Maven build folders 2 | **/target 3 | 4 | # NetBeans project files 5 | **/nbactions.xml 6 | **/nb-configuration.xml 7 | 8 | # Intellij project files 9 | **/.idea/ 10 | **/*.iml 11 | **/*.iws 12 | **/*.ipr -------------------------------------------------------------------------------- /BUILD.md: -------------------------------------------------------------------------------- 1 | ## Building the YDB Java SDK 2 | 3 | ### Requirements 4 | 5 | * Java 8 or newer 6 | * Maven 3.0.0 or newer 7 | 8 | ### Installing in local repo 9 | 10 | You can install the SDK artifacts in your local maven cache by running the following command in project folder. 11 | During the build process, the working directory will be cleared, tests will be run, artifacts will be built and copied to the local repository. 12 | ``` 13 | mvn clean install 14 | ``` 15 | 16 | If you don't need the test executions, just disable them 17 | ``` 18 | mvn clean install -DskipTests=true 19 | ``` 20 | 21 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Notice to external contributors 2 | 3 | ## Common 4 | 5 | YDB is a free and open project and we appreciate to receive contributions from our community. 6 | 7 | ## Contributing code changes 8 | 9 | If you would like to contribute a new feature or a bug fix, please discuss your idea first on the GitHub issue. 10 | If there is no issue for your idea, please open one. It may be that somebody is already working on it, 11 | or that there are some complex obstacles that you should know about before starting the implementation. 12 | Usually there are several ways to fix a problem and it is important to find the right approach before spending time on a PR 13 | that cannot be merged. 14 | 15 | ## Provide a contribution 16 | 17 | To make a contribution you should submit a pull request. There will probably be discussion about the pull request and, if any changes are needed, we would love to work with you to get your pull request merged. 18 | 19 | ## Other questions 20 | 21 | If you have any questions, please mail us at info@ydb.tech. -------------------------------------------------------------------------------- /auth-api/src/main/java/tech/ydb/auth/AuthIdentity.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.auth; 2 | 3 | /** 4 | * Provides an authentication token for every request. 5 | */ 6 | public interface AuthIdentity extends AutoCloseable { 7 | 8 | String getToken(); 9 | 10 | @Override 11 | default void close() { 12 | } 13 | } 14 | 15 | -------------------------------------------------------------------------------- /auth-api/src/main/java/tech/ydb/auth/AuthProvider.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.auth; 2 | 3 | /** 4 | * Provides AuthIdentity instances for use in the operation of the YDB transport layer. 5 | */ 6 | public interface AuthProvider extends AuthRpcProvider { 7 | /** 8 | * Create new instance of AuthIdentity 9 | * @return new instance of AuthIdentity 10 | */ 11 | AuthIdentity createAuthIdentity(); 12 | 13 | @Override 14 | default AuthIdentity createAuthIdentity(Object rpc) { 15 | return createAuthIdentity(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /auth-api/src/main/java/tech/ydb/auth/AuthRpcProvider.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.auth; 2 | 3 | /** 4 | * Provides AuthIdentity instances for use in the operation of the YDB transport layer. 5 | * 6 | * @param Optional type specification for a transport-provided helper. 7 | */ 8 | public interface AuthRpcProvider { 9 | /** 10 | * Create new instance of AuthIdentity 11 | * @param rpc helper provided by a transport implementation 12 | * @return new instance of AuthIdentity 13 | */ 14 | AuthIdentity createAuthIdentity(T rpc); 15 | } 16 | -------------------------------------------------------------------------------- /auth-api/src/main/java/tech/ydb/auth/NopAuthProvider.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.auth; 2 | 3 | 4 | /** 5 | * Implementation of AuthProvider for anonymous connections 6 | */ 7 | public class NopAuthProvider implements AuthProvider { 8 | public static final NopAuthProvider INSTANCE = new NopAuthProvider(); 9 | 10 | protected NopAuthProvider() { 11 | } 12 | 13 | @Override 14 | public AuthIdentity createAuthIdentity() { 15 | return null; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /auth-api/src/main/java/tech/ydb/auth/TokenAuthProvider.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.auth; 2 | 3 | /** 4 | * Implementation of AuthProvider for connections with static token value 5 | */ 6 | public class TokenAuthProvider implements AuthProvider { 7 | private final TokenIdentity identity; 8 | 9 | public TokenAuthProvider(String token) { 10 | this.identity = new TokenIdentity(token); 11 | } 12 | 13 | @Override 14 | public AuthIdentity createAuthIdentity() { 15 | return identity; 16 | } 17 | 18 | private static final class TokenIdentity implements AuthIdentity { 19 | private final String token; 20 | 21 | private TokenIdentity(String token) { 22 | this.token = token; 23 | } 24 | 25 | @Override 26 | public String getToken() { 27 | return token; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /auth-providers/oauth2-provider/src/main/java/tech/ydb/auth/OAuth2AuthHelper.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.auth; 2 | 3 | import java.nio.file.Path; 4 | 5 | import tech.ydb.core.impl.auth.GrpcAuthRpc; 6 | 7 | /** 8 | * 9 | * @author Aleksandr Gorshenin 10 | */ 11 | public class OAuth2AuthHelper { 12 | private OAuth2AuthHelper() { } 13 | 14 | public static AuthIdentity configFileIdentity(Path file, GrpcAuthRpc rpc) { 15 | return OAuth2TokenExchangeProvider 16 | .fromFile(file.toFile()) 17 | .build() 18 | .createAuthIdentity(rpc); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /common/pom.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 4.0.0 7 | 8 | 9 | tech.ydb 10 | ydb-sdk-parent 11 | 2.3.16-SNAPSHOT 12 | 13 | 14 | ydb-sdk-common 15 | Common module of Java SDK for YDB 16 | Common module of Java SDK for YDB 17 | 18 | 19 | UTF-8 20 | 21 | 22 | 23 | 24 | tech.ydb 25 | ydb-sdk-core 26 | 27 | 28 | org.slf4j 29 | slf4j-api 30 | 31 | 32 | 33 | junit 34 | junit 35 | test 36 | 37 | 38 | org.apache.logging.log4j 39 | log4j-slf4j-impl 40 | test 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /common/src/main/java/tech/ydb/common/retry/ErrorPolicy.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.common.retry; 2 | 3 | /** 4 | * Recipes should use the configured error policy to decide how to retry 5 | * errors like unsuccessful {@link tech.ydb.core.StatusCode}. 6 | * 7 | * @author Aleksandr Gorshenin 8 | * @param Type of errors to check 9 | */ 10 | public interface ErrorPolicy { 11 | 12 | /** 13 | * Returns true if the given value should be retried 14 | * 15 | * @param value value to check 16 | * @return true if value is retryable 17 | */ 18 | boolean isRetryable(T value); 19 | 20 | /** 21 | * Returns true if the given exception should be retried 22 | * Usually exceptions are never retried, but some policies can implement more difficult logic 23 | * 24 | * @param ex exception to check 25 | * @return true if exception is retryable 26 | */ 27 | default boolean isRetryable(Exception ex) { 28 | return false; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /common/src/main/java/tech/ydb/common/retry/ExponentialBackoffRetry.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.common.retry; 2 | 3 | import java.util.concurrent.ThreadLocalRandom; 4 | 5 | 6 | /** 7 | * 8 | * @author Aleksandr Gorshenin 9 | */ 10 | public abstract class ExponentialBackoffRetry implements RetryPolicy { 11 | private final long backoffMs; 12 | private final int backoffCeiling; 13 | 14 | protected ExponentialBackoffRetry(long backoffMs, int backoffCeiling) { 15 | this.backoffMs = backoffMs; 16 | this.backoffCeiling = backoffCeiling; 17 | } 18 | 19 | protected long backoffTimeMillis(int retryNumber) { 20 | int slots = 1 << Math.min(retryNumber, backoffCeiling); 21 | long delay = backoffMs * slots; 22 | return delay + ThreadLocalRandom.current().nextLong(delay); 23 | } 24 | 25 | /** 26 | * Return current base of backoff delays 27 | * @return backoff base duration in milliseconds 28 | */ 29 | public long getBackoffMillis() { 30 | return backoffMs; 31 | } 32 | 33 | /** 34 | * Return current maximal level of backoff exponent 35 | * @return maximal level of backoff exponent 36 | */ 37 | public int getBackoffCeiling() { 38 | return backoffCeiling; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /common/src/main/java/tech/ydb/common/retry/RetryForever.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.common.retry; 2 | 3 | /** 4 | * 5 | * @author Aleksandr Gorshenin 6 | */ 7 | public class RetryForever implements RetryPolicy { 8 | private final long intervalMs; 9 | 10 | public RetryForever(long intervalMs) { 11 | this.intervalMs = intervalMs; 12 | } 13 | 14 | @Override 15 | public long nextRetryMs(int retryCount, long elapsedTimeMs) { 16 | return intervalMs; 17 | } 18 | 19 | /** 20 | * Return current interval of retries 21 | * @return retry interval in milliseconds 22 | */ 23 | public long getIntervalMillis() { 24 | return intervalMs; 25 | } 26 | 27 | /** 28 | * Create new retry policy with specified retry interval 29 | * @param ms new interval in milliseconds 30 | * @return updated retry policy */ 31 | public RetryForever withIntervalMs(long ms) { 32 | return new RetryForever(ms); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /common/src/main/java/tech/ydb/common/retry/RetryNTimes.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.common.retry; 2 | 3 | /** 4 | * 5 | * @author Aleksandr Gorshenin 6 | */ 7 | public class RetryNTimes extends ExponentialBackoffRetry { 8 | private final int maxRetries; 9 | 10 | public RetryNTimes(int maxRetries, long backoffMs, int backoffCeiling) { 11 | super(backoffMs, backoffCeiling); 12 | this.maxRetries = maxRetries; 13 | } 14 | 15 | @Override 16 | public long nextRetryMs(int retryCount, long elapsedTimeMs) { 17 | if (retryCount >= maxRetries) { 18 | return -1; 19 | } 20 | return backoffTimeMillis(retryCount); 21 | } 22 | 23 | /** 24 | * Return maximal count of retries 25 | * @return maximal count of retries 26 | */ 27 | public int getMaxRetries() { 28 | return maxRetries; 29 | } 30 | 31 | /** 32 | * Create new retry policy with specified max retries count 33 | * @param maxRetries new value of max count of retries 34 | * @return updated retry policy */ 35 | public RetryNTimes withMaxRetries(int maxRetries) { 36 | return new RetryNTimes(maxRetries, getBackoffMillis(), getBackoffCeiling()); 37 | } 38 | 39 | /** 40 | * Create new retry policy with specified backoff duration 41 | * @param ms new backoff duration in milliseconds 42 | * @return updated retry policy */ 43 | public RetryNTimes withBackoffMs(long ms) { 44 | return new RetryNTimes(maxRetries, ms, getBackoffCeiling()); 45 | } 46 | 47 | /** 48 | * Create new retry policy with specified backoff ceiling 49 | * @param ceiling new backoff ceiling 50 | * @return updated retry policy */ 51 | public RetryNTimes withBackoffCeiling(int ceiling) { 52 | return new RetryNTimes(maxRetries, getBackoffMillis(), ceiling); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /common/src/main/java/tech/ydb/common/retry/RetryPolicy.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.common.retry; 2 | 3 | /** 4 | * Abstracts the policy to use when retrying some actions 5 | * 6 | * @author Aleksandr Gorshenin 7 | */ 8 | public interface RetryPolicy { 9 | /** 10 | * Called when an operation is failed for some reason to determine if it should be retried. 11 | * And if so, returns the delay to make the next retry attempt after 12 | * 13 | * @param retryCount the number of times retried so far (0 the first time) 14 | * @param elapsedTimeMs the elapsed time in ms since the operation was attempted 15 | * @return delay for the next retry 16 | *
    17 | *
  • Positive number N - operation must be retried in N milliseconds
  • 18 | *
  • Zero : operation must be retried immediately
  • 19 | *
  • Negative number : retry is not allowed, operation must be failed
  • 20 | *
21 | */ 22 | long nextRetryMs(int retryCount, long elapsedTimeMs); 23 | } 24 | -------------------------------------------------------------------------------- /common/src/main/java/tech/ydb/common/transaction/TxMode.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.common.transaction; 2 | 3 | /** 4 | * 5 | * @author Aleksandr Gorshenin 6 | */ 7 | public enum TxMode { 8 | NONE, 9 | 10 | SERIALIZABLE_RW, 11 | SNAPSHOT_RO, 12 | STALE_RO, 13 | 14 | ONLINE_RO, 15 | ONLINE_INCONSISTENT_RO 16 | } 17 | -------------------------------------------------------------------------------- /common/src/main/java/tech/ydb/common/transaction/YdbTransaction.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.common.transaction; 2 | 3 | import java.util.concurrent.CompletableFuture; 4 | 5 | import tech.ydb.core.Status; 6 | 7 | /** 8 | * A base interface for all YDB transactions from different services 9 | * @author Nikolay Perfilov 10 | */ 11 | public interface YdbTransaction { 12 | 13 | /** 14 | * Returns identifier of the transaction or null if the transaction is not active = (not 15 | * started/committed/rolled back). When {@link YdbTransaction} is not active - any query on this object 16 | * starts a new transaction on server. When transaction is active any call of {@code commit}, 17 | * {@code rollback} or execution of any query with {@code commitAtEnd}=true finishes this transaction 18 | * 19 | * @return identifier of the transaction or null if the transaction is not active 20 | */ 21 | String getId(); 22 | 23 | /** 24 | * Returns {@link TxMode} with mode of the transaction 25 | * 26 | * @return the transaction mode 27 | */ 28 | TxMode getTxMode(); 29 | 30 | default boolean isActive() { 31 | return getId() != null; 32 | } 33 | 34 | String getSessionId(); 35 | 36 | CompletableFuture getStatusFuture(); 37 | } 38 | -------------------------------------------------------------------------------- /common/src/main/java/tech/ydb/common/transaction/impl/YdbTransactionImpl.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.common.transaction.impl; 2 | 3 | import java.util.concurrent.CompletableFuture; 4 | import java.util.concurrent.atomic.AtomicReference; 5 | 6 | import tech.ydb.common.transaction.TxMode; 7 | import tech.ydb.common.transaction.YdbTransaction; 8 | import tech.ydb.core.Status; 9 | 10 | /** 11 | * @author Nikolay Perfilov 12 | */ 13 | public abstract class YdbTransactionImpl implements YdbTransaction { 14 | protected final TxMode txMode; 15 | protected final AtomicReference txId; 16 | protected final AtomicReference> statusFuture = new AtomicReference<>( 17 | new CompletableFuture<>()); 18 | 19 | protected YdbTransactionImpl(TxMode txMode, String txId) { 20 | this.txMode = txMode; 21 | this.txId = new AtomicReference<>(txId); 22 | } 23 | 24 | @Override 25 | public String getId() { 26 | return txId.get(); 27 | } 28 | 29 | @Override 30 | public TxMode getTxMode() { 31 | return txMode; 32 | } 33 | 34 | @Override 35 | public CompletableFuture getStatusFuture() { 36 | return statusFuture.get(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /common/src/test/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /config/ydb.suppressions.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /coordination/src/main/java/tech/ydb/coordination/SemaphoreLease.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.coordination; 2 | 3 | import java.util.concurrent.CompletableFuture; 4 | 5 | 6 | /** 7 | * @author Aleksandr Gorshenin 8 | */ 9 | public interface SemaphoreLease { 10 | String getSemaphoreName(); 11 | 12 | CoordinationSession getSession(); 13 | 14 | CompletableFuture release(); 15 | } 16 | -------------------------------------------------------------------------------- /coordination/src/main/java/tech/ydb/coordination/description/SemaphoreChangedEvent.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.coordination.description; 2 | 3 | import tech.ydb.proto.coordination.SessionResponse; 4 | 5 | public class SemaphoreChangedEvent { 6 | private final boolean dataChanged; 7 | private final boolean ownersChanged; 8 | 9 | public SemaphoreChangedEvent(SessionResponse.DescribeSemaphoreChanged event) { 10 | this.dataChanged = event.getDataChanged(); 11 | this.ownersChanged = event.getOwnersChanged(); 12 | } 13 | 14 | public boolean isDataChanged() { 15 | return dataChanged; 16 | } 17 | 18 | public boolean isOwnersChanged() { 19 | return ownersChanged; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /coordination/src/main/java/tech/ydb/coordination/description/SemaphoreWatcher.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.coordination.description; 2 | 3 | import java.util.concurrent.CompletableFuture; 4 | 5 | import tech.ydb.core.Result; 6 | 7 | /** 8 | * 9 | * @author Aleksandr Gorshenin 10 | */ 11 | public class SemaphoreWatcher { 12 | private final SemaphoreDescription description; 13 | private final CompletableFuture> changedFuture; 14 | 15 | public SemaphoreWatcher(SemaphoreDescription desc, CompletableFuture> changed) { 16 | this.description = desc; 17 | this.changedFuture = changed; 18 | } 19 | 20 | public SemaphoreDescription getDescription() { 21 | return description; 22 | } 23 | 24 | public CompletableFuture> getChangedFuture() { 25 | return changedFuture; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /coordination/src/main/java/tech/ydb/coordination/impl/CoordinationServiceImpl.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.coordination.impl; 2 | 3 | import javax.annotation.WillNotClose; 4 | 5 | import tech.ydb.coordination.CoordinationClient; 6 | import tech.ydb.core.grpc.GrpcTransport; 7 | 8 | /** 9 | * 10 | * @author Aleksandr Gorshenin 11 | */ 12 | public class CoordinationServiceImpl { 13 | private CoordinationServiceImpl() { } 14 | 15 | public static CoordinationClient newClient(@WillNotClose GrpcTransport transport) { 16 | Rpc rpc = new RpcImpl(transport); 17 | return new ClientImpl(rpc); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /coordination/src/main/java/tech/ydb/coordination/impl/LeaseImpl.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.coordination.impl; 2 | 3 | import java.util.concurrent.CompletableFuture; 4 | 5 | import tech.ydb.coordination.CoordinationSession; 6 | import tech.ydb.coordination.SemaphoreLease; 7 | 8 | /** 9 | * 10 | * @author Aleksandr Gorshenin 11 | */ 12 | class LeaseImpl implements SemaphoreLease { 13 | private final SessionImpl session; 14 | private final String name; 15 | 16 | LeaseImpl(SessionImpl session, String name) { 17 | this.session = session; 18 | this.name = name; 19 | } 20 | 21 | @Override 22 | public CoordinationSession getSession() { 23 | return session; 24 | } 25 | 26 | @Override 27 | public String getSemaphoreName() { 28 | return name; 29 | } 30 | 31 | @Override 32 | public CompletableFuture release() { 33 | return session.releaseSemaphore(name).thenApply(r -> null); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /coordination/src/main/java/tech/ydb/coordination/impl/Rpc.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.coordination.impl; 2 | 3 | import java.util.concurrent.CompletableFuture; 4 | import java.util.concurrent.ScheduledExecutorService; 5 | 6 | import tech.ydb.coordination.description.NodeConfig; 7 | import tech.ydb.core.Result; 8 | import tech.ydb.core.Status; 9 | import tech.ydb.core.grpc.GrpcReadWriteStream; 10 | import tech.ydb.core.grpc.GrpcRequestSettings; 11 | import tech.ydb.proto.coordination.AlterNodeRequest; 12 | import tech.ydb.proto.coordination.CreateNodeRequest; 13 | import tech.ydb.proto.coordination.DescribeNodeRequest; 14 | import tech.ydb.proto.coordination.DropNodeRequest; 15 | import tech.ydb.proto.coordination.SessionRequest; 16 | import tech.ydb.proto.coordination.SessionResponse; 17 | 18 | /** 19 | * @author Kirill Kurdyukov 20 | */ 21 | interface Rpc { 22 | 23 | GrpcReadWriteStream createSession(GrpcRequestSettings settings); 24 | 25 | CompletableFuture createNode(CreateNodeRequest request, GrpcRequestSettings settings); 26 | 27 | CompletableFuture alterNode(AlterNodeRequest request, GrpcRequestSettings settings); 28 | 29 | CompletableFuture dropNode(DropNodeRequest request, GrpcRequestSettings settings); 30 | 31 | CompletableFuture> describeNode(DescribeNodeRequest request, GrpcRequestSettings settings); 32 | 33 | String getDatabase(); 34 | 35 | ScheduledExecutorService getScheduler(); 36 | } 37 | -------------------------------------------------------------------------------- /coordination/src/main/java/tech/ydb/coordination/settings/CoordinationNodeSettings.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.coordination.settings; 2 | 3 | import tech.ydb.coordination.description.NodeConfig; 4 | import tech.ydb.core.settings.OperationSettings; 5 | 6 | /** 7 | * @author Kirill Kurdyukov 8 | */ 9 | public class CoordinationNodeSettings extends OperationSettings { 10 | private final NodeConfig config; 11 | 12 | private CoordinationNodeSettings(Builder builder) { 13 | super(builder); 14 | this.config = builder.config; 15 | } 16 | 17 | public NodeConfig getConfig() { 18 | return this.config; 19 | } 20 | 21 | public static Builder newBuilder() { 22 | return new Builder(); 23 | } 24 | 25 | public static class Builder extends OperationSettings.OperationBuilder { 26 | private NodeConfig config = NodeConfig.create(); 27 | 28 | public Builder withNodeConfig(NodeConfig config) { 29 | this.config = config; 30 | return this; 31 | } 32 | 33 | @Override 34 | public CoordinationNodeSettings build() { 35 | return new CoordinationNodeSettings(this); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /coordination/src/main/java/tech/ydb/coordination/settings/DescribeCoordinationNodeSettings.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.coordination.settings; 2 | 3 | import tech.ydb.core.settings.OperationSettings; 4 | 5 | /** 6 | * @author Kirill Kurdyukov 7 | */ 8 | public class DescribeCoordinationNodeSettings extends OperationSettings { 9 | private DescribeCoordinationNodeSettings(Builder builder) { 10 | super(builder); 11 | } 12 | 13 | public static Builder newBuilder() { 14 | return new Builder(); 15 | } 16 | 17 | public static class Builder extends OperationBuilder { 18 | @Override 19 | public DescribeCoordinationNodeSettings build() { 20 | return new DescribeCoordinationNodeSettings(this); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /coordination/src/main/java/tech/ydb/coordination/settings/DescribeSemaphoreMode.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.coordination.settings; 2 | 3 | /** 4 | * 5 | * @author Aleksandr Gorshenin 6 | */ 7 | public enum DescribeSemaphoreMode { 8 | /** 9 | * Describe only semaphore's data (name, user-defined data and others) 10 | */ 11 | DATA_ONLY(false, false), 12 | /** 13 | * Include owners list to describe result 14 | */ 15 | WITH_OWNERS(true, false), 16 | /** 17 | * Include waiters list to describe result 18 | */ 19 | WITH_WAITERS(false, true), 20 | /** 21 | * Include waiters and owners lists to describe result 22 | */ 23 | WITH_OWNERS_AND_WAITERS(true, true); 24 | 25 | private final boolean includeOwners; 26 | private final boolean includeWaiters; 27 | 28 | DescribeSemaphoreMode(boolean includeOwners, boolean includeWaiters) { 29 | this.includeOwners = includeOwners; 30 | this.includeWaiters = includeWaiters; 31 | } 32 | 33 | public boolean includeOwners() { 34 | return includeOwners; 35 | } 36 | 37 | public boolean includeWaiters() { 38 | return includeWaiters; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /coordination/src/main/java/tech/ydb/coordination/settings/DropCoordinationNodeSettings.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.coordination.settings; 2 | 3 | import tech.ydb.core.settings.OperationSettings; 4 | 5 | /** 6 | * @author Kirill Kurdyukov 7 | */ 8 | public class DropCoordinationNodeSettings extends OperationSettings { 9 | 10 | private DropCoordinationNodeSettings(Builder builder) { 11 | super(builder); 12 | } 13 | 14 | public static Builder newBuilder() { 15 | return new Builder(); 16 | } 17 | 18 | public static class Builder extends OperationBuilder { 19 | @Override 20 | public DropCoordinationNodeSettings build() { 21 | return new DropCoordinationNodeSettings(this); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /coordination/src/main/java/tech/ydb/coordination/settings/WatchSemaphoreMode.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.coordination.settings; 2 | 3 | /** 4 | * 5 | * @author Aleksandr Gorshenin 6 | */ 7 | public enum WatchSemaphoreMode { 8 | /** 9 | * Watch for changes in semaphore data 10 | */ 11 | WATCH_DATA(true, false), 12 | /** 13 | * Watch for changes in semaphore owners 14 | */ 15 | WATCH_OWNERS(false, true), 16 | /** 17 | * Watch for changes in semaphore data or owners 18 | */ 19 | WATCH_DATA_AND_OWNERS(true, true); 20 | 21 | private final boolean watchData; 22 | private final boolean watchOwners; 23 | 24 | WatchSemaphoreMode(boolean watchData, boolean watchOwners) { 25 | this.watchData = watchData; 26 | this.watchOwners = watchOwners; 27 | } 28 | 29 | public boolean watchData() { 30 | return watchData; 31 | } 32 | 33 | public boolean watchOwners() { 34 | return watchOwners; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /coordination/src/test/java/tech/ydb/coordination/impl/ClientTest.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.coordination.impl; 2 | 3 | import java.util.concurrent.CompletableFuture; 4 | 5 | import org.junit.Assert; 6 | import org.junit.Before; 7 | import org.junit.Test; 8 | import org.mockito.ArgumentCaptor; 9 | import org.mockito.Mockito; 10 | 11 | import tech.ydb.core.Status; 12 | import tech.ydb.proto.coordination.CreateNodeRequest; 13 | 14 | /** 15 | * 16 | * @author Aleksandr Gorshenin 17 | */ 18 | public class ClientTest { 19 | private final Rpc rpc = Mockito.mock(Rpc.class); 20 | private final ClientImpl client = new ClientImpl(rpc); 21 | 22 | @Before 23 | public void setUp() { 24 | Mockito.when(rpc.createNode(Mockito.any(), Mockito.any())) 25 | .thenReturn(CompletableFuture.completedFuture(Status.SUCCESS)); 26 | Mockito.when(rpc.getDatabase()).thenReturn("/mocked"); 27 | } 28 | 29 | @Test 30 | public void validatePathTest() { 31 | ArgumentCaptor requestCapture = ArgumentCaptor.forClass(CreateNodeRequest.class); 32 | 33 | client.createNode("test"); 34 | client.createNode("/test"); 35 | 36 | Mockito.verify(rpc, Mockito.times(2)).createNode(requestCapture.capture(), Mockito.any()); 37 | 38 | Assert.assertEquals("/mocked/test", requestCapture.getAllValues().get(0).getPath()); 39 | Assert.assertEquals("/test", requestCapture.getAllValues().get(1).getPath()); 40 | } 41 | 42 | @Test(expected = IllegalArgumentException.class) 43 | public void nullPathError() { 44 | client.createNode(null); 45 | } 46 | 47 | @Test(expected = IllegalArgumentException.class) 48 | public void emptyPathError() { 49 | client.createNode(""); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /coordination/src/test/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /core/src/main/java/tech/ydb/core/Constants.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.core; 2 | 3 | /** 4 | * @author Sergey Polovko 5 | */ 6 | final class Constants { 7 | static final int SERVER_STATUSES_FIRST = 400000; 8 | static final int TRANSPORT_STATUSES_FIRST = 401000; 9 | static final int TRANSPORT_STATUSES_LAST = 401999; 10 | static final int INTERNAL_CLIENT_FIRST = 402000; 11 | 12 | private Constants() { } 13 | } 14 | -------------------------------------------------------------------------------- /core/src/main/java/tech/ydb/core/auth/AuthIdentity.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.core.auth; 2 | 3 | /** 4 | * @deprecated 5 | * Use {@link tech.ydb.auth.AuthIdentity} instead. 6 | */ 7 | @Deprecated 8 | public interface AuthIdentity extends tech.ydb.auth.AuthIdentity { 9 | } 10 | 11 | -------------------------------------------------------------------------------- /core/src/main/java/tech/ydb/core/auth/AuthProvider.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.core.auth; 2 | 3 | import tech.ydb.auth.AuthRpcProvider; 4 | 5 | /** 6 | * @deprecated 7 | * Use {@link tech.ydb.auth.AuthProvider} instead. 8 | */ 9 | @Deprecated 10 | public interface AuthProvider extends AuthRpcProvider { 11 | @Override 12 | AuthIdentity createAuthIdentity(AuthRpc rpc); 13 | } 14 | -------------------------------------------------------------------------------- /core/src/main/java/tech/ydb/core/auth/AuthRpc.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.core.auth; 2 | 3 | /** 4 | * @deprecated 5 | */ 6 | @Deprecated 7 | public interface AuthRpc { 8 | } 9 | -------------------------------------------------------------------------------- /core/src/main/java/tech/ydb/core/auth/NopAuthProvider.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.core.auth; 2 | 3 | /** 4 | * @deprecated 5 | * Use {@link tech.ydb.auth.NopAuthProvider} instead. 6 | */ 7 | @Deprecated 8 | public class NopAuthProvider extends tech.ydb.auth.NopAuthProvider { 9 | } 10 | -------------------------------------------------------------------------------- /core/src/main/java/tech/ydb/core/auth/TokenAuthProvider.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.core.auth; 2 | 3 | /** 4 | * @deprecated 5 | * Use {@link tech.ydb.auth.TokenAuthProvider} instead. 6 | */ 7 | @Deprecated 8 | public class TokenAuthProvider extends tech.ydb.auth.TokenAuthProvider { 9 | public TokenAuthProvider(String token) { 10 | super(token); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /core/src/main/java/tech/ydb/core/grpc/GrpcCompression.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.core.grpc; 2 | 3 | /** 4 | * 5 | * @author Aleksandr Gorshenin 6 | */ 7 | public enum GrpcCompression { 8 | NO_COMPRESSION(null), 9 | GZIP("gzip"); 10 | 11 | private final String compressor; 12 | 13 | GrpcCompression(String compressor) { 14 | this.compressor = compressor; 15 | } 16 | 17 | public String compressor() { 18 | return this.compressor; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /core/src/main/java/tech/ydb/core/grpc/GrpcReadStream.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.core.grpc; 2 | 3 | import java.util.concurrent.CompletableFuture; 4 | 5 | import tech.ydb.core.Status; 6 | 7 | /** 8 | * 9 | * @author Aleksandr Gorshenin 10 | * @param type of message received 11 | */ 12 | public interface GrpcReadStream { 13 | interface Observer { 14 | void onNext(R value); 15 | } 16 | 17 | /** 18 | * Start a stream, using {@code observer} for processing response messages. 19 | * Returns future with the stream finish status. 20 | * 21 | * @param observer receives response messages 22 | * @return future with the stream finish status 23 | * @throws IllegalStateException if a method (including {@code start()}) on this class has been 24 | * called. 25 | */ 26 | CompletableFuture start(Observer observer); 27 | 28 | /** 29 | * Prevent any further processing for this {@code GrpcReadStream}. No further messages may be sent or 30 | * will be received. The server is informed of cancellations, but may not stop processing the 31 | * call. The future for the stream finish status will be completed with CANCELLED code 32 | */ 33 | void cancel(); 34 | } 35 | -------------------------------------------------------------------------------- /core/src/main/java/tech/ydb/core/grpc/GrpcReadWriteStream.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.core.grpc; 2 | 3 | 4 | /** 5 | * 6 | * @author Aleksandr Gorshenin 7 | * @param type of message received 8 | * @param type of message to be sent to the server 9 | */ 10 | public interface GrpcReadWriteStream extends GrpcReadStream { 11 | String authToken(); 12 | 13 | /** 14 | * Send a request message to the server. 15 | * @param message message to be sent to the server. 16 | */ 17 | void sendNext(W message); 18 | 19 | /** 20 | * Close the call for next message sending. Incoming response messages are unaffected. This 21 | * should be called when no more messages will be sent from the client. 22 | */ 23 | void close(); 24 | } 25 | -------------------------------------------------------------------------------- /core/src/main/java/tech/ydb/core/grpc/YdbHeaders.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.core.grpc; 2 | 3 | import io.grpc.Metadata; 4 | 5 | 6 | /** 7 | * @author Sergey Polovko 8 | */ 9 | public class YdbHeaders { 10 | public static final Metadata.Key DATABASE = 11 | Metadata.Key.of("x-ydb-database", Metadata.ASCII_STRING_MARSHALLER); 12 | 13 | public static final Metadata.Key TRACE_ID = 14 | Metadata.Key.of("x-ydb-trace-id", Metadata.ASCII_STRING_MARSHALLER); 15 | 16 | public static final Metadata.Key BUILD_INFO = 17 | Metadata.Key.of("x-ydb-sdk-build-info", Metadata.ASCII_STRING_MARSHALLER); 18 | 19 | public static final Metadata.Key YDB_CLIENT_CAPABILITIES = 20 | Metadata.Key.of("x-ydb-client-capabilities", Metadata.ASCII_STRING_MARSHALLER); 21 | 22 | public static final Metadata.Key YDB_SERVER_HINTS = 23 | Metadata.Key.of("x-ydb-server-hints", Metadata.ASCII_STRING_MARSHALLER); 24 | 25 | private YdbHeaders() { } 26 | } 27 | -------------------------------------------------------------------------------- /core/src/main/java/tech/ydb/core/impl/auth/YdbCallCredentials.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.core.impl.auth; 2 | 3 | import java.util.concurrent.Executor; 4 | 5 | import io.grpc.CallCredentials; 6 | import io.grpc.Metadata; 7 | import io.grpc.Status; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | import tech.ydb.auth.AuthIdentity; 12 | 13 | 14 | /** 15 | * @author Sergey Polovko 16 | */ 17 | class YdbCallCredentials extends CallCredentials { 18 | static final Metadata.Key AUTH_TICKET = 19 | Metadata.Key.of("x-ydb-auth-ticket", Metadata.ASCII_STRING_MARSHALLER); 20 | 21 | private static final Logger logger = LoggerFactory.getLogger(YdbCallCredentials.class); 22 | 23 | private final AuthIdentity identity; 24 | 25 | YdbCallCredentials(AuthIdentity identity) { 26 | this.identity = identity; 27 | } 28 | 29 | @Override 30 | public void applyRequestMetadata(RequestInfo requestInfo, Executor appExecutor, MetadataApplier applier) { 31 | try { 32 | Metadata headers = new Metadata(); 33 | String token = identity.getToken(); 34 | if (token != null) { 35 | headers.put(AUTH_TICKET, token); 36 | } 37 | applier.apply(headers); 38 | } catch (Exception ex) { 39 | logger.error("unexpected exception ", ex); 40 | applier.fail(Status.INTERNAL.withDescription("get token exception").withCause(ex)); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /core/src/main/java/tech/ydb/core/impl/call/EmptyStream.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.core.impl.call; 2 | 3 | import java.util.concurrent.CompletableFuture; 4 | 5 | import tech.ydb.core.Status; 6 | import tech.ydb.core.grpc.GrpcReadStream; 7 | import tech.ydb.core.grpc.GrpcReadWriteStream; 8 | 9 | /** 10 | * Empty stream without messages but with status 11 | * @author Aleksandr Gorshenin 12 | * @param type of message received 13 | * @param type of message to be sent to the server 14 | */ 15 | public class EmptyStream implements GrpcReadWriteStream { 16 | private final Status status; 17 | 18 | public EmptyStream(Status status) { 19 | this.status = status; 20 | } 21 | 22 | @Override 23 | public String authToken() { 24 | return null; 25 | } 26 | 27 | @Override 28 | public void cancel() { 29 | // nothing 30 | } 31 | 32 | @Override 33 | public CompletableFuture start(GrpcReadStream.Observer observer) { 34 | return CompletableFuture.completedFuture(status); 35 | } 36 | 37 | @Override 38 | public void sendNext(W message) { 39 | // nothing 40 | } 41 | 42 | @Override 43 | public void close() { 44 | // nothing 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /core/src/main/java/tech/ydb/core/impl/call/GrpcStatusHandler.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.core.impl.call; 2 | 3 | import io.grpc.Metadata; 4 | import io.grpc.Status; 5 | 6 | /** 7 | * 8 | * @author Aleksandr Gorshenin 9 | */ 10 | public interface GrpcStatusHandler { 11 | void accept(Status status, Metadata trailers); 12 | } 13 | -------------------------------------------------------------------------------- /core/src/main/java/tech/ydb/core/impl/call/ProxyReadStream.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.core.impl.call; 2 | 3 | import java.util.concurrent.CompletableFuture; 4 | 5 | import tech.ydb.core.Status; 6 | import tech.ydb.core.grpc.GrpcReadStream; 7 | 8 | /** 9 | * 10 | * @author Aleksandr Gorshenin 11 | * @param type of origin stream message 12 | * @param new stream message type 13 | */ 14 | public class ProxyReadStream implements GrpcReadStream { 15 | public interface MessageFunctor { 16 | void apply(BaseR message, CompletableFuture promise, Observer observer); 17 | } 18 | 19 | private final GrpcReadStream origin; 20 | private final MessageFunctor functor; 21 | private final CompletableFuture future = new CompletableFuture<>(); 22 | 23 | public ProxyReadStream(GrpcReadStream origin, MessageFunctor functor) { 24 | this.origin = origin; 25 | this.functor = functor; 26 | } 27 | 28 | @Override 29 | public CompletableFuture start(Observer observer) { 30 | origin.start(response -> functor.apply(response, future, observer)).whenComplete((status, th) -> { 31 | // promise may be completed by functor and in that case this code will be ignored 32 | if (th != null) { 33 | future.completeExceptionally(th); 34 | } 35 | if (status != null) { 36 | future.complete(status); 37 | } 38 | }); 39 | 40 | return future; 41 | } 42 | 43 | @Override 44 | public void cancel() { 45 | origin.cancel(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /core/src/main/java/tech/ydb/core/impl/pool/ChannelFactoryLoader.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.core.impl.pool; 2 | 3 | 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | 8 | /** 9 | * 10 | * @author Aleksandr Gorshenin 11 | */ 12 | public class ChannelFactoryLoader { 13 | private static final Logger logger = LoggerFactory.getLogger(ChannelFactoryLoader.class); 14 | 15 | private ChannelFactoryLoader() { } 16 | 17 | public static ManagedChannelFactory.Builder load() { 18 | return FactoryLoader.factory; 19 | } 20 | 21 | private static class FactoryLoader { 22 | private static final String SHADED_DEPS = "io.grpc.netty.shaded.io.grpc.netty.NettyChannelBuilder"; 23 | private static final String NETTY_DEPS = "io.grpc.netty.NettyChannelBuilder"; 24 | 25 | private static ManagedChannelFactory.Builder factory; 26 | 27 | static { 28 | boolean ok = tryLoad(SHADED_DEPS, ShadedNettyChannelFactory.build()) 29 | || tryLoad(NETTY_DEPS, NettyChannelFactory.build()); 30 | if (!ok) { 31 | throw new IllegalStateException("Cannot load any ManagedChannelFactory!! " 32 | + "Classpath must contain grpc-netty or grpc-netty-shaded"); 33 | } 34 | } 35 | 36 | private static boolean tryLoad(String name, ManagedChannelFactory.Builder f) { 37 | try { 38 | Class.forName(name); 39 | logger.info("class {} is found, use {}", name, f); 40 | factory = f; 41 | return true; 42 | } catch (ClassNotFoundException ex) { 43 | logger.info("class {} is not found", name); 44 | return false; 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /core/src/main/java/tech/ydb/core/impl/pool/EndpointRecord.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.core.impl.pool; 2 | 3 | import java.util.Objects; 4 | 5 | /** 6 | * @author Nikolay Perfilov 7 | */ 8 | public class EndpointRecord { 9 | private final String host; 10 | private final String hostAndPort; 11 | private final String locationDC; 12 | private final String authority; 13 | private final int port; 14 | private final int nodeId; 15 | 16 | public EndpointRecord(String host, int port, int nodeId, String locationDC, String authority) { 17 | this.host = Objects.requireNonNull(host); 18 | this.port = port; 19 | this.hostAndPort = host + ":" + port; 20 | this.nodeId = nodeId; 21 | this.locationDC = locationDC; 22 | if (authority != null && !authority.isEmpty()) { 23 | this.authority = authority; 24 | } else { 25 | this.authority = null; 26 | } 27 | } 28 | 29 | public EndpointRecord(String host, int port) { 30 | this(host, port, 0, null, null); 31 | } 32 | 33 | public String getHost() { 34 | return host; 35 | } 36 | 37 | public String getAuthority() { 38 | return authority; 39 | } 40 | 41 | public int getPort() { 42 | return port; 43 | } 44 | 45 | public String getHostAndPort() { 46 | return hostAndPort; 47 | } 48 | 49 | public int getNodeId() { 50 | return nodeId; 51 | } 52 | 53 | public String getLocation() { 54 | return locationDC; 55 | } 56 | 57 | @Override 58 | public String toString() { 59 | return "Endpoint{host=" + host + ", port=" + port + ", node=" + nodeId + 60 | ", location=" + locationDC + ", overrideAuthority=" + authority + "}"; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /core/src/main/java/tech/ydb/core/impl/pool/ManagedChannelFactory.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.core.impl.pool; 2 | 3 | import io.grpc.ManagedChannel; 4 | 5 | import tech.ydb.core.grpc.GrpcTransportBuilder; 6 | 7 | /** 8 | * @author Nikolay Perfilov 9 | * @author Aleksandr Gorshenin 10 | */ 11 | public interface ManagedChannelFactory { 12 | interface Builder { 13 | ManagedChannelFactory buildFactory(GrpcTransportBuilder builder); 14 | } 15 | 16 | ManagedChannel newManagedChannel(String host, int port, String authority); 17 | 18 | long getConnectTimeoutMs(); 19 | } 20 | -------------------------------------------------------------------------------- /core/src/main/java/tech/ydb/core/operation/AsyncOperation.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.core.operation; 2 | 3 | import java.util.concurrent.ScheduledExecutorService; 4 | 5 | /** 6 | * 7 | * @author Aleksandr Gorshenin 8 | */ 9 | interface AsyncOperation extends Operation { 10 | ScheduledExecutorService getScheduler(); 11 | } 12 | -------------------------------------------------------------------------------- /core/src/main/java/tech/ydb/core/operation/FailedOperation.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.core.operation; 2 | 3 | import java.util.concurrent.CompletableFuture; 4 | import java.util.function.Function; 5 | 6 | import tech.ydb.core.Result; 7 | import tech.ydb.core.Status; 8 | 9 | /** 10 | * 11 | * @author Aleksandr Gorshenin 12 | */ 13 | class FailedOperation implements Operation { 14 | private final T value; 15 | private final Status status; 16 | 17 | FailedOperation(T value, Status status) { 18 | this.value = value; 19 | this.status = status; 20 | } 21 | 22 | @Override 23 | public String getId() { 24 | return null; 25 | } 26 | 27 | @Override 28 | public boolean isReady() { 29 | return true; 30 | } 31 | 32 | @Override 33 | public T getValue() { 34 | return value; 35 | } 36 | 37 | @Override 38 | public CompletableFuture cancel() { 39 | return CompletableFuture.completedFuture(status); 40 | } 41 | 42 | @Override 43 | public CompletableFuture forget() { 44 | return CompletableFuture.completedFuture(status); 45 | } 46 | 47 | @Override 48 | public CompletableFuture> fetch() { 49 | return CompletableFuture.completedFuture(Result.fail(status)); 50 | } 51 | 52 | @Override 53 | public Operation transform(Function func) { 54 | return new FailedOperation<>(func.apply(value), status); 55 | } 56 | 57 | @Override 58 | public String toString() { 59 | return "FailedOperation{status=" + status + "}"; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /core/src/main/java/tech/ydb/core/operation/StatusExtractor.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.core.operation; 2 | 3 | import java.util.List; 4 | import java.util.function.Function; 5 | 6 | import tech.ydb.core.Issue; 7 | import tech.ydb.core.Result; 8 | import tech.ydb.core.Status; 9 | import tech.ydb.core.StatusCode; 10 | import tech.ydb.proto.StatusCodesProtos.StatusIds; 11 | import tech.ydb.proto.YdbIssueMessage.IssueMessage; 12 | 13 | public class StatusExtractor implements Function, Result> { 14 | private final Function statusMethod; 15 | private final Function> issuesMethod; 16 | 17 | private StatusExtractor(Function status, Function> issues) { 18 | this.statusMethod = status; 19 | this.issuesMethod = issues; 20 | } 21 | 22 | @Override 23 | public Result apply(Result result) { 24 | if (!result.isSuccess()) { 25 | return result; 26 | } 27 | 28 | R resp = result.getValue(); 29 | Status status = Status.of( 30 | StatusCode.fromProto(statusMethod.apply(resp)), 31 | result.getStatus().getConsumedRu(), 32 | Issue.fromPb(issuesMethod.apply(resp)) 33 | ); 34 | 35 | return status.isSuccess() ? Result.success(resp, status) : Result.fail(status); 36 | } 37 | 38 | public static StatusExtractor of( 39 | Function statusMethod, 40 | Function> issuerMethod 41 | ) { 42 | return new StatusExtractor<>(statusMethod, issuerMethod); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /core/src/main/java/tech/ydb/core/operation/StatusMapper.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.core.operation; 2 | 3 | import java.util.List; 4 | import java.util.function.Function; 5 | 6 | import tech.ydb.core.Issue; 7 | import tech.ydb.core.Result; 8 | import tech.ydb.core.Status; 9 | import tech.ydb.core.StatusCode; 10 | import tech.ydb.proto.StatusCodesProtos.StatusIds; 11 | import tech.ydb.proto.YdbIssueMessage.IssueMessage; 12 | 13 | public class StatusMapper implements Function, Status> { 14 | private final Function statusMethod; 15 | private final Function> issuesMethod; 16 | 17 | private StatusMapper(Function status, Function> issues) { 18 | this.statusMethod = status; 19 | this.issuesMethod = issues; 20 | } 21 | 22 | @Override 23 | public Status apply(Result result) { 24 | if (!result.isSuccess()) { 25 | return result.getStatus(); 26 | } 27 | 28 | R resp = result.getValue(); 29 | return Status.of( 30 | StatusCode.fromProto(statusMethod.apply(resp)), 31 | result.getStatus().getConsumedRu(), 32 | Issue.fromPb(issuesMethod.apply(resp)) 33 | ); 34 | } 35 | 36 | public static StatusMapper of( 37 | Function statusMethod, 38 | Function> issuesMethod 39 | ) { 40 | return new StatusMapper<>(statusMethod, issuesMethod); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /core/src/main/java/tech/ydb/core/utils/FutureTools.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.core.utils; 2 | 3 | import java.util.concurrent.CompletableFuture; 4 | import java.util.concurrent.CompletionException; 5 | 6 | /** 7 | * 8 | * @author Aleksandr Gorshenin 9 | */ 10 | public class FutureTools { 11 | private FutureTools() { } 12 | 13 | public static Throwable unwrapCompletionException(Throwable throwable) { 14 | Throwable cause = throwable; 15 | while (cause instanceof CompletionException && cause.getCause() != null) { 16 | cause = cause.getCause(); 17 | } 18 | return cause; 19 | } 20 | 21 | public static CompletableFuture failedFuture(Throwable t) { 22 | CompletableFuture f = new CompletableFuture<>(); 23 | f.completeExceptionally(t); 24 | return f; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /core/src/main/java/tech/ydb/core/utils/ProtobufUtils.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.core.utils; 2 | 3 | import java.time.Instant; 4 | 5 | import javax.annotation.Nullable; 6 | 7 | import com.google.protobuf.Duration; 8 | import com.google.protobuf.Timestamp; 9 | 10 | /** 11 | * @author Nikolay Perfilov 12 | */ 13 | public class ProtobufUtils { 14 | 15 | private ProtobufUtils() { } 16 | 17 | @Nullable 18 | public static Duration durationToProto(@Nullable java.time.Duration duration) { 19 | return duration == null 20 | ? null 21 | : Duration.newBuilder() 22 | .setSeconds(duration.getSeconds()) 23 | .setNanos(duration.getNano()) 24 | .build(); 25 | } 26 | 27 | public static Timestamp instantToProto(java.time.Instant instant) { 28 | return Timestamp.newBuilder() 29 | .setSeconds(instant.getEpochSecond()) 30 | .setNanos(instant.getNano()) 31 | .build(); 32 | } 33 | 34 | @Nullable 35 | public static java.time.Duration protoToDuration(@Nullable Duration duration) { 36 | return duration == null 37 | ? null 38 | : java.time.Duration.ofSeconds(duration.getSeconds(), duration.getNanos()); 39 | } 40 | 41 | public static java.time.Instant protoToInstant(Timestamp timestamp) { 42 | return Instant.ofEpochSecond(timestamp.getSeconds(), timestamp.getNanos()); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /core/src/main/java/tech/ydb/core/utils/Version.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.core.utils; 2 | 3 | import java.io.InputStream; 4 | import java.util.Optional; 5 | import java.util.Properties; 6 | 7 | public class Version { 8 | 9 | public static final String UNKNOWN_VERSION = "unknown-version"; 10 | 11 | private Version() { 12 | // 13 | } 14 | 15 | public static Optional getVersion() { 16 | try (InputStream in = Version.class.getResourceAsStream("/ydb_sdk_version.properties")) { 17 | Properties prop = new Properties(); 18 | prop.load(in); 19 | return Optional.ofNullable(prop.getProperty("version")); 20 | } catch (Exception ex) { 21 | return Optional.empty(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /core/src/main/resources/certificates/YandexAllCAs.pkcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ydb-platform/ydb-java-sdk/5b4eb6217040af3a0d6e6374f0ebbe2109acc258/core/src/main/resources/certificates/YandexAllCAs.pkcs -------------------------------------------------------------------------------- /core/src/main/resources/ydb_sdk_version.properties: -------------------------------------------------------------------------------- 1 | version=${project.version} 2 | -------------------------------------------------------------------------------- /core/src/test/java/tech/ydb/core/IssueTest.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.core; 2 | 3 | import tech.ydb.core.Issue.Position; 4 | import org.junit.Assert; 5 | import org.junit.Test; 6 | 7 | 8 | /** 9 | * @author Sergey Polovko 10 | */ 11 | public class IssueTest { 12 | 13 | @Test 14 | public void testToString() { 15 | Issue i1 = Issue.of("message", Issue.Severity.ERROR); 16 | Assert.assertEquals("message (S_ERROR)", i1.toString()); 17 | 18 | Issue i2 = Issue.of("message", Issue.Severity.FATAL); 19 | Assert.assertEquals("message (S_FATAL)", i2.toString()); 20 | 21 | Issue i3 = Issue.of(3, "message", Issue.Severity.WARNING); 22 | Assert.assertEquals("#3 message (S_WARNING)", i3.toString()); 23 | 24 | Issue i4 = Issue.of(Position.of(11, 22), 4, "message", Issue.Severity.WARNING); 25 | Assert.assertEquals("11:22: #4 message (S_WARNING)", i4.toString()); 26 | 27 | Issue i5 = Issue.of(Position.of(11, 22, "file.cpp"), 5, "message", Issue.Severity.WARNING); 28 | Assert.assertEquals("11:22 at file.cpp: #5 message (S_WARNING)", i5.toString()); 29 | 30 | Issue i6 = Issue.of(Position.of(10, 20), Position.of(15, 30), 6, "message", Issue.Severity.INFO); 31 | Assert.assertEquals("10:20 - 15:30: #6 message (S_INFO)", i6.toString()); 32 | 33 | Issue x = Issue.of(Position.EMPTY, Position.EMPTY, 7, "root cause", Issue.Severity.FATAL, i3, i4, i5); 34 | Assert.assertEquals( 35 | "#7 root cause (S_FATAL)\n" + 36 | " #3 message (S_WARNING)\n" + 37 | " 11:22: #4 message (S_WARNING)\n" + 38 | " 11:22 at file.cpp: #5 message (S_WARNING)", x.toString()); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /core/src/test/java/tech/ydb/core/StatusCodeTest.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.core; 2 | 3 | import java.util.HashSet; 4 | import java.util.Set; 5 | 6 | import org.junit.Assert; 7 | import org.junit.Test; 8 | 9 | import tech.ydb.proto.StatusCodesProtos.StatusIds; 10 | 11 | 12 | /** 13 | * @author Sergey Polovko 14 | */ 15 | public class StatusCodeTest { 16 | 17 | @Test 18 | public void statusCodesAreUnique() { 19 | Set codes = new HashSet<>(); 20 | for (StatusCode code : StatusCode.values()) { 21 | Assert.assertTrue(codes.add(code.getCode())); 22 | } 23 | } 24 | 25 | @Test 26 | public void statusCodesMatchProtobufCodes() { 27 | for (StatusIds.StatusCode codePb : StatusIds.StatusCode.values()) { 28 | if (codePb == StatusIds.StatusCode.UNRECOGNIZED) { 29 | continue; 30 | } 31 | 32 | StatusCode code = StatusCode.fromProto(codePb); 33 | Assert.assertEquals( 34 | String.format("enums %s and %s has different codes", code, codePb), 35 | code.getCode(), codePb.getNumber()); 36 | 37 | if (codePb == StatusIds.StatusCode.STATUS_CODE_UNSPECIFIED) { 38 | Assert.assertEquals(StatusCode.UNUSED_STATUS, code); 39 | } else { 40 | Assert.assertEquals(code.name(), codePb.name()); 41 | Assert.assertFalse(code.isTransportError()); 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /core/src/test/java/tech/ydb/core/UnexpectedResultExceptionTest.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.core; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | 7 | /** 8 | * @author Sergey Polovko 9 | */ 10 | public class UnexpectedResultExceptionTest { 11 | 12 | @Test 13 | public void testToString() { 14 | UnexpectedResultException e1 = new UnexpectedResultException("", 15 | Status.of(StatusCode.OVERLOADED)); 16 | Assert.assertEquals("code: OVERLOADED", e1.getMessage()); 17 | 18 | UnexpectedResultException e2 = new UnexpectedResultException("some message", 19 | Status.of(StatusCode.OVERLOADED)); 20 | Assert.assertEquals("some message, code: OVERLOADED", e2.getMessage()); 21 | 22 | UnexpectedResultException e3 = new UnexpectedResultException( 23 | "some message", 24 | Status.of(StatusCode.OVERLOADED).withIssues(Issue.of("issue message", Issue.Severity.ERROR)) 25 | ); 26 | Assert.assertEquals("some message, code: OVERLOADED, issues: [issue message (S_ERROR)]", e3.getMessage()); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /core/src/test/java/tech/ydb/core/auth/JwtBuilder.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.core.auth; 2 | 3 | import java.nio.charset.StandardCharsets; 4 | import java.time.Instant; 5 | import java.util.Base64; 6 | 7 | /** 8 | * 9 | * @author Aleksandr Gorshenin 10 | */ 11 | public class JwtBuilder { 12 | // {"typ":"JWT","alg":"none"} 13 | private final static String PREFIX = "eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0."; 14 | 15 | public static String create(Instant expiredAt, Instant issuedAt) { 16 | StringBuilder sb = new StringBuilder(); 17 | sb.append("{"); 18 | sb.append("\"exp\":").append(expiredAt.getEpochSecond()).append(","); 19 | sb.append("\"iat\":").append(issuedAt.getEpochSecond()).append(","); 20 | sb.append("\"iss\":\"").append("MOCK").append("\""); 21 | sb.append("}"); 22 | 23 | String base64 = Base64.getEncoder().encodeToString(sb.toString().getBytes(StandardCharsets.UTF_8)); 24 | 25 | return PREFIX + base64; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /core/src/test/java/tech/ydb/core/auth/JwtUtilsTest.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.core.auth; 2 | 3 | import java.time.Instant; 4 | 5 | import org.junit.Assert; 6 | import org.junit.Test; 7 | 8 | /** 9 | * 10 | * @author Aleksandr Gorshenin 11 | */ 12 | public class JwtUtilsTest { 13 | 14 | @Test 15 | public void parseTest() { 16 | // { "alg": "HS256", "typ": "JWT" }.{ "sub": "1234567890", "iat": 1516239022, "exp": 1726544488 } 17 | String jwt1 = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE3MjY1NDQ0ODh9"; 18 | // { "alg": "HS256", "typ": "JWT" }.{ "aud": "Base", "sub": "1234567890", "iat": 1516239022, "exp": 1726544488 } 19 | String jwt2 = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJCYXNlIiwic3ViIjoiMTIzNDU2Nzg5MCIsImlhdCI6MTUxNjIzOTAyMiwiZXhwIjoxNzI2NTQ0NDg4fQ"; 20 | // { "alg": "HS256", "typ": "JWT" }.{ "aud": [ "Base" ], "sub": "1234567890", "iat": 1516239022, "exp": 1726544488 } 21 | String jwt3 = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiQmFzZSJdLCJzdWIiOiIxMjM0NTY3ODkwIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE3MjY1NDQ0ODh9"; 22 | 23 | Assert.assertEquals(Instant.ofEpochSecond(1726544488), JwtUtils.extractExpireAt(jwt1, Instant.EPOCH)); 24 | Assert.assertEquals(Instant.ofEpochSecond(1726544488), JwtUtils.extractExpireAt(jwt2, Instant.EPOCH)); 25 | Assert.assertEquals(Instant.ofEpochSecond(1726544488), JwtUtils.extractExpireAt(jwt3, Instant.EPOCH)); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /core/src/test/java/tech/ydb/core/impl/MockedClock.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.core.impl; 2 | 3 | import java.time.Clock; 4 | import java.time.Instant; 5 | import java.time.ZoneId; 6 | 7 | /** 8 | * 9 | * @author Aleksandr Gorshenin 10 | */ 11 | public class MockedClock extends Clock { 12 | private final ZoneId zoneID; 13 | private final MockedInstant mock; 14 | 15 | private MockedClock(ZoneId zoneId, MockedInstant instant) { 16 | this.zoneID = zoneId; 17 | this.mock = instant; 18 | } 19 | 20 | @Override 21 | public ZoneId getZone() { 22 | return zoneID; 23 | } 24 | 25 | @Override 26 | public Clock withZone(ZoneId zone) { 27 | return new MockedClock(zone, mock); 28 | } 29 | 30 | @Override 31 | public Instant instant() { 32 | return mock.instant(); 33 | } 34 | 35 | public void goToFuture(Instant future) { 36 | mock.goToFuture(future); 37 | } 38 | 39 | public void reset(Instant now) { 40 | mock.reset(now); 41 | } 42 | 43 | public static MockedClock create(ZoneId zoneId) { 44 | return new MockedClock(zoneId, new MockedInstant(Instant.now())); 45 | } 46 | 47 | private static class MockedInstant { 48 | private volatile Instant now; 49 | 50 | public MockedInstant(Instant now) { 51 | reset(now); 52 | } 53 | 54 | private void reset(Instant now) { 55 | this.now = now; 56 | } 57 | 58 | private Instant instant() { 59 | return now; 60 | } 61 | 62 | private void goToFuture(Instant future) { 63 | if (future.isAfter(now)) { 64 | this.now = future; 65 | } 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /core/src/test/java/tech/ydb/core/timer/TestTicker.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.core.timer; 2 | 3 | import java.util.Arrays; 4 | import java.util.Iterator; 5 | 6 | import com.google.common.base.Ticker; 7 | 8 | /** 9 | * @author Kirill Kurdyukov 10 | */ 11 | public class TestTicker extends Ticker { 12 | private final Iterator iterator; 13 | 14 | public TestTicker(Integer... pings) { 15 | this.iterator = Arrays.stream(pings).iterator(); 16 | } 17 | 18 | @Override 19 | public long read() { 20 | return iterator.next(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /core/src/test/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /export/pom.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 4.0.0 7 | 8 | 9 | tech.ydb 10 | ydb-sdk-parent 11 | 2.3.16-SNAPSHOT 12 | 13 | 14 | ydb-sdk-export 15 | Export client implementation 16 | Export client implementation 17 | 18 | 19 | UTF-8 20 | 21 | 22 | 23 | 24 | tech.ydb 25 | ydb-sdk-core 26 | 27 | 28 | org.apache.logging.log4j 29 | log4j-slf4j-impl 30 | test 31 | 32 | 33 | 34 | 35 | 36 | 37 | org.apache.maven.plugins 38 | maven-surefire-plugin 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /export/src/main/java/tech/ydb/export/ExportRpc.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.export; 2 | 3 | import java.util.concurrent.CompletableFuture; 4 | 5 | import tech.ydb.core.Result; 6 | import tech.ydb.core.grpc.GrpcRequestSettings; 7 | import tech.ydb.core.operation.Operation; 8 | import tech.ydb.proto.export.YdbExport; 9 | 10 | /** 11 | * @author Kirill Kurdyukov 12 | */ 13 | public interface ExportRpc { 14 | 15 | CompletableFuture>> findExportToS3( 16 | String operationId, GrpcRequestSettings settings 17 | ); 18 | 19 | CompletableFuture>> findExportToYT( 20 | String operationId, GrpcRequestSettings settings 21 | ); 22 | 23 | CompletableFuture>> exportS3( 24 | YdbExport.ExportToS3Request request, GrpcRequestSettings settings 25 | ); 26 | 27 | CompletableFuture>> exportYt( 28 | YdbExport.ExportToYtRequest request, GrpcRequestSettings settings 29 | ); 30 | } 31 | -------------------------------------------------------------------------------- /export/src/main/java/tech/ydb/export/result/ExportToS3Result.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.export.result; 2 | 3 | import tech.ydb.proto.export.YdbExport; 4 | 5 | public class ExportToS3Result { 6 | 7 | public ExportToS3Result(YdbExport.ExportToS3Result exportToS3Result) { 8 | // do nothing 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /export/src/main/java/tech/ydb/export/result/ExportToYtResult.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.export.result; 2 | 3 | import tech.ydb.proto.export.YdbExport; 4 | 5 | public class ExportToYtResult { 6 | 7 | public ExportToYtResult(YdbExport.ExportToYtResult exportToYtResult) { 8 | // do nothing 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /export/src/main/java/tech/ydb/export/settings/FindExportSettings.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.export.settings; 2 | 3 | import tech.ydb.core.settings.OperationSettings; 4 | 5 | /** 6 | * 7 | * @author Aleksandr Gorshenin 8 | */ 9 | public class FindExportSettings extends OperationSettings { 10 | private FindExportSettings(Builder builder) { 11 | super(builder); 12 | } 13 | 14 | public static Builder newBuilder() { 15 | return new Builder().withAsyncMode(true); 16 | } 17 | 18 | public static class Builder extends OperationSettings.OperationBuilder { 19 | @Override 20 | public FindExportSettings build() { 21 | return new FindExportSettings(this); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /query/src/main/java/tech/ydb/query/QueryStream.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.query; 2 | 3 | import java.util.concurrent.CompletableFuture; 4 | 5 | import io.grpc.ExperimentalApi; 6 | 7 | import tech.ydb.core.Issue; 8 | import tech.ydb.core.Result; 9 | import tech.ydb.query.result.QueryInfo; 10 | import tech.ydb.query.result.QueryResultPart; 11 | 12 | /** 13 | * 14 | * @author Aleksandr Gorshenin 15 | */ 16 | @ExperimentalApi("QueryService is experimental and API may change without notice") 17 | public interface QueryStream { 18 | interface PartsHandler { 19 | default void onIssues(Issue[] issues) { } 20 | void onNextPart(QueryResultPart part); 21 | } 22 | 23 | CompletableFuture> execute(PartsHandler handler); 24 | 25 | void cancel(); 26 | 27 | default CompletableFuture> execute() { 28 | return execute(null); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /query/src/main/java/tech/ydb/query/result/QueryInfo.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.query.result; 2 | 3 | 4 | /** 5 | * 6 | * @author Aleksandr Gorshenin 7 | */ 8 | public class QueryInfo { 9 | private final QueryStats stats; 10 | 11 | public QueryInfo(QueryStats stats) { 12 | this.stats = stats; 13 | } 14 | 15 | public boolean hasStats() { 16 | return stats != null; 17 | } 18 | 19 | public QueryStats getStats() { 20 | return stats; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /query/src/main/java/tech/ydb/query/result/QueryResultPart.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.query.result; 2 | 3 | import tech.ydb.proto.ValueProtos; 4 | import tech.ydb.table.result.ResultSetReader; 5 | import tech.ydb.table.result.impl.ProtoValueReaders; 6 | 7 | /** 8 | * 9 | * @author Aleksandr Gorshenin 10 | */ 11 | public class QueryResultPart { 12 | private final long index; 13 | private final ValueProtos.ResultSet resultSet; 14 | 15 | public QueryResultPart(long index, ValueProtos.ResultSet resultSet) { 16 | this.index = index; 17 | this.resultSet = resultSet; 18 | } 19 | 20 | public long getResultSetIndex() { 21 | return this.index; 22 | } 23 | 24 | public int getResultSetRowsCount() { 25 | return this.resultSet.getRowsCount(); 26 | } 27 | 28 | public ResultSetReader getResultSetReader() { 29 | return ProtoValueReaders.forResultSet(resultSet); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /query/src/main/java/tech/ydb/query/settings/AttachSessionSettings.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.query.settings; 2 | 3 | import tech.ydb.core.settings.BaseRequestSettings; 4 | 5 | /** 6 | * 7 | * @author Aleksandr Gorshenin 8 | */ 9 | public class AttachSessionSettings extends BaseRequestSettings { 10 | private AttachSessionSettings(Builder builder) { 11 | super(builder); 12 | } 13 | 14 | public static Builder newBuilder() { 15 | return new Builder(); 16 | } 17 | 18 | public static class Builder extends BaseBuilder { 19 | @Override 20 | public AttachSessionSettings build() { 21 | return new AttachSessionSettings(this); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /query/src/main/java/tech/ydb/query/settings/BeginTransactionSettings.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.query.settings; 2 | 3 | import tech.ydb.core.settings.OperationSettings; 4 | 5 | /** 6 | * 7 | * @author Aleksandr Gorshenin 8 | */ 9 | public class BeginTransactionSettings extends OperationSettings { 10 | private BeginTransactionSettings(Builder builder) { 11 | super(builder); 12 | } 13 | 14 | public static Builder newBuilder() { 15 | return new Builder(); 16 | } 17 | 18 | public static class Builder extends OperationBuilder { 19 | @Override 20 | public BeginTransactionSettings build() { 21 | return new BeginTransactionSettings(this); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /query/src/main/java/tech/ydb/query/settings/CommitTransactionSettings.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.query.settings; 2 | 3 | import tech.ydb.core.settings.OperationSettings; 4 | 5 | /** 6 | * 7 | * @author Aleksandr Gorshenin 8 | */ 9 | public class CommitTransactionSettings extends OperationSettings { 10 | private CommitTransactionSettings(Builder builder) { 11 | super(builder); 12 | } 13 | 14 | public static Builder newBuilder() { 15 | return new Builder(); 16 | } 17 | 18 | public static class Builder extends OperationBuilder { 19 | @Override 20 | public CommitTransactionSettings build() { 21 | return new CommitTransactionSettings(this); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /query/src/main/java/tech/ydb/query/settings/CreateSessionSettings.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.query.settings; 2 | 3 | import tech.ydb.core.settings.OperationSettings; 4 | 5 | /** 6 | * 7 | * @author Aleksandr Gorshenin 8 | */ 9 | public class CreateSessionSettings extends OperationSettings { 10 | private CreateSessionSettings(Builder builder) { 11 | super(builder); 12 | } 13 | 14 | public static Builder newBuilder() { 15 | return new Builder(); 16 | } 17 | 18 | public static class Builder extends OperationBuilder { 19 | @Override 20 | public CreateSessionSettings build() { 21 | return new CreateSessionSettings(this); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /query/src/main/java/tech/ydb/query/settings/DeleteSessionSettings.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.query.settings; 2 | 3 | import tech.ydb.core.settings.OperationSettings; 4 | 5 | /** 6 | * 7 | * @author Aleksandr Gorshenin 8 | */ 9 | public class DeleteSessionSettings extends OperationSettings { 10 | private DeleteSessionSettings(Builder builder) { 11 | super(builder); 12 | } 13 | 14 | public static Builder newBuilder() { 15 | return new Builder(); 16 | } 17 | 18 | public static class Builder extends OperationBuilder { 19 | @Override 20 | public DeleteSessionSettings build() { 21 | return new DeleteSessionSettings(this); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /query/src/main/java/tech/ydb/query/settings/QueryExecMode.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.query.settings; 2 | 3 | /** 4 | * 5 | * @author Aleksandr Gorshenin 6 | */ 7 | public enum QueryExecMode { 8 | EXECUTE, 9 | EXPLAIN, 10 | PARSE, 11 | VALIDATE, 12 | UNSPECIFIED 13 | } 14 | -------------------------------------------------------------------------------- /query/src/main/java/tech/ydb/query/settings/QueryStatsMode.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.query.settings; 2 | 3 | /** 4 | * 5 | * @author Aleksandr Gorshenin 6 | */ 7 | public enum QueryStatsMode { 8 | NONE, 9 | BASIC, 10 | FULL, 11 | PROFILE, 12 | UNSPECIFIED 13 | } 14 | -------------------------------------------------------------------------------- /query/src/main/java/tech/ydb/query/settings/RollbackTransactionSettings.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.query.settings; 2 | 3 | import tech.ydb.core.settings.OperationSettings; 4 | 5 | /** 6 | * 7 | * @author Aleksandr Gorshenin 8 | */ 9 | public class RollbackTransactionSettings extends OperationSettings { 10 | private RollbackTransactionSettings(Builder builder) { 11 | super(builder); 12 | } 13 | 14 | public static Builder newBuilder() { 15 | return new Builder(); 16 | } 17 | 18 | public static class Builder extends OperationBuilder { 19 | @Override 20 | public RollbackTransactionSettings build() { 21 | return new RollbackTransactionSettings(this); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /query/src/test/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /scheme/pom.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 4.0.0 7 | 8 | 9 | tech.ydb 10 | ydb-sdk-parent 11 | 2.3.16-SNAPSHOT 12 | 13 | 14 | ydb-sdk-scheme 15 | Scheme client implementation 16 | Scheme client implementation 17 | 18 | 19 | UTF-8 20 | 21 | 22 | 23 | 24 | tech.ydb 25 | ydb-sdk-core 26 | 27 | 28 | 29 | junit 30 | junit 31 | test 32 | 33 | 34 | org.apache.logging.log4j 35 | log4j-slf4j-impl 36 | test 37 | 38 | 39 | tech.ydb.test 40 | ydb-junit4-support 41 | test 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /scheme/src/main/java/tech/ydb/scheme/SchemeClient.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.scheme; 2 | 3 | import java.util.concurrent.CompletableFuture; 4 | 5 | import javax.annotation.WillNotClose; 6 | 7 | import tech.ydb.core.Result; 8 | import tech.ydb.core.Status; 9 | import tech.ydb.core.grpc.GrpcTransport; 10 | import tech.ydb.scheme.description.DescribePathResult; 11 | import tech.ydb.scheme.description.ListDirectoryResult; 12 | import tech.ydb.scheme.impl.GrpcSchemeRpc; 13 | import tech.ydb.scheme.impl.SchemeClientImpl; 14 | 15 | 16 | /** 17 | * @author Sergey Polovko 18 | */ 19 | public interface SchemeClient extends AutoCloseable { 20 | 21 | static Builder newClient(@WillNotClose GrpcTransport transport) { 22 | return SchemeClientImpl.newClient(GrpcSchemeRpc.useTransport(transport)); 23 | } 24 | 25 | /** 26 | * Create single directory. 27 | * 28 | * Parent directories must be already present. 29 | * @param path path to directory 30 | * @return operation status 31 | */ 32 | CompletableFuture makeDirectory(String path); 33 | 34 | /** 35 | * Create directory and all its parent directories if they are not present. 36 | * 37 | * @param path path to directory 38 | * @return operation status 39 | */ 40 | CompletableFuture makeDirectories(String path); 41 | 42 | CompletableFuture removeDirectory(String path); 43 | 44 | CompletableFuture> describePath(String path); 45 | 46 | CompletableFuture> listDirectory(String path); 47 | 48 | @Override 49 | void close(); 50 | 51 | /** 52 | * BUILDER 53 | */ 54 | interface Builder { 55 | 56 | SchemeClient build(); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /scheme/src/main/java/tech/ydb/scheme/description/DescribePathResult.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.scheme.description; 2 | 3 | import tech.ydb.proto.scheme.SchemeOperationProtos; 4 | 5 | 6 | /** 7 | * @author Sergey Polovko 8 | */ 9 | public class DescribePathResult { 10 | private final SchemeOperationProtos.Entry self; 11 | private final Entry entry; 12 | 13 | protected DescribePathResult(SchemeOperationProtos.Entry self) { 14 | this.self = self; 15 | this.entry = new Entry(self); 16 | } 17 | 18 | public DescribePathResult(SchemeOperationProtos.DescribePathResult result) { 19 | this(result.getSelf()); 20 | } 21 | 22 | @Deprecated 23 | public SchemeOperationProtos.Entry getSelf() { 24 | return self; 25 | } 26 | 27 | public Entry getEntry() { 28 | return entry; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /scheme/src/main/java/tech/ydb/scheme/description/EntryType.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.scheme.description; 2 | 3 | /** 4 | * 5 | * @author Aleksandr Gorshenin 6 | */ 7 | public enum EntryType { 8 | UNSPECIFIED(0), 9 | 10 | DIRECTORY(1), 11 | TABLE(2), 12 | PERS_QUEUE_GROUP(3), 13 | DATABASE(4), 14 | RTMR_VOLUME(5), 15 | BLOCK_STORE_VOLUME(6), 16 | COORDINATION_NODE(7), 17 | COLUMN_STORE(12), 18 | COLUMN_TABLE(13), 19 | SEQUENCE(15), 20 | REPLICATION(16), 21 | TOPIC(17), 22 | EXTERNAL_TABLE(18), 23 | EXTERNAL_DATA_SOURCE(19), 24 | VIEW(20); 25 | 26 | private final int code; 27 | 28 | EntryType(int code) { 29 | this.code = code; 30 | } 31 | 32 | public int getCode() { 33 | return code; 34 | } 35 | 36 | public static EntryType fromCode(int code) { 37 | for (EntryType type: EntryType.values()) { 38 | if (code == type.code) { 39 | return type; 40 | } 41 | } 42 | return UNSPECIFIED; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /scheme/src/main/java/tech/ydb/scheme/description/ListDirectoryResult.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.scheme.description; 2 | 3 | import java.util.List; 4 | import java.util.stream.Collectors; 5 | 6 | import tech.ydb.proto.scheme.SchemeOperationProtos; 7 | 8 | /** 9 | * @author Sergey Polovko 10 | */ 11 | public class ListDirectoryResult extends DescribePathResult { 12 | 13 | private final List children; 14 | private final List entryChildren; 15 | 16 | public ListDirectoryResult(SchemeOperationProtos.ListDirectoryResult result) { 17 | super(result.getSelf()); 18 | this.children = result.getChildrenList(); 19 | this.entryChildren = result.getChildrenList().stream().map(Entry::new).collect(Collectors.toList()); 20 | } 21 | 22 | @Deprecated 23 | public List getChildren() { 24 | return children; 25 | } 26 | 27 | public List getEntryChildren() { 28 | return entryChildren; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /scheme/src/main/java/tech/ydb/scheme/impl/SchemeClientBuilderImpl.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.scheme.impl; 2 | 3 | import tech.ydb.scheme.SchemeClient; 4 | 5 | 6 | 7 | /** 8 | * @author Sergey Polovko 9 | */ 10 | public class SchemeClientBuilderImpl implements SchemeClient.Builder { 11 | 12 | protected final SchemeRpc schemeRpc; 13 | 14 | public SchemeClientBuilderImpl(SchemeRpc schemeRpc) { 15 | this.schemeRpc = schemeRpc; 16 | } 17 | 18 | @Override 19 | public SchemeClient build() { 20 | return new SchemeClientImpl(this); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /scheme/src/test/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/SessionSupplier.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table; 2 | 3 | import java.time.Duration; 4 | import java.util.concurrent.CompletableFuture; 5 | import java.util.concurrent.ScheduledExecutorService; 6 | 7 | import tech.ydb.core.Result; 8 | 9 | 10 | /** 11 | * @author Aleksandr Gorshenin 12 | */ 13 | public interface SessionSupplier { 14 | /** 15 | * Create new session asynchronous 16 | * 17 | * @param duration - timeout of operation completion waiting 18 | * @return Return a new CompletableFuture that is completed with successful 19 | * Result when session created, and fail Result otherwise 20 | */ 21 | CompletableFuture> createSession(Duration duration); 22 | 23 | /** 24 | * Default scheduler for asynchronous tasks execution 25 | * @return Default tasks scheduler 26 | */ 27 | ScheduledExecutorService getScheduler(); 28 | 29 | } 30 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/TableClient.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table; 2 | 3 | import java.time.Duration; 4 | 5 | import javax.annotation.WillNotClose; 6 | 7 | import tech.ydb.core.grpc.GrpcTransport; 8 | import tech.ydb.table.impl.PooledTableClient; 9 | import tech.ydb.table.rpc.grpc.GrpcTableRpc; 10 | 11 | 12 | /** 13 | * @author Sergey Polovko 14 | * @author Aleksandr Gorshenin 15 | * 16 | * TableClient is a main point for accepting and releasing sessions 17 | * It has factory method {@link #newClient(GrpcTransport)} which 18 | * return instance of default implementation {@link PooledTableClient}. This 19 | * implementation contains session pool with fixed sizes. This is recommended way 20 | * to create implementation of SessionSupplier. 21 | * If you want to use implementation without session pool, you may use 22 | * {@link tech.ydb.table.impl.SimpleTableClient} 23 | */ 24 | public interface TableClient extends SessionSupplier, AutoCloseable { 25 | 26 | /** 27 | * Return TableClient builder used passed {@link GrpcTransport} 28 | * @param transport instance of grpc transport 29 | * @return {@link TableClient.Builder} for TableClient creating 30 | */ 31 | static Builder newClient(@WillNotClose GrpcTransport transport) { 32 | return PooledTableClient.newClient(GrpcTableRpc.useTransport(transport)); 33 | } 34 | 35 | SessionPoolStats sessionPoolStats(); 36 | 37 | @Override 38 | void close(); 39 | 40 | interface Builder { 41 | 42 | Builder keepQueryText(boolean keep); 43 | 44 | Builder sessionPoolSize(int minSize, int maxSize); 45 | 46 | Builder sessionKeepAliveTime(Duration duration); 47 | 48 | Builder sessionMaxIdleTime(Duration duration); 49 | 50 | TableClient build(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/description/ColumnFamily.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.description; 2 | 3 | public final class ColumnFamily { 4 | private final String name; 5 | private final StoragePool data; 6 | private final Compression compression; 7 | 8 | @Deprecated 9 | public ColumnFamily(String name, StoragePool data, Compression compression, boolean keepInMemory) { 10 | this.name = name; 11 | this.data = data; 12 | this.compression = compression; 13 | // this.keepInMemory = keepInMemory; 14 | } 15 | 16 | public ColumnFamily(String name, StoragePool data, Compression compression) { 17 | this.name = name; 18 | this.data = data; 19 | this.compression = compression; 20 | } 21 | 22 | public String getName() { 23 | return name; 24 | } 25 | 26 | public StoragePool getData() { 27 | return data; 28 | } 29 | 30 | public Compression getCompression() { 31 | return compression; 32 | } 33 | 34 | @Deprecated 35 | public boolean isKeepInMemory() { 36 | return false; 37 | } 38 | 39 | public enum Compression { 40 | COMPRESSION_NONE, 41 | COMPRESSION_LZ4 42 | } 43 | } 44 | 45 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/description/KeyBound.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.description; 2 | 3 | import tech.ydb.table.values.Value; 4 | 5 | public class KeyBound { 6 | private final Value value; 7 | private final boolean inclusive; 8 | 9 | public KeyBound( 10 | Value value, 11 | boolean inclusive 12 | ) { 13 | this.value = value; 14 | this.inclusive = inclusive; 15 | } 16 | 17 | public Value getValue() { 18 | return value; 19 | } 20 | 21 | public boolean isInclusive() { 22 | return inclusive; 23 | } 24 | 25 | public static KeyBound inclusive(Value value) { 26 | return new KeyBound(value, true); 27 | } 28 | 29 | public static KeyBound exclusive(Value value) { 30 | return new KeyBound(value, false); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/description/KeyRange.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.description; 2 | 3 | import java.util.Optional; 4 | 5 | public class KeyRange { 6 | private final Optional from; 7 | private final Optional to; 8 | 9 | public KeyRange( 10 | Optional from, 11 | Optional to 12 | ) { 13 | this.from = from; 14 | this.to = to; 15 | } 16 | 17 | public Optional getFrom() { 18 | return from; 19 | } 20 | 21 | public Optional getTo() { 22 | return to; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/description/StoragePool.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.description; 2 | 3 | public final class StoragePool { 4 | private final String media; 5 | 6 | public StoragePool(String media) { 7 | this.media = media; 8 | } 9 | 10 | public String getMedia() { 11 | return media; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/description/TableColumn.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.description; 2 | 3 | import javax.annotation.Nullable; 4 | 5 | import tech.ydb.table.values.Type; 6 | 7 | 8 | /** 9 | * @author Sergey Polovko 10 | */ 11 | public class TableColumn { 12 | 13 | private final String name; 14 | private final Type type; 15 | @Nullable 16 | private final String family; 17 | 18 | private final boolean hasDefaultValue; 19 | 20 | public TableColumn(String name, Type type, String family, boolean hasDefaultValue) { 21 | this.name = name; 22 | this.type = type; 23 | this.family = family; 24 | this.hasDefaultValue = hasDefaultValue; 25 | } 26 | 27 | public TableColumn(String name, Type type, String family) { 28 | this(name, type, family, false); 29 | } 30 | 31 | public TableColumn(String name, Type type) { 32 | this(name, type, null); 33 | } 34 | 35 | public String getName() { 36 | return name; 37 | } 38 | 39 | public Type getType() { 40 | return type; 41 | } 42 | 43 | public boolean hasDefaultValue() { 44 | return hasDefaultValue; 45 | } 46 | 47 | @Nullable 48 | public String getFamily() { 49 | return family; 50 | } 51 | 52 | @Override 53 | public String toString() { 54 | return name + ' ' + type; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/description/TableIndex.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.description; 2 | 3 | import java.util.List; 4 | 5 | import static java.util.Collections.emptyList; 6 | 7 | /** 8 | * @author Sergey Polovko 9 | * @author Kirill Kurdyukov 10 | */ 11 | public class TableIndex { 12 | 13 | public enum Type { 14 | GLOBAL, 15 | GLOBAL_ASYNC, 16 | GLOBAL_UNIQUE, 17 | } 18 | 19 | /** 20 | * Name of the index. 21 | */ 22 | private final String name; 23 | 24 | /** 25 | * List of indexed columns. 26 | */ 27 | private final List columns; 28 | 29 | /** 30 | * List of columns content to be copied in to index table. 31 | */ 32 | private final List dataColumns; 33 | 34 | /** 35 | * Index type. 36 | */ 37 | private final Type type; 38 | 39 | public TableIndex( 40 | String name, 41 | List columns, 42 | Type type 43 | ) { 44 | this(name, columns, emptyList(), type); 45 | } 46 | 47 | public TableIndex( 48 | String name, 49 | List columns, 50 | List dataColumns, 51 | Type type 52 | ) { 53 | this.name = name; 54 | this.columns = columns; 55 | this.dataColumns = dataColumns; 56 | this.type = type; 57 | } 58 | 59 | public String getName() { 60 | return name; 61 | } 62 | 63 | public List getColumns() { 64 | return columns; 65 | } 66 | 67 | public List getDataColumns() { 68 | return dataColumns; 69 | } 70 | 71 | public Type getType() { 72 | return type; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/query/DataQuery.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.query; 2 | 3 | import java.util.Map; 4 | import java.util.Optional; 5 | import java.util.concurrent.CompletableFuture; 6 | 7 | import tech.ydb.core.Result; 8 | import tech.ydb.table.settings.ExecuteDataQuerySettings; 9 | import tech.ydb.table.transaction.TxControl; 10 | import tech.ydb.table.values.Type; 11 | 12 | 13 | /** 14 | * @author Sergey Polovko 15 | */ 16 | public interface DataQuery { 17 | 18 | String getId(); 19 | 20 | Params newParams(); 21 | 22 | /** 23 | * Returns parameter types 24 | * 25 | * @return unmodifiable map of types 26 | */ 27 | Map types(); 28 | 29 | Optional getText(); 30 | 31 | CompletableFuture> execute( 32 | TxControl txControl, Params params, ExecuteDataQuerySettings settings); 33 | 34 | default CompletableFuture> execute(TxControl txControl, Params params) { 35 | return execute(txControl, params, new ExecuteDataQuerySettings()); 36 | } 37 | 38 | default CompletableFuture> execute(TxControl txControl) { 39 | return execute(txControl, Params.empty(), new ExecuteDataQuerySettings()); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/query/DataQueryResult.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.query; 2 | 3 | import java.util.List; 4 | 5 | import tech.ydb.proto.ValueProtos; 6 | import tech.ydb.proto.table.YdbTable; 7 | import tech.ydb.table.query.stats.QueryStats; 8 | import tech.ydb.table.result.ResultSetReader; 9 | import tech.ydb.table.result.impl.ProtoValueReaders; 10 | 11 | /** 12 | * @author Sergey Polovko 13 | */ 14 | public class DataQueryResult { 15 | 16 | private final String txId; 17 | private final List resultSets; 18 | private final QueryStats queryStats; 19 | 20 | public DataQueryResult(YdbTable.ExecuteQueryResult result) { 21 | this.txId = result.getTxMeta().getId(); 22 | this.resultSets = result.getResultSetsList(); 23 | queryStats = result.hasQueryStats() ? new QueryStats(result.getQueryStats()) : null; 24 | } 25 | 26 | public String getTxId() { 27 | return txId; 28 | } 29 | 30 | public int getResultSetCount() { 31 | return resultSets.size(); 32 | } 33 | 34 | public ResultSetReader getResultSet(int index) { 35 | return ProtoValueReaders.forResultSet(resultSets.get(index)); 36 | } 37 | 38 | public boolean isTruncated(int index) { 39 | return resultSets.get(index).getTruncated(); 40 | } 41 | 42 | public int getRowCount(int index) { 43 | return resultSets.get(index).getRowsCount(); 44 | } 45 | 46 | public boolean isEmpty() { 47 | return txId.isEmpty() && resultSets.isEmpty(); 48 | } 49 | 50 | public QueryStats getQueryStats() { 51 | return queryStats; 52 | } 53 | 54 | public boolean hasQueryStats() { 55 | return queryStats != null; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/query/ExplainDataQueryResult.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.query; 2 | 3 | import tech.ydb.proto.table.YdbTable; 4 | 5 | /** 6 | * @author Sergey Polovko 7 | */ 8 | public class ExplainDataQueryResult { 9 | 10 | private final String queryAst; 11 | private final String queryPlan; 12 | 13 | public ExplainDataQueryResult(YdbTable.ExplainQueryResult query) { 14 | this.queryAst = query.getQueryAst(); 15 | this.queryPlan = query.getQueryPlan(); 16 | } 17 | 18 | public String getQueryAst() { 19 | return queryAst; 20 | } 21 | 22 | public String getQueryPlan() { 23 | return queryPlan; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/query/ReadRowsResult.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.query; 2 | 3 | import tech.ydb.proto.table.YdbTable.ReadRowsResponse; 4 | import tech.ydb.table.result.ResultSetReader; 5 | import tech.ydb.table.result.impl.ProtoValueReaders; 6 | 7 | public class ReadRowsResult { 8 | private final ResultSetReader resultSetReader; 9 | 10 | public ReadRowsResult(ReadRowsResponse readRowsResponse) { 11 | this.resultSetReader = ProtoValueReaders.forResultSet(readRowsResponse.getResultSet()); 12 | } 13 | 14 | public ResultSetReader getResultSetReader() { 15 | return resultSetReader; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/query/ReadTablePart.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.query; 2 | 3 | import tech.ydb.proto.common.CommonProtos; 4 | import tech.ydb.proto.table.YdbTable; 5 | import tech.ydb.table.result.ResultSetReader; 6 | import tech.ydb.table.result.impl.ProtoValueReaders; 7 | 8 | /** 9 | * @author Ilya Udalov 10 | */ 11 | public class ReadTablePart { 12 | public static final class VirtualTimestamp { 13 | private final long planStep; 14 | private final long txId; 15 | 16 | public VirtualTimestamp(long planStep, long txId) { 17 | this.planStep = planStep; 18 | this.txId = txId; 19 | } 20 | 21 | public long getPlanStep() { 22 | return planStep; 23 | } 24 | 25 | public long getTxId() { 26 | return txId; 27 | } 28 | } 29 | 30 | private final ResultSetReader resultSetReader; 31 | private final VirtualTimestamp timestamp; 32 | 33 | public ReadTablePart(YdbTable.ReadTableResult result, CommonProtos.VirtualTimestamp snapshot) { 34 | this.resultSetReader = ProtoValueReaders.forResultSet(result.getResultSet()); 35 | this.timestamp = new VirtualTimestamp(snapshot.getPlanStep(), snapshot.getTxId()); 36 | } 37 | 38 | public ResultSetReader getResultSetReader() { 39 | return resultSetReader; 40 | } 41 | 42 | public VirtualTimestamp getVirtualTimestamp() { 43 | return timestamp; 44 | } 45 | } 46 | 47 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/query/stats/CompilationStats.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.query.stats; 2 | 3 | import java.util.Objects; 4 | 5 | public final class CompilationStats { 6 | private final boolean fromCache; 7 | private final long durationUs; 8 | private final long cpuTimeUs; 9 | 10 | public CompilationStats(tech.ydb.proto.YdbQueryStats.CompilationStats protoAutoGenCompilationStats) { 11 | this.fromCache = protoAutoGenCompilationStats.getFromCache(); 12 | this.durationUs = protoAutoGenCompilationStats.getDurationUs(); 13 | this.cpuTimeUs = protoAutoGenCompilationStats.getCpuTimeUs(); 14 | } 15 | 16 | public boolean getFromCache() { 17 | return this.fromCache; 18 | } 19 | 20 | public long getDurationUs() { 21 | return this.durationUs; 22 | } 23 | 24 | public long getCpuTimeUs() { 25 | return this.cpuTimeUs; 26 | } 27 | 28 | @Override 29 | public boolean equals(Object obj) { 30 | if (obj == this) { 31 | return true; 32 | } else if (!(obj instanceof CompilationStats)) { 33 | return super.equals(obj); 34 | } else { 35 | CompilationStats other = (CompilationStats) obj; 36 | return Objects.equals(getDurationUs(), other.getDurationUs()) && 37 | Objects.equals(getFromCache(), other.getFromCache()) && 38 | Objects.equals(getCpuTimeUs(), other.getCpuTimeUs()); 39 | } 40 | } 41 | 42 | @Override 43 | public int hashCode() { 44 | return Objects.hash(fromCache, durationUs, cpuTimeUs); 45 | } 46 | 47 | @Override 48 | public String toString() { 49 | return "CompilationStats{" + "fromCache=" + fromCache + ", durationUs=" + durationUs + ", cpuTimeUs=" + 50 | cpuTimeUs + '}'; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/query/stats/OperationStats.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.query.stats; 2 | 3 | import java.util.Objects; 4 | 5 | public final class OperationStats { 6 | private final long rows; 7 | private final long bytes; 8 | 9 | public OperationStats(tech.ydb.proto.YdbQueryStats.OperationStats protoAutoGenOperationStats) { 10 | this.rows = protoAutoGenOperationStats.getRows(); 11 | this.bytes = protoAutoGenOperationStats.getBytes(); 12 | } 13 | 14 | public long getRows() { 15 | return this.rows; 16 | } 17 | 18 | public long getBytes() { 19 | return this.bytes; 20 | } 21 | 22 | @Override 23 | public boolean equals(Object obj) { 24 | if (obj == this) { 25 | return true; 26 | } else if (!(obj instanceof OperationStats)) { 27 | return super.equals(obj); 28 | } else { 29 | OperationStats other = (OperationStats) obj; 30 | return Objects.equals(getRows(), other.getRows()) && Objects.equals(getBytes(), other.getBytes()); 31 | } 32 | } 33 | 34 | @Override 35 | public int hashCode() { 36 | return Objects.hash(getRows(), getBytes()); 37 | } 38 | 39 | @Override 40 | public String toString() { 41 | return "OperationStats{" + "rows=" + rows + ", bytes=" + bytes + '}'; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/query/stats/QueryStatsCollectionMode.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.query.stats; 2 | 3 | import tech.ydb.proto.table.YdbTable.QueryStatsCollection.Mode; 4 | 5 | 6 | public enum QueryStatsCollectionMode { 7 | UNSPECIFIED, 8 | NONE, 9 | BASIC, 10 | FULL, 11 | PROFILE; 12 | 13 | public Mode toPb() { 14 | switch (this) { 15 | case UNSPECIFIED: 16 | return Mode.STATS_COLLECTION_UNSPECIFIED; 17 | case NONE: 18 | return Mode.STATS_COLLECTION_NONE; 19 | case BASIC: 20 | return Mode.STATS_COLLECTION_BASIC; 21 | case FULL: 22 | return Mode.STATS_COLLECTION_FULL; 23 | case PROFILE: 24 | return Mode.STATS_COLLECTION_PROFILE; 25 | default: 26 | throw new IllegalStateException("Unsupported query statistic collection mode."); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/result/DictReader.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.result; 2 | 3 | /** 4 | * @author Sergey Polovko 5 | */ 6 | public interface DictReader { 7 | 8 | int getDictItemsCount(); 9 | 10 | ValueReader getDictKey(int index); 11 | 12 | ValueReader getDictValue(int index); 13 | } 14 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/result/ListReader.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.result; 2 | 3 | /** 4 | * @author Sergey Polovko 5 | */ 6 | public interface ListReader { 7 | 8 | int getListItemsCount(); 9 | 10 | ValueReader getListItem(int index); 11 | } 12 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/result/OptionalReader.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.result; 2 | 3 | /** 4 | * @author Sergey Polovko 5 | */ 6 | public interface OptionalReader { 7 | 8 | boolean isOptionalItemPresent(); 9 | 10 | ValueReader getOptionalItem(); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/result/PrimitiveReader.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.result; 2 | 3 | import java.nio.charset.Charset; 4 | import java.time.Duration; 5 | import java.time.Instant; 6 | import java.time.LocalDate; 7 | import java.time.LocalDateTime; 8 | import java.time.ZonedDateTime; 9 | import java.util.UUID; 10 | 11 | import tech.ydb.table.values.DecimalValue; 12 | 13 | 14 | /** 15 | * @author Sergey Polovko 16 | */ 17 | public interface PrimitiveReader { 18 | 19 | boolean getBool(); 20 | 21 | byte getInt8(); 22 | 23 | int getUint8(); 24 | 25 | short getInt16(); 26 | 27 | int getUint16(); 28 | 29 | int getInt32(); 30 | 31 | long getUint32(); 32 | 33 | long getInt64(); 34 | 35 | long getUint64(); 36 | 37 | float getFloat(); 38 | 39 | double getDouble(); 40 | 41 | LocalDate getDate(); 42 | 43 | LocalDateTime getDatetime(); 44 | 45 | Instant getTimestamp(); 46 | 47 | Duration getInterval(); 48 | 49 | LocalDate getDate32(); 50 | 51 | LocalDateTime getDatetime64(); 52 | 53 | Instant getTimestamp64(); 54 | 55 | Duration getInterval64(); 56 | 57 | ZonedDateTime getTzDate(); 58 | 59 | ZonedDateTime getTzDatetime(); 60 | 61 | ZonedDateTime getTzTimestamp(); 62 | 63 | byte[] getBytes(); 64 | 65 | default String getBytesAsString(Charset charset) { 66 | return new String(getBytes(), charset); 67 | } 68 | 69 | UUID getUuid(); 70 | 71 | String getText(); 72 | 73 | byte[] getYson(); 74 | 75 | String getJson(); 76 | 77 | String getJsonDocument(); 78 | 79 | DecimalValue getDecimal(); 80 | } 81 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/result/ResultSetReader.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.result; 2 | 3 | import tech.ydb.table.values.Type; 4 | 5 | /** 6 | * @author Sergey Polovko 7 | */ 8 | public interface ResultSetReader { 9 | 10 | /** 11 | * Returns {@code true} if the result was truncated, {@code false} otherwise. 12 | */ 13 | boolean isTruncated(); 14 | 15 | /** 16 | * Returns number of columns. 17 | */ 18 | int getColumnCount(); 19 | 20 | /** 21 | * Returns number of rows. 22 | */ 23 | int getRowCount(); 24 | 25 | /** 26 | * Explicitly switch to a specific row. 27 | */ 28 | void setRowIndex(int index); 29 | 30 | /** 31 | * Set iterator to the next table row. 32 | * 33 | * On success tryNextRow will reset all column parsers to the values in next row. 34 | * Column parsers are invalid before the first TryNextRow call. 35 | */ 36 | boolean next(); 37 | 38 | /** 39 | * Returns column name by index. 40 | */ 41 | String getColumnName(int index); 42 | 43 | /** 44 | * Returns column index by name or {@code -1} if column with given name is not present. 45 | */ 46 | int getColumnIndex(String name); 47 | 48 | /** 49 | * Returns value reader for column by index. 50 | */ 51 | ValueReader getColumn(int index); 52 | 53 | /** 54 | * Returns value reader for column by name. 55 | */ 56 | ValueReader getColumn(String name); 57 | 58 | /** 59 | * Returns column type by index (always create a new type instance) 60 | */ 61 | Type getColumnType(int index); 62 | } 63 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/result/StructReader.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.result; 2 | 3 | /** 4 | * @author Sergey Polovko 5 | */ 6 | public interface StructReader { 7 | 8 | int getStructMembersCount(); 9 | 10 | String getStructMemberName(int index); 11 | 12 | ValueReader getStructMember(int index); 13 | 14 | ValueReader getStructMember(String name); 15 | } 16 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/result/TupleReader.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.result; 2 | 3 | /** 4 | * @author Sergey Polovko 5 | */ 6 | public interface TupleReader { 7 | 8 | int getTupleElementsCount(); 9 | 10 | ValueReader getTupleElement(int index); 11 | } 12 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/result/ValueReader.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.result; 2 | 3 | import tech.ydb.table.values.Type; 4 | import tech.ydb.table.values.Value; 5 | 6 | /** 7 | * @author Sergey Polovko 8 | */ 9 | public interface ValueReader extends 10 | PrimitiveReader, 11 | OptionalReader, 12 | TupleReader, 13 | ListReader, 14 | DictReader, 15 | StructReader, 16 | VariantReader { 17 | 18 | /** 19 | * Writes string representation of current value into given string builder. 20 | * 21 | * @param sb string builder 22 | */ 23 | void toString(StringBuilder sb); 24 | 25 | /** 26 | * Returns value object for current cell. 27 | * Please note that this method will create value object for each method call. 28 | * 29 | * @return value 30 | */ 31 | Value getValue(); 32 | 33 | /** 34 | * Returns value type for current cell. 35 | * Please note that this method will create value type for each method call. 36 | * 37 | * @return type 38 | */ 39 | Type getType(); 40 | 41 | } 42 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/result/VariantReader.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.result; 2 | 3 | /** 4 | * @author Sergey Polovko 5 | */ 6 | public interface VariantReader { 7 | 8 | int getVariantTypeIndex(); 9 | 10 | ValueReader getVariantItem(); 11 | } 12 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/result/impl/ProtoListValueReader.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.result.impl; 2 | 3 | import tech.ydb.proto.ValueProtos; 4 | import tech.ydb.table.result.ValueReader; 5 | 6 | 7 | /** 8 | * @author Sergey Polovko 9 | */ 10 | final class ProtoListValueReader extends AbstractValueReader { 11 | 12 | private final ValueProtos.Type type; 13 | private final AbstractValueReader itemReader; 14 | private ValueProtos.Value value; 15 | 16 | ProtoListValueReader(ValueProtos.Type type, AbstractValueReader itemReader) { 17 | this.type = type; 18 | this.itemReader = itemReader; 19 | } 20 | 21 | @Override 22 | protected ValueProtos.Type getProtoType() { 23 | return type; 24 | } 25 | 26 | @Override 27 | protected ValueProtos.Value getProtoValue() { 28 | return value; 29 | } 30 | 31 | @Override 32 | protected void setProtoValue(ValueProtos.Value value) { 33 | this.value = value; 34 | } 35 | 36 | @Override 37 | public int getListItemsCount() { 38 | return value.getItemsCount(); 39 | } 40 | 41 | @Override 42 | public ValueReader getListItem(int index) { 43 | itemReader.setProtoValue(value.getItems(index)); 44 | return itemReader; 45 | } 46 | 47 | @Override 48 | public void toString(StringBuilder sb) { 49 | sb.append("List["); 50 | for (int i = 0; i < getListItemsCount(); i++) { 51 | getListItem(i).toString(sb); 52 | sb.append(", "); 53 | } 54 | if (getListItemsCount() > 0) { 55 | sb.setLength(sb.length() - 2); 56 | } 57 | sb.append(']'); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/result/impl/ProtoNullValueReader.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.result.impl; 2 | 3 | import tech.ydb.proto.ValueProtos; 4 | import tech.ydb.table.values.proto.ProtoType; 5 | import tech.ydb.table.values.proto.ProtoValue; 6 | 7 | 8 | /** 9 | * @author Aleksandr Gorshenin 10 | */ 11 | final class ProtoNullValueReader extends AbstractValueReader { 12 | static final ProtoNullValueReader INSTANCE = new ProtoNullValueReader(); 13 | 14 | private ProtoNullValueReader() { } 15 | 16 | @Override 17 | protected ValueProtos.Type getProtoType() { 18 | return ProtoType.getNull(); 19 | } 20 | 21 | @Override 22 | protected ValueProtos.Value getProtoValue() { 23 | return ProtoValue.nullValue(); 24 | } 25 | 26 | @Override 27 | protected void setProtoValue(ValueProtos.Value value) { 28 | // skip 29 | } 30 | 31 | @Override 32 | public void toString(StringBuilder sb) { 33 | sb.append("Null"); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/result/impl/ProtoTupleValueReader.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.result.impl; 2 | 3 | import tech.ydb.proto.ValueProtos; 4 | import tech.ydb.table.result.ValueReader; 5 | 6 | 7 | /** 8 | * @author Sergey Polovko 9 | */ 10 | final class ProtoTupleValueReader extends AbstractValueReader { 11 | 12 | private final ValueProtos.Type type; 13 | private final AbstractValueReader[] elementReaders; 14 | private ValueProtos.Value value; 15 | 16 | ProtoTupleValueReader(ValueProtos.Type type, AbstractValueReader[] elementReaders) { 17 | this.type = type; 18 | this.elementReaders = elementReaders; 19 | } 20 | 21 | @Override 22 | protected ValueProtos.Type getProtoType() { 23 | return type; 24 | } 25 | 26 | @Override 27 | protected ValueProtos.Value getProtoValue() { 28 | return value; 29 | } 30 | 31 | @Override 32 | protected void setProtoValue(ValueProtos.Value value) { 33 | this.value = value; 34 | } 35 | 36 | @Override 37 | public int getTupleElementsCount() { 38 | return elementReaders.length; 39 | } 40 | 41 | @Override 42 | public ValueReader getTupleElement(int index) { 43 | AbstractValueReader elementReader = elementReaders[index]; 44 | elementReader.setProtoValue(value.getItems(index)); 45 | return elementReader; 46 | } 47 | 48 | @Override 49 | public void toString(StringBuilder sb) { 50 | sb.append("Tuple["); 51 | for (int i = 0; i < getTupleElementsCount(); i++) { 52 | getTupleElement(i).toString(sb); 53 | sb.append(", "); 54 | } 55 | if (getTupleElementsCount() > 0) { 56 | sb.setLength(sb.length() - 2); 57 | } 58 | sb.append(']'); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/result/impl/ProtoVariantValueReader.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.result.impl; 2 | 3 | import tech.ydb.proto.ValueProtos; 4 | import tech.ydb.table.result.ValueReader; 5 | 6 | 7 | /** 8 | * @author Sergey Polovko 9 | */ 10 | final class ProtoVariantValueReader extends AbstractValueReader { 11 | 12 | private final ValueProtos.Type type; 13 | private final AbstractValueReader[] itemReaders; 14 | private ValueProtos.Value value; 15 | 16 | ProtoVariantValueReader(ValueProtos.Type type, AbstractValueReader[] itemReaders) { 17 | this.type = type; 18 | this.itemReaders = itemReaders; 19 | } 20 | 21 | @Override 22 | protected ValueProtos.Type getProtoType() { 23 | return type; 24 | } 25 | 26 | @Override 27 | protected ValueProtos.Value getProtoValue() { 28 | return value; 29 | } 30 | 31 | @Override 32 | protected void setProtoValue(ValueProtos.Value value) { 33 | this.value = value; 34 | } 35 | 36 | @Override 37 | public int getVariantTypeIndex() { 38 | return value.getVariantIndex(); 39 | } 40 | 41 | @Override 42 | public ValueReader getVariantItem() { 43 | AbstractValueReader itemReader = itemReaders[value.getVariantIndex()]; 44 | itemReader.setProtoValue(value.getNestedValue()); 45 | return itemReader; 46 | } 47 | 48 | @Override 49 | public void toString(StringBuilder sb) { 50 | sb.append("Variant["); 51 | sb.append(getVariantTypeIndex()); 52 | sb.append("; "); 53 | getVariantItem().toString(sb); 54 | sb.append(']'); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/result/impl/ProtoVoidValueReader.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.result.impl; 2 | 3 | import tech.ydb.proto.ValueProtos; 4 | import tech.ydb.table.values.proto.ProtoType; 5 | import tech.ydb.table.values.proto.ProtoValue; 6 | 7 | 8 | /** 9 | * @author Sergey Polovko 10 | */ 11 | final class ProtoVoidValueReader extends AbstractValueReader { 12 | static final ProtoVoidValueReader INSTANCE = new ProtoVoidValueReader(); 13 | 14 | private ProtoVoidValueReader() { } 15 | 16 | @Override 17 | protected ValueProtos.Type getProtoType() { 18 | return ProtoType.getVoid(); 19 | } 20 | 21 | @Override 22 | protected ValueProtos.Value getProtoValue() { 23 | return ProtoValue.voidValue(); 24 | } 25 | 26 | @Override 27 | protected void setProtoValue(ValueProtos.Value value) { 28 | // skip 29 | } 30 | 31 | @Override 32 | public void toString(StringBuilder sb) { 33 | sb.append("Void"); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/settings/AutoPartitioningPolicy.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.settings; 2 | 3 | /** 4 | * @author Sergey Polovko 5 | */ 6 | public enum AutoPartitioningPolicy { 7 | DISABLED, 8 | AUTO_SPLIT, 9 | AUTO_SPLIT_MERGE, 10 | } 11 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/settings/BeginTxSettings.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.settings; 2 | 3 | /** 4 | * @author Sergey Polovko 5 | */ 6 | public class BeginTxSettings extends RequestSettings { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/settings/BulkUpsertSettings.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.settings; 2 | 3 | public class BulkUpsertSettings extends RequestSettings { 4 | } 5 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/settings/CommitTxSettings.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.settings; 2 | 3 | /** 4 | * @author Sergey Polovko 5 | */ 6 | public class CommitTxSettings extends RequestSettings { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/settings/CopyTableSettings.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.settings; 2 | 3 | 4 | /** 5 | * @author Sergey Polovko 6 | */ 7 | public class CopyTableSettings extends RequestSettings { 8 | 9 | } 10 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/settings/CreateSessionSettings.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.settings; 2 | 3 | /** 4 | * @author Sergey Polovko 5 | */ 6 | public class CreateSessionSettings extends RequestSettings { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/settings/DeleteSessionSettings.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.settings; 2 | 3 | /** 4 | * @author Sergey Polovko 5 | */ 6 | public class DeleteSessionSettings extends RequestSettings { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/settings/DescribeTableOptionsSettings.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.settings; 2 | 3 | /** 4 | * Setting for describe able options. 5 | * 6 | * @author Evgeny Kuvardin 7 | */ 8 | public class DescribeTableOptionsSettings extends RequestSettings { 9 | 10 | } 11 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/settings/DescribeTableSettings.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.settings; 2 | 3 | /** 4 | * @author Sergey Polovko 5 | */ 6 | public class DescribeTableSettings extends RequestSettings { 7 | private boolean includeTableStats; 8 | private boolean includeShardKeyBounds; 9 | private boolean includePartitionStats; 10 | 11 | public boolean isIncludeTableStats() { 12 | return includeTableStats; 13 | } 14 | 15 | public boolean isIncludeShardKeyBounds() { 16 | return includeShardKeyBounds; 17 | } 18 | 19 | public boolean isIncludePartitionStats() { 20 | return includePartitionStats; 21 | } 22 | 23 | public void setIncludeTableStats(boolean includeTableStats) { 24 | this.includeTableStats = includeTableStats; 25 | } 26 | 27 | public void setIncludeShardKeyBounds(boolean includeShardKeyBounds) { 28 | this.includeShardKeyBounds = includeShardKeyBounds; 29 | } 30 | 31 | public void setIncludePartitionStats(boolean includePartitionStats) { 32 | this.includePartitionStats = includePartitionStats; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/settings/DropTableSettings.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.settings; 2 | 3 | 4 | /** 5 | * @author Sergey Polovko 6 | */ 7 | public class DropTableSettings extends RequestSettings { 8 | 9 | } 10 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/settings/ExecuteDataQuerySettings.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.settings; 2 | 3 | import javax.annotation.Nonnull; 4 | 5 | import tech.ydb.table.query.stats.QueryStatsCollectionMode; 6 | 7 | /** 8 | * @author Sergey Polovko 9 | */ 10 | public class ExecuteDataQuerySettings extends RequestSettings { 11 | private boolean keepInQueryCache = true; 12 | private QueryStatsCollectionMode collectStats = QueryStatsCollectionMode.NONE; 13 | 14 | public boolean isKeepInQueryCache() { 15 | return keepInQueryCache; 16 | } 17 | 18 | public ExecuteDataQuerySettings disableQueryCache() { 19 | keepInQueryCache = false; 20 | return this; 21 | } 22 | 23 | @Nonnull 24 | public QueryStatsCollectionMode collectStats() { 25 | return collectStats; 26 | } 27 | 28 | public ExecuteDataQuerySettings setCollectStats(@Nonnull QueryStatsCollectionMode collectStats) { 29 | this.collectStats = collectStats; 30 | return this; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/settings/ExecuteSchemeQuerySettings.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.settings; 2 | 3 | /** 4 | * @author Sergey Polovko 5 | */ 6 | public class ExecuteSchemeQuerySettings extends RequestSettings { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/settings/ExplainDataQuerySettings.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.settings; 2 | 3 | /** 4 | * @author Sergey Polovko 5 | */ 6 | public class ExplainDataQuerySettings extends RequestSettings { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/settings/KeepAliveSessionSettings.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.settings; 2 | 3 | /** 4 | * @author Sergey Polovko 5 | */ 6 | public class KeepAliveSessionSettings extends RequestSettings { 7 | } 8 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/settings/PrepareDataQuerySettings.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.settings; 2 | 3 | /** 4 | * @author Sergey Polovko 5 | */ 6 | public class PrepareDataQuerySettings extends RequestSettings { 7 | 8 | private boolean keepInQueryCache = false; 9 | 10 | public boolean isKeepInQueryCache() { 11 | return keepInQueryCache; 12 | } 13 | 14 | public PrepareDataQuerySettings keepInQueryCache() { 15 | keepInQueryCache = true; 16 | return this; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/settings/ReplicationPolicy.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.settings; 2 | 3 | import javax.annotation.Nullable; 4 | 5 | /** 6 | * @author openminder 7 | */ 8 | 9 | public class ReplicationPolicy { 10 | 11 | @Nullable 12 | private String presetName; 13 | private int replicasCount; 14 | private boolean createPerAvailabilityZone; 15 | private boolean allowPromotion; 16 | 17 | @Nullable 18 | public String getPresetName() { 19 | return presetName; 20 | } 21 | 22 | public ReplicationPolicy setPresetName(@Nullable String presetName) { 23 | this.presetName = presetName; 24 | return this; 25 | } 26 | 27 | public int getReplicasCount() { 28 | return replicasCount; 29 | } 30 | 31 | public ReplicationPolicy setReplicasCount(int replicasCount) { 32 | this.replicasCount = replicasCount; 33 | return this; 34 | } 35 | 36 | public boolean isCreatePerAvailabilityZone() { 37 | return createPerAvailabilityZone; 38 | } 39 | 40 | public ReplicationPolicy setCreatePerAvailabilityZone(boolean createPerAvailabilityZone) { 41 | this.createPerAvailabilityZone = createPerAvailabilityZone; 42 | return this; 43 | } 44 | 45 | public boolean isAllowPromotion() { 46 | return allowPromotion; 47 | } 48 | 49 | public ReplicationPolicy setAllowPromotion(boolean allowPromotion) { 50 | this.allowPromotion = allowPromotion; 51 | return this; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/settings/RollbackTxSettings.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.settings; 2 | 3 | /** 4 | * @author Sergey Polovko 5 | */ 6 | public class RollbackTxSettings extends RequestSettings { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/settings/StoragePolicy.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.settings; 2 | 3 | import javax.annotation.Nonnull; 4 | import javax.annotation.Nullable; 5 | 6 | 7 | /** 8 | * @author Sergey Polovko 9 | */ 10 | public class StoragePolicy { 11 | 12 | @Nullable 13 | private String presetName; 14 | @Nullable 15 | private String sysLog; 16 | @Nullable 17 | private String log; 18 | @Nullable 19 | private String data; 20 | @Nullable 21 | private String external; 22 | 23 | @Nullable 24 | public String getPresetName() { 25 | return presetName; 26 | } 27 | 28 | public StoragePolicy setPresetName(@Nonnull String presetName) { 29 | this.presetName = presetName; 30 | return this; 31 | } 32 | 33 | @Nullable 34 | public String getSysLog() { 35 | return sysLog; 36 | } 37 | 38 | public StoragePolicy setSysLog(@Nonnull String sysLog) { 39 | this.sysLog = sysLog; 40 | return this; 41 | } 42 | 43 | @Nullable 44 | public String getLog() { 45 | return log; 46 | } 47 | 48 | public StoragePolicy setLog(@Nonnull String log) { 49 | this.log = log; 50 | return this; 51 | } 52 | 53 | @Nullable 54 | public String getData() { 55 | return data; 56 | } 57 | 58 | public StoragePolicy setData(@Nonnull String data) { 59 | this.data = data; 60 | return this; 61 | } 62 | 63 | @Nullable 64 | public String getExternal() { 65 | return external; 66 | } 67 | 68 | public StoragePolicy setExternal(@Nonnull String external) { 69 | this.external = external; 70 | return this; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/settings/TtlSettings.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.settings; 2 | 3 | import javax.annotation.Nonnull; 4 | 5 | @Deprecated 6 | public final class TtlSettings { 7 | private final String dateTimeColumn; 8 | private final int expireAfterSeconds; 9 | 10 | public TtlSettings(@Nonnull String dateTimeColumn, int expireAfterSeconds) { 11 | this.dateTimeColumn = dateTimeColumn; 12 | this.expireAfterSeconds = expireAfterSeconds; 13 | } 14 | 15 | public String getDateTimeColumn() { 16 | return dateTimeColumn; 17 | } 18 | 19 | public int getExpireAfterSeconds() { 20 | return expireAfterSeconds; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/transaction/Transaction.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.transaction; 2 | 3 | import java.util.concurrent.CompletableFuture; 4 | 5 | import tech.ydb.core.Status; 6 | import tech.ydb.table.settings.CommitTxSettings; 7 | import tech.ydb.table.settings.RollbackTxSettings; 8 | 9 | /** 10 | * @author Sergey Polovko 11 | * Consider using {@link TableTransaction} instead 12 | */ 13 | public interface Transaction { 14 | enum Mode { 15 | SERIALIZABLE_READ_WRITE, 16 | ONLINE_READ_ONLY, 17 | STALE_READ_ONLY, 18 | SNAPSHOT_READ_ONLY; 19 | } 20 | 21 | String getId(); 22 | 23 | CompletableFuture commit(CommitTxSettings settings); 24 | CompletableFuture rollback(RollbackTxSettings settings); 25 | 26 | default CompletableFuture commit() { 27 | return commit(new CommitTxSettings()); 28 | } 29 | 30 | default CompletableFuture rollback() { 31 | return rollback(new RollbackTxSettings()); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/utils/Hex.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.utils; 2 | 3 | import com.google.protobuf.ByteString; 4 | 5 | 6 | /** 7 | * @author Sergey Polovko 8 | */ 9 | public class Hex { 10 | private static final char[] HEX_DIGITS = new char[] { 11 | '0', '1', '2', '3', '4', '5', '6', '7', 12 | '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' 13 | }; 14 | 15 | private Hex() { } 16 | 17 | public static void toHex(ByteString bytes, StringBuilder sb) { 18 | sb.ensureCapacity(bytes.size()); 19 | for (int i = 0; i < bytes.size(); i++) { 20 | byte b = bytes.byteAt(i); 21 | sb.append(HEX_DIGITS[(b & 0xf0) >>> 4]); 22 | sb.append(HEX_DIGITS[b & 0x0f]); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/utils/LittleEndian.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.utils; 2 | 3 | /** 4 | * @author Sergey Polovko 5 | */ 6 | public class LittleEndian { 7 | private LittleEndian() { } 8 | 9 | /** 10 | * Reverses the byte order of a long value. 11 | */ 12 | public static long bswap(long v) { 13 | return 14 | (v & 0x00000000000000ffL) << 56 | 15 | (v & 0x000000000000ff00L) << 40 | 16 | (v & 0x0000000000ff0000L) << 24 | 17 | (v & 0x00000000ff000000L) << 8 | 18 | (v & 0x000000ff00000000L) >>> 8 | 19 | (v & 0x0000ff0000000000L) >>> 24 | 20 | (v & 0x00ff000000000000L) >>> 40 | 21 | (v & 0xff00000000000000L) >>> 56; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/values/NullType.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.values; 2 | 3 | 4 | import tech.ydb.proto.ValueProtos; 5 | import tech.ydb.table.values.proto.ProtoType; 6 | 7 | 8 | /** 9 | * @author Aleksandr Gorshenin 10 | */ 11 | public final class NullType implements Type { 12 | 13 | private static final NullType INSTANCE = new NullType(); 14 | 15 | private NullType() { 16 | } 17 | 18 | public static NullType of() { 19 | return NullType.INSTANCE; 20 | } 21 | 22 | @Override 23 | public Kind getKind() { 24 | return Kind.NULL; 25 | } 26 | 27 | @Override 28 | public String toString() { 29 | return "Null"; 30 | } 31 | 32 | @Override 33 | public ValueProtos.Type toPb() { 34 | return ProtoType.getNull(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/values/NullValue.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.values; 2 | 3 | import tech.ydb.proto.ValueProtos; 4 | import tech.ydb.table.values.proto.ProtoValue; 5 | 6 | 7 | /** 8 | * @author Aleksandr Gorshenin 9 | */ 10 | public class NullValue implements Value { 11 | 12 | private static final NullValue INSTANCE = new NullValue(); 13 | 14 | private NullValue() { 15 | } 16 | 17 | public static NullValue of() { 18 | return INSTANCE; 19 | } 20 | 21 | @Override 22 | public String toString() { 23 | return "Null"; 24 | } 25 | 26 | @Override 27 | public NullType getType() { 28 | return NullType.of(); 29 | } 30 | 31 | @Override 32 | public ValueProtos.Value toPb() { 33 | return ProtoValue.nullValue(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/values/OptionalType.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.values; 2 | 3 | import java.util.Objects; 4 | 5 | import tech.ydb.proto.ValueProtos; 6 | import tech.ydb.table.values.proto.ProtoType; 7 | 8 | 9 | /** 10 | * @author Sergey Polovko 11 | */ 12 | public final class OptionalType implements Type { 13 | 14 | private final Type itemType; 15 | 16 | private OptionalType(Type itemType) { 17 | this.itemType = itemType; 18 | } 19 | 20 | public static OptionalType of(Type itemType) { 21 | return new OptionalType(itemType); 22 | } 23 | 24 | public Type getItemType() { 25 | return itemType; 26 | } 27 | 28 | @Override 29 | public Kind getKind() { 30 | return Kind.OPTIONAL; 31 | } 32 | 33 | @Override 34 | public boolean equals(Object o) { 35 | if (this == o) { 36 | return true; 37 | } 38 | 39 | if (o == null || o.getClass() != OptionalType.class) { 40 | return false; 41 | } 42 | 43 | OptionalType optionalType = (OptionalType) o; 44 | return itemType.equals(optionalType.getItemType()); 45 | } 46 | 47 | @Override 48 | public int hashCode() { 49 | return 31 * Kind.OPTIONAL.hashCode() + itemType.hashCode(); 50 | } 51 | 52 | @Override 53 | public String toString() { 54 | return String.valueOf(itemType) + '?'; 55 | } 56 | 57 | @Override 58 | public ValueProtos.Type toPb() { 59 | return ProtoType.getOptional(itemType.toPb()); 60 | } 61 | 62 | public OptionalValue emptyValue() { 63 | return new OptionalValue(this, null); 64 | } 65 | 66 | public OptionalValue newValue(Value item) { 67 | return new OptionalValue(this, Objects.requireNonNull(item, "item")); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/values/PgType.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.values; 2 | 3 | import java.util.Objects; 4 | 5 | import tech.ydb.proto.ValueProtos; 6 | import tech.ydb.table.values.proto.ProtoType; 7 | 8 | /** 9 | * 10 | * @author Aleksandr Gorshenin 11 | */ 12 | public class PgType implements Type { 13 | private final int oid; 14 | private final int typlen; 15 | private final int typmod; 16 | 17 | private PgType(int oid, int typlen, int typmod) { 18 | this.oid = oid; 19 | this.typlen = typlen; 20 | this.typmod = typmod; 21 | } 22 | 23 | public static PgType of(int oid) { 24 | return new PgType(oid, 0, 0); 25 | } 26 | 27 | public static PgType of(int oid, int typlen, int typmod) { 28 | return new PgType(oid, typlen, typmod); 29 | } 30 | 31 | public int getOid() { 32 | return oid; 33 | } 34 | 35 | @Override 36 | public Kind getKind() { 37 | return Kind.PG_TYPE; 38 | } 39 | 40 | @Override 41 | public boolean equals(Object o) { 42 | if (this == o) { 43 | return true; 44 | } 45 | 46 | if (o == null || getClass() != o.getClass()) { 47 | return false; 48 | } 49 | 50 | PgType that = (PgType) o; 51 | return oid == that.oid && typlen == that.typlen && typmod == that.typmod; 52 | } 53 | 54 | @Override 55 | public int hashCode() { 56 | return Objects.hash(oid, typlen, typmod); 57 | } 58 | 59 | @Override 60 | public String toString() { 61 | return "PgType[" + oid + "]"; 62 | } 63 | 64 | @Override 65 | public ValueProtos.Type toPb() { 66 | return ProtoType.getPgType(oid, typlen, typmod); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/values/Type.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.values; 2 | 3 | import tech.ydb.proto.ValueProtos; 4 | 5 | 6 | /** 7 | * @author Sergey Polovko 8 | */ 9 | public interface Type { 10 | 11 | Type[] EMPTY_ARRAY = {}; 12 | 13 | Kind getKind(); 14 | 15 | @Override 16 | boolean equals(Object o); 17 | 18 | @Override 19 | int hashCode(); 20 | 21 | @Override 22 | String toString(); 23 | 24 | ValueProtos.Type toPb(); 25 | 26 | default OptionalType makeOptional() { 27 | return OptionalType.of(this); 28 | } 29 | 30 | default Type unwrapOptional() { 31 | if (this instanceof OptionalType) { 32 | return ((OptionalType) this).getItemType(); 33 | } 34 | throw new IllegalStateException("expected OptionalType, but was: " + this); 35 | } 36 | 37 | /** 38 | * KIND 39 | */ 40 | enum Kind { 41 | PRIMITIVE, 42 | DECIMAL, 43 | OPTIONAL, 44 | LIST, 45 | TUPLE, 46 | STRUCT, 47 | DICT, 48 | VARIANT, 49 | VOID, 50 | NULL, 51 | PG_TYPE; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/values/Value.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.values; 2 | 3 | import tech.ydb.proto.ValueProtos; 4 | 5 | /** 6 | * @author Sergey Polovko 7 | * @param type of value 8 | */ 9 | public interface Value { 10 | 11 | Value[] EMPTY_ARRAY = {}; 12 | 13 | T getType(); 14 | 15 | ValueProtos.Value toPb(); 16 | 17 | default PrimitiveValue asData() { 18 | return (PrimitiveValue) this; 19 | } 20 | 21 | default DictValue asDict() { 22 | return (DictValue) this; 23 | } 24 | 25 | default ListValue asList() { 26 | return (ListValue) this; 27 | } 28 | 29 | default OptionalValue asOptional() { 30 | return (OptionalValue) this; 31 | } 32 | 33 | /** 34 | * @deprecated Use {{@link #asStruct()}} instead 35 | */ 36 | @Deprecated 37 | default StructValue asStuct() { 38 | return asStruct(); 39 | } 40 | 41 | default StructValue asStruct() { 42 | return (StructValue) this; 43 | } 44 | 45 | default VariantValue asVariant() { 46 | return (VariantValue) this; 47 | } 48 | 49 | default VoidValue asVoid() { 50 | return (VoidValue) this; 51 | } 52 | 53 | default OptionalValue makeOptional() { 54 | return OptionalValue.of(this); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/values/VoidType.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.values; 2 | 3 | 4 | import tech.ydb.proto.ValueProtos; 5 | import tech.ydb.table.values.proto.ProtoType; 6 | 7 | 8 | /** 9 | * @author Sergey Polovko 10 | */ 11 | public final class VoidType implements Type { 12 | 13 | private static final VoidType INSTANCE = new VoidType(); 14 | 15 | private VoidType() { 16 | } 17 | 18 | public static VoidType of() { 19 | return VoidType.INSTANCE; 20 | } 21 | 22 | @Override 23 | public Kind getKind() { 24 | return Kind.VOID; 25 | } 26 | 27 | @Override 28 | public boolean equals(Object o) { 29 | return this == o; 30 | } 31 | 32 | @Override 33 | public int hashCode() { 34 | return 31 * Kind.VOID.hashCode(); 35 | } 36 | 37 | @Override 38 | public String toString() { 39 | return "Void"; 40 | } 41 | 42 | @Override 43 | public ValueProtos.Type toPb() { 44 | return ProtoType.getVoid(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /table/src/main/java/tech/ydb/table/values/VoidValue.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.values; 2 | 3 | import tech.ydb.proto.ValueProtos; 4 | import tech.ydb.table.values.proto.ProtoValue; 5 | 6 | 7 | /** 8 | * @author Sergey Polovko 9 | */ 10 | public class VoidValue implements Value { 11 | 12 | private static final VoidValue INSTANCE = new VoidValue(); 13 | 14 | private VoidValue() { 15 | } 16 | 17 | public static VoidValue of() { 18 | return INSTANCE; 19 | } 20 | 21 | @Override 22 | public boolean equals(Object o) { 23 | return o == this; 24 | } 25 | 26 | @Override 27 | public int hashCode() { 28 | return 1987; 29 | } 30 | 31 | @Override 32 | public String toString() { 33 | return "Void"; 34 | } 35 | 36 | @Override 37 | public VoidType getType() { 38 | return VoidType.of(); 39 | } 40 | 41 | @Override 42 | public ValueProtos.Value toPb() { 43 | return ProtoValue.voidValue(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /table/src/test/java/tech/ydb/table/impl/pool/MockedClock.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.impl.pool; 2 | 3 | import java.time.Clock; 4 | import java.time.Instant; 5 | import java.time.ZoneId; 6 | 7 | /** 8 | * 9 | * @author Aleksandr Gorshenin 10 | */ 11 | public class MockedClock extends Clock { 12 | private final ZoneId zoneID; 13 | private final MockedInstant mock; 14 | 15 | private MockedClock(ZoneId zoneId, MockedInstant instant) { 16 | this.zoneID = zoneId; 17 | this.mock = instant; 18 | } 19 | 20 | @Override 21 | public ZoneId getZone() { 22 | return zoneID; 23 | } 24 | 25 | @Override 26 | public Clock withZone(ZoneId zone) { 27 | return new MockedClock(zone, mock); 28 | } 29 | 30 | @Override 31 | public Instant instant() { 32 | return mock.instant(); 33 | } 34 | 35 | public void goToFuture(Instant future) { 36 | mock.goToFuture(future); 37 | } 38 | 39 | public void reset(Instant now) { 40 | mock.reset(now); 41 | } 42 | 43 | public static MockedClock create(ZoneId zoneId) { 44 | return new MockedClock(zoneId, new MockedInstant(Instant.now())); 45 | } 46 | 47 | private static class MockedInstant { 48 | private volatile Instant now; 49 | 50 | public MockedInstant(Instant now) { 51 | reset(now); 52 | } 53 | 54 | private void reset(Instant now) { 55 | this.now = now; 56 | } 57 | 58 | private Instant instant() { 59 | return now; 60 | } 61 | 62 | private void goToFuture(Instant future) { 63 | if (future.isAfter(now)) { 64 | this.now = future; 65 | } 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /table/src/test/java/tech/ydb/table/integration/DescribeTableTest.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.integration; 2 | 3 | import org.junit.Assert; 4 | import org.junit.ClassRule; 5 | import org.junit.Test; 6 | 7 | import tech.ydb.core.Issue; 8 | import tech.ydb.core.Status; 9 | import tech.ydb.core.StatusCode; 10 | import tech.ydb.table.SessionRetryContext; 11 | import tech.ydb.table.impl.SimpleTableClient; 12 | import tech.ydb.table.rpc.grpc.GrpcTableRpc; 13 | import tech.ydb.test.junit4.GrpcTransportRule; 14 | 15 | /** 16 | * 17 | * @author Aleksandr Gorshenin 18 | */ 19 | public class DescribeTableTest { 20 | @ClassRule 21 | public static final GrpcTransportRule YDB_TRANSPORT = new GrpcTransportRule(); 22 | private static final SessionRetryContext CTX = SessionRetryContext.create(SimpleTableClient.newClient( 23 | GrpcTableRpc.useTransport(YDB_TRANSPORT) 24 | ).build()).build(); 25 | 26 | @Test 27 | public void wrongTypeTest() { 28 | String databasePath = YDB_TRANSPORT.getDatabase(); 29 | Status status = CTX.supplyResult(s -> s.describeTable(databasePath)).join().getStatus(); 30 | 31 | Assert.assertFalse("Unexpected success", status.isSuccess()); 32 | Assert.assertEquals(StatusCode.SCHEME_ERROR, status.getCode()); 33 | Issue[] issues = status.getIssues(); 34 | Assert.assertEquals(1, issues.length); 35 | String entryName = databasePath.substring(1); // remove lead / 36 | Assert.assertEquals("Entry " + entryName + " with type DIRECTORY is not a table", issues[0].getMessage()); 37 | Assert.assertEquals(Issue.Severity.ERROR, issues[0].getSeverity()); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /table/src/test/java/tech/ydb/table/utils/HexTest.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.utils; 2 | 3 | import com.google.protobuf.ByteString; 4 | import org.junit.Assert; 5 | import org.junit.Test; 6 | 7 | 8 | /** 9 | * @author Sergey Polovko 10 | */ 11 | public class HexTest { 12 | 13 | @Test 14 | public void empty() { 15 | StringBuilder sb = new StringBuilder(); 16 | Hex.toHex(ByteString.EMPTY, sb); 17 | Assert.assertEquals("", sb.toString()); 18 | } 19 | 20 | @Test 21 | public void oneByte() { 22 | for (int i = 0; i <= 255; i++) { 23 | String expected = String.format("%02x", i); 24 | 25 | StringBuilder sb = new StringBuilder(); 26 | Hex.toHex(ByteString.copyFrom(new byte[] { (byte) i }), sb); 27 | Assert.assertEquals(expected, sb.toString()); 28 | } 29 | } 30 | 31 | @Test 32 | public void manyBytes() { 33 | StringBuilder sb = new StringBuilder(); 34 | Hex.toHex(ByteString.copyFrom(new byte[] { 35 | (byte) 0x00, (byte) 0x11, (byte) 0x22, (byte) 0x33, 36 | (byte) 0x44, (byte) 0x55, (byte) 0x66, (byte) 0x77, 37 | (byte) 0x88, (byte) 0x99, (byte) 0xaa, (byte) 0xbb, 38 | (byte) 0xcc, (byte) 0xdd, (byte) 0xee, (byte) 0xff, 39 | }), sb); 40 | Assert.assertEquals("00112233445566778899aabbccddeeff", sb.toString()); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /table/src/test/java/tech/ydb/table/utils/LittleEndianTest.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.utils; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | 7 | 8 | /** 9 | * @author Sergey Polovko 10 | */ 11 | public class LittleEndianTest { 12 | 13 | @Test 14 | public void bswap() { 15 | Assert.assertEquals(0x0000000000000000L, LittleEndian.bswap(0x0000000000000000L)); 16 | Assert.assertEquals(0xefcdab9078563412L, LittleEndian.bswap(0x1234567890abcdefL)); 17 | Assert.assertEquals(0xffffffffffffffffL, LittleEndian.bswap(0xffffffffffffffffL)); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /table/src/test/java/tech/ydb/table/utils/TtlModeMappingTest.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.table.utils; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | import tech.ydb.proto.table.YdbTable; 6 | import tech.ydb.table.description.TableTtl; 7 | 8 | public class TtlModeMappingTest { 9 | @Test 10 | public void protoMappingTest() { 11 | YdbTable.TtlSettings.ModeCase[] apiValues = YdbTable.TtlSettings.ModeCase.values(); 12 | for (YdbTable.TtlSettings.ModeCase apiValue : apiValues) { 13 | TableTtl.TtlMode sdkTtlMode = TableTtl.TtlMode.forCase(apiValue.getNumber()); 14 | Assert.assertNotNull(String.format("TtlMode not defined for %s", apiValue), sdkTtlMode); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /table/src/test/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /tests/common/src/main/java/tech/ydb/test/integration/YdbHelper.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.test.integration; 2 | 3 | import tech.ydb.core.grpc.GrpcTransport; 4 | 5 | /** 6 | * 7 | * @author Aleksandr Gorshenin 8 | */ 9 | public interface YdbHelper extends AutoCloseable { 10 | GrpcTransport createTransport(); 11 | 12 | String endpoint(); 13 | String database(); 14 | 15 | boolean useTls(); 16 | byte[] pemCert(); 17 | 18 | String authToken(); 19 | 20 | @Override 21 | void close(); 22 | } 23 | -------------------------------------------------------------------------------- /tests/common/src/main/java/tech/ydb/test/integration/utils/PortsGenerator.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.test.integration.utils; 2 | 3 | import java.io.IOException; 4 | import java.net.InetAddress; 5 | import java.net.ServerSocket; 6 | import java.security.SecureRandom; 7 | import java.util.Random; 8 | 9 | import javax.net.ServerSocketFactory; 10 | 11 | /** 12 | * 13 | * @author Alexandr Gorshenin 14 | */ 15 | public class PortsGenerator { 16 | private static final int PORT_RANGE_MIN = 51000; 17 | private static final int PORT_RANGE_MAX = 59000; 18 | private static final Random RANDOM = new SecureRandom(); 19 | 20 | private int nextPort; 21 | 22 | public PortsGenerator() { 23 | this.nextPort = randomPort(); 24 | } 25 | 26 | public int findAvailablePort() { 27 | while (true) { 28 | nextPort++; 29 | if (nextPort > PORT_RANGE_MAX) { 30 | nextPort = randomPort(); 31 | } 32 | 33 | try { 34 | ServerSocket serverSocket = ServerSocketFactory.getDefault() 35 | .createServerSocket(nextPort, 1, InetAddress.getByName("localhost")); 36 | serverSocket.close(); 37 | return nextPort; 38 | } catch (IOException ex) { } // port is used 39 | } 40 | } 41 | 42 | private static int randomPort() { 43 | return PORT_RANGE_MIN + RANDOM.nextInt(PORT_RANGE_MAX - PORT_RANGE_MIN + 1); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /tests/common/src/main/java/tech/ydb/test/integration/utils/ProxyYdbHelper.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.test.integration.utils; 2 | 3 | import tech.ydb.core.grpc.GrpcTransport; 4 | import tech.ydb.test.integration.YdbHelper; 5 | 6 | /** 7 | * 8 | * @author Aleksandr Gorshenin 9 | */ 10 | public abstract class ProxyYdbHelper implements YdbHelper { 11 | 12 | protected abstract YdbHelper origin(); 13 | 14 | private YdbHelper checked() { 15 | YdbHelper check = origin(); 16 | if (check == null) { 17 | throw new NullPointerException("Can't proxy method of null"); 18 | } 19 | return check; 20 | } 21 | 22 | @Override 23 | public GrpcTransport createTransport() { 24 | return checked().createTransport(); 25 | } 26 | 27 | @Override 28 | public String endpoint() { 29 | return checked().endpoint(); 30 | } 31 | 32 | @Override 33 | public String database() { 34 | return checked().database(); 35 | } 36 | 37 | @Override 38 | public boolean useTls() { 39 | return checked().useTls(); 40 | } 41 | 42 | @Override 43 | public byte[] pemCert() { 44 | return checked().pemCert(); 45 | } 46 | 47 | @Override 48 | public String authToken() { 49 | return checked().authToken(); 50 | } 51 | 52 | @Override 53 | public void close() { 54 | // Usally origin helper must be closed by its owner 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /tests/common/src/test/java/tech/ydb/test/integration/GrpcTransportMock.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.test.integration; 2 | 3 | 4 | import java.util.concurrent.CompletableFuture; 5 | 6 | import org.mockito.MockedStatic; 7 | import org.mockito.Mockito; 8 | 9 | import tech.ydb.core.Result; 10 | import tech.ydb.core.grpc.GrpcTransport; 11 | import tech.ydb.core.grpc.GrpcTransportBuilder; 12 | 13 | /** 14 | * 15 | * @author Aleksandr Gorshenin 16 | */ 17 | public class GrpcTransportMock implements AutoCloseable { 18 | private final MockedStatic staticGrpcTransport = Mockito.mockStatic(GrpcTransport.class); 19 | 20 | private final GrpcTransportBuilder builderMock = Mockito.mock(GrpcTransportBuilder.class); 21 | private final GrpcTransport transportMock = Mockito.mock(GrpcTransport.class); 22 | 23 | public void setup(String database) { 24 | staticGrpcTransport.when(() -> GrpcTransport.forEndpoint(Mockito.any(), Mockito.any())) 25 | .thenReturn(builderMock); 26 | 27 | Mockito.when(builderMock.build()).thenReturn(transportMock); 28 | 29 | Mockito.when(transportMock.getDatabase()).thenReturn(database); 30 | Mockito.when(transportMock.unaryCall(Mockito.any(), Mockito.any(), Mockito.any())) 31 | .thenReturn(CompletableFuture.completedFuture(Result.success(Boolean.TRUE))); 32 | } 33 | 34 | @Override 35 | public void close() { 36 | staticGrpcTransport.close(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /tests/common/src/test/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /tests/junit4-support/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 4.0.0 8 | 9 | tech.ydb 10 | ydb-sdk-parent 11 | 2.3.16-SNAPSHOT 12 | ../../pom.xml 13 | 14 | 15 | tech.ydb.test 16 | ydb-junit4-support 17 | JUnit 4 support module 18 | 19 | jar 20 | 21 | 22 | 23 | tech.ydb.test 24 | ydb-tests-common 25 | 26 | 27 | 28 | junit 29 | junit 30 | provided 31 | 32 | 33 | -------------------------------------------------------------------------------- /tests/junit5-support/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 4.0.0 8 | 9 | tech.ydb 10 | ydb-sdk-parent 11 | 2.3.16-SNAPSHOT 12 | ../../pom.xml 13 | 14 | 15 | tech.ydb.test 16 | ydb-junit5-support 17 | JUnit 5 support module 18 | 19 | jar 20 | 21 | 22 | 23 | tech.ydb.test 24 | ydb-tests-common 25 | 26 | 27 | 28 | org.junit.jupiter 29 | junit-jupiter-api 30 | provided 31 | 32 | 33 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/description/Codec.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.description; 2 | 3 | /** 4 | * @author Nikolay Perfilov 5 | */ 6 | public enum Codec { 7 | RAW, 8 | GZIP, 9 | LZOP, 10 | ZSTD, 11 | CUSTOM; 12 | } 13 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/description/ConsumerDescription.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.description; 2 | 3 | 4 | import java.util.List; 5 | import java.util.Objects; 6 | import java.util.stream.Collectors; 7 | 8 | import tech.ydb.proto.topic.YdbTopic; 9 | 10 | /** 11 | * 12 | * @author Aleksandr Gorshenin 13 | */ 14 | public class ConsumerDescription { 15 | private final Consumer consumer; 16 | private final List partitions; 17 | 18 | public ConsumerDescription(YdbTopic.DescribeConsumerResult result) { 19 | this.consumer = new Consumer(result.getConsumer()); 20 | this.partitions = result.getPartitionsList().stream() 21 | .map(ConsumerPartitionInfo::new) 22 | .collect(Collectors.toList()); 23 | } 24 | 25 | public Consumer getConsumer() { 26 | return consumer; 27 | } 28 | 29 | public List getPartitions() { 30 | return partitions; 31 | } 32 | 33 | @Override 34 | public boolean equals(Object o) { 35 | if (this == o) { 36 | return true; 37 | } 38 | if (o == null || getClass() != o.getClass()) { 39 | return false; 40 | } 41 | ConsumerDescription that = (ConsumerDescription) o; 42 | return Objects.equals(consumer, that.consumer) && Objects.equals(partitions, that.partitions); 43 | } 44 | 45 | @Override 46 | public int hashCode() { 47 | return Objects.hash(consumer, partitions); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/description/MetadataItem.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.description; 2 | 3 | import javax.annotation.Nonnull; 4 | 5 | /** 6 | * @author Nikolay Perfilov 7 | */ 8 | public class MetadataItem { 9 | private final String key; 10 | private final byte[] value; 11 | 12 | public MetadataItem(@Nonnull String key, byte[] value) { 13 | this.key = key; 14 | this.value = value; 15 | } 16 | 17 | public String getKey() { 18 | return key; 19 | } 20 | 21 | public byte[] getValue() { 22 | return value; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/description/MeteringMode.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.description; 2 | 3 | /** 4 | * @author Nikolay Perfilov 5 | */ 6 | public enum MeteringMode { 7 | UNSPECIFIED, 8 | RESERVED_CAPACITY, 9 | REQUEST_UNITS 10 | } 11 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/description/MultipleWindowsStat.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.description; 2 | 3 | import java.util.Objects; 4 | 5 | import tech.ydb.proto.topic.YdbTopic; 6 | 7 | /** 8 | * @author Nikolay Perfilov 9 | */ 10 | public class MultipleWindowsStat { 11 | private final long perMinute; 12 | private final long perHour; 13 | private final long perDay; 14 | 15 | public MultipleWindowsStat(YdbTopic.MultipleWindowsStat stat) { 16 | this.perMinute = stat.getPerMinute(); 17 | this.perHour = stat.getPerHour(); 18 | this.perDay = stat.getPerDay(); 19 | } 20 | 21 | public MultipleWindowsStat(long perMinute, long perHour, long perDay) { 22 | this.perMinute = perMinute; 23 | this.perHour = perHour; 24 | this.perDay = perDay; 25 | } 26 | 27 | public long getPerMinute() { 28 | return perMinute; 29 | } 30 | 31 | public long getPerHour() { 32 | return perHour; 33 | } 34 | 35 | public long getPerDay() { 36 | return perDay; 37 | } 38 | 39 | @Override 40 | public boolean equals(Object o) { 41 | if (this == o) { 42 | return true; 43 | } 44 | if (o == null || getClass() != o.getClass()) { 45 | return false; 46 | } 47 | MultipleWindowsStat that = (MultipleWindowsStat) o; 48 | return perMinute == that.perMinute && perHour == that.perHour && perDay == that.perDay; 49 | } 50 | 51 | @Override 52 | public int hashCode() { 53 | return Objects.hash(perMinute, perHour, perDay); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/description/OffsetsRange.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.description; 2 | 3 | /** 4 | * @author Nikolay Perfilov 5 | */ 6 | public interface OffsetsRange { 7 | long getStart(); 8 | 9 | long getEnd(); 10 | } 11 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/description/PartitionLocation.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.description; 2 | 3 | import tech.ydb.proto.topic.YdbTopic; 4 | 5 | /** 6 | * 7 | * @author Aleksandr Gorshenin 8 | */ 9 | public class PartitionLocation { 10 | private final int nodeId; 11 | private final long generation; 12 | 13 | public PartitionLocation(YdbTopic.PartitionLocation location) { 14 | this.nodeId = location.getNodeId(); 15 | this.generation = location.getGeneration(); 16 | } 17 | 18 | public int getNodeId() { 19 | return nodeId; 20 | } 21 | 22 | public long getGeneration() { 23 | return generation; 24 | } 25 | 26 | @Override 27 | public String toString() { 28 | return "PartitionLocation{nodeId=" + nodeId + ", generation=" + generation + "}"; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/description/SupportedCodecs.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.description; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.Objects; 6 | 7 | import com.google.common.collect.ImmutableList; 8 | 9 | /** 10 | * @author Nikolay Perfilov 11 | */ 12 | public class SupportedCodecs { 13 | private final List codecs; 14 | 15 | public SupportedCodecs(Builder builder) { 16 | this.codecs = ImmutableList.copyOf(builder.codecs); 17 | } 18 | 19 | public SupportedCodecs(List codecs) { 20 | this.codecs = codecs; 21 | } 22 | 23 | public List getCodecs() { 24 | return codecs; 25 | } 26 | 27 | public static Builder newBuilder() { 28 | return new Builder(); 29 | } 30 | 31 | /** 32 | * BUILDER 33 | */ 34 | public static class Builder { 35 | private List codecs = new ArrayList<>(); 36 | 37 | public Builder addCodec(Codec codec) { 38 | codecs.add(codec); 39 | return this; 40 | } 41 | 42 | public Builder setCodecs(List supportedCodecs) { 43 | this.codecs = supportedCodecs; 44 | return this; 45 | } 46 | 47 | public SupportedCodecs build() { 48 | return new SupportedCodecs(this); 49 | } 50 | } 51 | 52 | @Override 53 | public boolean equals(Object o) { 54 | if (this == o) { 55 | return true; 56 | } 57 | if (o == null || getClass() != o.getClass()) { 58 | return false; 59 | } 60 | SupportedCodecs that = (SupportedCodecs) o; 61 | return Objects.equals(codecs, that.codecs); 62 | } 63 | 64 | @Override 65 | public int hashCode() { 66 | return Objects.hashCode(codecs); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/impl/Session.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.impl; 2 | 3 | /** 4 | * @author Nikolay Perfilov 5 | */ 6 | public interface Session { 7 | void startAndInitialize(); 8 | boolean shutdown(); 9 | } 10 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/impl/TopicClientBuilderImpl.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.impl; 2 | 3 | import java.util.concurrent.Executor; 4 | 5 | import tech.ydb.topic.TopicClient; 6 | import tech.ydb.topic.TopicRpc; 7 | 8 | 9 | /** 10 | * @author Nikolay Perfilov 11 | */ 12 | public class TopicClientBuilderImpl implements TopicClient.Builder { 13 | 14 | protected final TopicRpc topicRpc; 15 | protected Integer compressionExecutorThreadCount; 16 | protected Executor compressionExecutor; 17 | 18 | public TopicClientBuilderImpl(TopicRpc topicRpc) { 19 | this.topicRpc = topicRpc; 20 | } 21 | 22 | @Override 23 | public TopicClientBuilderImpl setCompressionPoolThreadCount(Integer compressionPoolThreadCount) { 24 | this.compressionExecutorThreadCount = compressionPoolThreadCount; 25 | return this; 26 | } 27 | 28 | @Override 29 | public TopicClientBuilderImpl setCompressionExecutor(Executor compressionExecutor) { 30 | this.compressionExecutor = compressionExecutor; 31 | return this; 32 | } 33 | 34 | @Override 35 | public TopicClient build() { 36 | return new TopicClientImpl(this); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/read/DecompressionException.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.read; 2 | 3 | import java.io.IOException; 4 | import java.io.UncheckedIOException; 5 | 6 | import tech.ydb.topic.description.Codec; 7 | 8 | /** 9 | * @author Nikolay Perfilov 10 | */ 11 | public class DecompressionException extends UncheckedIOException { 12 | private static final long serialVersionUID = 2720187645859527813L; 13 | 14 | private final byte[] rawData; 15 | private final Codec codec; 16 | 17 | public DecompressionException(String message, IOException cause, byte[] rawData, Codec codec) { 18 | super(message, cause); 19 | this.rawData = rawData; 20 | this.codec = codec; 21 | } 22 | 23 | /** 24 | * @return Raw message byte data that failed be decompressed 25 | */ 26 | public byte[] getRawData() { 27 | return rawData; 28 | } 29 | 30 | /** 31 | * @return Codec of message byte data 32 | */ 33 | public Codec getCodec() { 34 | return codec; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/read/DeferredCommitter.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.read; 2 | 3 | import tech.ydb.topic.read.events.DataReceivedEvent; 4 | import tech.ydb.topic.read.impl.DeferredCommitterImpl; 5 | 6 | /** 7 | * A helper class that is used to call deferred commits. 8 | * Several {@link Message}s or/and {@link tech.ydb.topic.read.events.DataReceivedEvent}s can be accepted to commit later 9 | * all at once. 10 | * Contains no data references and therefore may also be useful in cases where commit() is called after processing data 11 | * in an external system. 12 | * 13 | * @author Nikolay Perfilov 14 | */ 15 | public interface DeferredCommitter extends MessageAccumulator { 16 | /** 17 | * Creates a new instance of {@link DeferredCommitter} 18 | * 19 | * @return a new instance of {@link DeferredCommitter} 20 | */ 21 | static DeferredCommitter newInstance() { 22 | return new DeferredCommitterImpl(); 23 | } 24 | 25 | /** 26 | * Commits offset ranges from all {@link Message}s and {@link DataReceivedEvent}s 27 | * that were added to this DeferredCommitter since last commit 28 | */ 29 | void commit(); 30 | } 31 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/read/MessageAccumulator.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.read; 2 | 3 | import tech.ydb.topic.read.events.DataReceivedEvent; 4 | 5 | /** 6 | * A common interface that is used to accumulate several {@link Message}s or/and 7 | * {@link tech.ydb.topic.read.events.DataReceivedEvent}s to commit later all at once or to add to transaction. 8 | * 9 | * @author Nikolay Perfilov 10 | */ 11 | public interface MessageAccumulator { 12 | 13 | /** 14 | * Adds a {@link Message} to commit it later or to add to transaction 15 | * 16 | * @param message a {@link Message} 17 | */ 18 | void add(Message message); 19 | 20 | /** 21 | * Adds a {@link DataReceivedEvent} to commit all its messages later or to add to transaction 22 | * 23 | * @param event a {@link DataReceivedEvent} 24 | */ 25 | void add(DataReceivedEvent event); 26 | } 27 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/read/PartitionOffsets.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.read; 2 | 3 | import java.util.List; 4 | 5 | import tech.ydb.topic.description.OffsetsRange; 6 | 7 | /** 8 | * @author Nikolay Perfilov 9 | */ 10 | public class PartitionOffsets { 11 | private final PartitionSession partitionSession; 12 | private final List offsets; 13 | 14 | public PartitionOffsets(PartitionSession partitionSession, List offsets) { 15 | this.partitionSession = partitionSession; 16 | this.offsets = offsets; 17 | } 18 | 19 | public PartitionSession getPartitionSession() { 20 | return partitionSession; 21 | } 22 | 23 | public List getOffsets() { 24 | return offsets; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/read/PartitionSession.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.read; 2 | 3 | /** 4 | * @author Nikolay Perfilov 5 | */ 6 | public class PartitionSession { 7 | private final long id; 8 | private final long partitionId; 9 | private final String path; 10 | 11 | public PartitionSession(long id, long partitionId, String path) { 12 | this.id = id; 13 | this.partitionId = partitionId; 14 | this.path = path; 15 | } 16 | 17 | public long getId() { 18 | return id; 19 | } 20 | 21 | public long getPartitionId() { 22 | return partitionId; 23 | } 24 | 25 | public String getPath() { 26 | return path; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/read/TransactionMessageAccumulator.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.read; 2 | 3 | import java.util.concurrent.CompletableFuture; 4 | 5 | import tech.ydb.common.transaction.YdbTransaction; 6 | import tech.ydb.core.Status; 7 | import tech.ydb.topic.settings.UpdateOffsetsInTransactionSettings; 8 | 9 | /** 10 | * A helper class that is used to accumulate messages and add them to {@link YdbTransaction}. 11 | * Several {@link Message}s or/and {@link tech.ydb.topic.read.events.DataReceivedEvent}s can be accepted to add to 12 | * {@link YdbTransaction} later all at once. 13 | * All messages should be read from the same Reader this accumulator was created on. 14 | * Contains no data references and therefore may also be useful in cases where messages are committed after processing 15 | * data in an external system. 16 | * 17 | * @author Nikolay Perfilov 18 | */ 19 | public interface TransactionMessageAccumulator extends MessageAccumulator { 20 | CompletableFuture updateOffsetsInTransaction(YdbTransaction transaction, 21 | UpdateOffsetsInTransactionSettings settings); 22 | } 23 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/read/events/AbstractReadEventHandler.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.read.events; 2 | 3 | /** 4 | * @author Nikolay Perfilov 5 | */ 6 | public abstract class AbstractReadEventHandler implements ReadEventHandler { 7 | } 8 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/read/events/CommitOffsetAcknowledgementEvent.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.read.events; 2 | 3 | import tech.ydb.topic.read.PartitionSession; 4 | 5 | /** 6 | * @author Nikolay Perfilov 7 | */ 8 | public interface CommitOffsetAcknowledgementEvent { 9 | PartitionSession getPartitionSession(); 10 | long getCommittedOffset(); 11 | } 12 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/read/events/DataReceivedEvent.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.read.events; 2 | 3 | import java.util.List; 4 | import java.util.concurrent.CompletableFuture; 5 | 6 | import tech.ydb.topic.read.Message; 7 | import tech.ydb.topic.read.PartitionOffsets; 8 | import tech.ydb.topic.read.PartitionSession; 9 | 10 | /** 11 | * @author Nikolay Perfilov 12 | */ 13 | public interface DataReceivedEvent { 14 | 15 | /** 16 | * Returns a list of messages grouped in one batch. 17 | * Each message can be committed individually or all messages can be committed at once with commit() method 18 | * 19 | * @return a list of messages 20 | */ 21 | List getMessages(); 22 | 23 | /** 24 | * Returns a partition session this data was received on 25 | * 26 | * @return a partition session this data was received on 27 | */ 28 | PartitionSession getPartitionSession(); 29 | 30 | /** 31 | * Returns partition offsets of this message 32 | * 33 | * @return Partition offsets of this message 34 | */ 35 | PartitionOffsets getPartitionOffsets(); 36 | 37 | /** 38 | * Commits all messages in this event at once. 39 | * If there was an error while committing, there is no point of retrying committing the same messages: 40 | * the whole PartitionSession should be shut down by that time. And if commit hadn't reached the server, 41 | * it will resend all these messages in next PartitionSession. 42 | * 43 | * @return a CompletableFuture that will be completed when commit confirmation from server will be received 44 | */ 45 | CompletableFuture commit(); 46 | 47 | } 48 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/read/events/PartitionSessionClosedEvent.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.read.events; 2 | 3 | import tech.ydb.topic.read.PartitionSession; 4 | 5 | /** 6 | * @author Nikolay Perfilov 7 | */ 8 | public interface PartitionSessionClosedEvent { 9 | 10 | PartitionSession getPartitionSession(); 11 | } 12 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/read/events/PartitionSessionStatusEvent.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.read.events; 2 | 3 | /** 4 | * @author Nikolay Perfilov 5 | */ 6 | public class PartitionSessionStatusEvent { 7 | } 8 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/read/events/ReadEventHandler.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.read.events; 2 | 3 | import tech.ydb.topic.read.impl.events.SessionStartedEvent; 4 | 5 | /** 6 | * @author Nikolay Perfilov 7 | */ 8 | @FunctionalInterface 9 | public interface ReadEventHandler { 10 | 11 | void onMessages(DataReceivedEvent event); 12 | 13 | default void onCommitResponse(CommitOffsetAcknowledgementEvent event) { } 14 | 15 | 16 | default void onStartPartitionSession(StartPartitionSessionEvent event) { 17 | event.confirm(); 18 | } 19 | 20 | default void onStopPartitionSession(StopPartitionSessionEvent event) { 21 | event.confirm(); 22 | } 23 | 24 | default void onPartitionSessionClosed(PartitionSessionClosedEvent event) { } 25 | 26 | default void onReaderClosed(ReaderClosedEvent event) { } 27 | 28 | default void onSessionStarted(SessionStartedEvent event) { } 29 | } 30 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/read/events/ReaderClosedEvent.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.read.events; 2 | 3 | /** 4 | * @author Nikolay Perfilov 5 | */ 6 | public class ReaderClosedEvent { 7 | } 8 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/read/events/StartPartitionSessionEvent.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.read.events; 2 | 3 | import tech.ydb.topic.description.OffsetsRange; 4 | import tech.ydb.topic.read.PartitionSession; 5 | import tech.ydb.topic.settings.StartPartitionSessionSettings; 6 | 7 | /** 8 | * @author Nikolay Perfilov 9 | */ 10 | public interface StartPartitionSessionEvent { 11 | 12 | PartitionSession getPartitionSession(); 13 | 14 | long getCommittedOffset(); 15 | 16 | OffsetsRange getPartitionOffsets(); 17 | 18 | void confirm(); 19 | 20 | void confirm(StartPartitionSessionSettings settings); 21 | } 22 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/read/events/StopPartitionSessionEvent.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.read.events; 2 | 3 | import tech.ydb.topic.read.PartitionSession; 4 | 5 | /** 6 | * @author Nikolay Perfilov 7 | */ 8 | public interface StopPartitionSessionEvent { 9 | PartitionSession getPartitionSession(); 10 | long getPartitionSessionId(); 11 | 12 | Long getPartitionId(); 13 | 14 | long getCommittedOffset(); 15 | 16 | void confirm(); 17 | } 18 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/read/impl/Batch.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.read.impl; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.concurrent.CompletableFuture; 6 | 7 | import tech.ydb.topic.description.Codec; 8 | 9 | /** 10 | * @author Nikolay Perfilov 11 | */ 12 | public class Batch { 13 | private final BatchMeta meta; 14 | private final List messages = new ArrayList<>(); 15 | // Completes when batch is read 16 | private final CompletableFuture readFuture = new CompletableFuture<>(); 17 | private boolean decompressed = false; 18 | 19 | public Batch(BatchMeta meta) { 20 | this.meta = meta; 21 | } 22 | 23 | public List getMessages() { 24 | return messages; 25 | } 26 | 27 | public void addMessage(MessageImpl message) { 28 | messages.add(message); 29 | } 30 | 31 | public void complete() { 32 | readFuture.complete(null); 33 | } 34 | 35 | public CompletableFuture getReadFuture() { 36 | return readFuture; 37 | } 38 | 39 | public Codec getCodec() { 40 | return meta.getCodec(); 41 | } 42 | 43 | public boolean isDecompressed() { 44 | return decompressed; 45 | } 46 | 47 | public void setDecompressed(boolean decompressed) { 48 | this.decompressed = decompressed; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/read/impl/BatchMeta.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.read.impl; 2 | 3 | import java.time.Instant; 4 | import java.util.Map; 5 | 6 | import tech.ydb.core.utils.ProtobufUtils; 7 | import tech.ydb.proto.topic.YdbTopic; 8 | import tech.ydb.topic.description.Codec; 9 | 10 | /** 11 | * @author Nikolay Perfilov 12 | */ 13 | public class BatchMeta { 14 | private final String producerId; 15 | private final Map writeSessionMeta; 16 | private final Codec codec; 17 | private final Instant writtenAt; 18 | 19 | public BatchMeta(YdbTopic.StreamReadMessage.ReadResponse.Batch batch) { 20 | this.producerId = batch.getProducerId(); 21 | this.writeSessionMeta = batch.getWriteSessionMetaMap(); 22 | this.codec = tech.ydb.topic.utils.ProtoUtils.codecFromProto(batch.getCodec()); 23 | this.writtenAt = ProtobufUtils.protoToInstant(batch.getWrittenAt()); 24 | } 25 | 26 | public String getProducerId() { 27 | return producerId; 28 | } 29 | 30 | public Map getWriteSessionMeta() { 31 | return writeSessionMeta; 32 | } 33 | 34 | public Codec getCodec() { 35 | return codec; 36 | } 37 | 38 | public Instant getWrittenAt() { 39 | return writtenAt; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/read/impl/CommitterImpl.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.read.impl; 2 | 3 | import java.util.concurrent.CompletableFuture; 4 | 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import tech.ydb.topic.description.OffsetsRange; 9 | 10 | /** 11 | * @author Nikolay Perfilov 12 | */ 13 | public class CommitterImpl { 14 | private static final Logger logger = LoggerFactory.getLogger(CommitterImpl.class); 15 | private final PartitionSessionImpl partitionSession; 16 | private final int messageCount; 17 | private final OffsetsRange offsetsToCommit; 18 | 19 | public CommitterImpl(PartitionSessionImpl partitionSession, int messageCount, OffsetsRange offsetsToCommit) { 20 | this.partitionSession = partitionSession; 21 | this.messageCount = messageCount; 22 | this.offsetsToCommit = offsetsToCommit; 23 | } 24 | 25 | 26 | public CompletableFuture commit() { 27 | return commitImpl(true); 28 | } 29 | 30 | public CompletableFuture commitImpl(boolean fromCommitter) { 31 | if (logger.isDebugEnabled()) { 32 | logger.debug( 33 | "[{}] Committing {} message(s), offsets [{},{}){}", 34 | partitionSession.getFullId(), 35 | messageCount, 36 | offsetsToCommit.getStart(), 37 | offsetsToCommit.getEnd(), 38 | fromCommitter ? " from Committer" : "" 39 | ); 40 | } 41 | return partitionSession.commitOffsetRange(offsetsToCommit); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/read/impl/OffsetsRangeImpl.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.read.impl; 2 | 3 | import java.util.Objects; 4 | 5 | import tech.ydb.topic.description.OffsetsRange; 6 | 7 | /** 8 | * @author Nikolay Perfilov 9 | */ 10 | public class OffsetsRangeImpl implements OffsetsRange { 11 | private long start; 12 | private long end; 13 | 14 | public OffsetsRangeImpl(long start, long end) { 15 | this.start = start; 16 | this.end = end; 17 | } 18 | 19 | public OffsetsRangeImpl(OffsetsRange offsetsRange) { 20 | this.start = offsetsRange.getStart(); 21 | this.end = offsetsRange.getEnd(); 22 | } 23 | 24 | @Override 25 | public long getStart() { 26 | return start; 27 | } 28 | 29 | @Override 30 | public long getEnd() { 31 | return end; 32 | } 33 | 34 | public void setStart(long start) { 35 | this.start = start; 36 | } 37 | 38 | public void setEnd(long end) { 39 | this.end = end; 40 | } 41 | 42 | @Override 43 | public boolean equals(Object o) { 44 | if (this == o) { 45 | return true; 46 | } 47 | if (o == null || getClass() != o.getClass()) { 48 | return false; 49 | } 50 | OffsetsRangeImpl that = (OffsetsRangeImpl) o; 51 | return start == that.start && end == that.end; 52 | } 53 | 54 | @Override 55 | public int hashCode() { 56 | return Objects.hash(start, end); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/read/impl/ReadSession.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.read.impl; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import tech.ydb.proto.topic.YdbTopic; 7 | import tech.ydb.proto.topic.YdbTopic.StreamReadMessage.FromClient; 8 | import tech.ydb.proto.topic.YdbTopic.StreamReadMessage.FromServer; 9 | import tech.ydb.topic.TopicRpc; 10 | import tech.ydb.topic.impl.SessionBase; 11 | 12 | /** 13 | * @author Nikolay Perfilov 14 | */ 15 | public abstract class ReadSession extends SessionBase { 16 | private static final Logger logger = LoggerFactory.getLogger(ReadSession.class); 17 | 18 | protected final String streamId; 19 | 20 | public ReadSession(TopicRpc rpc, String streamId) { 21 | super(rpc.readSession(streamId)); 22 | this.streamId = streamId; 23 | } 24 | 25 | @Override 26 | protected Logger getLogger() { 27 | return logger; 28 | } 29 | 30 | @Override 31 | protected void sendUpdateTokenRequest(String token) { 32 | streamConnection.sendNext(YdbTopic.StreamReadMessage.FromClient.newBuilder() 33 | .setUpdateTokenRequest(YdbTopic.UpdateTokenRequest.newBuilder() 34 | .setToken(token) 35 | .build()) 36 | .build() 37 | ); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/read/impl/events/CommitOffsetAcknowledgementEventImpl.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.read.impl.events; 2 | 3 | import tech.ydb.topic.read.PartitionSession; 4 | import tech.ydb.topic.read.events.CommitOffsetAcknowledgementEvent; 5 | 6 | public class CommitOffsetAcknowledgementEventImpl implements CommitOffsetAcknowledgementEvent { 7 | private final PartitionSession partitionSession; 8 | private final long committedOffset; 9 | 10 | public CommitOffsetAcknowledgementEventImpl(PartitionSession partitionSession, long committedOffset) { 11 | this.partitionSession = partitionSession; 12 | this.committedOffset = committedOffset; 13 | } 14 | 15 | @Override 16 | public PartitionSession getPartitionSession() { 17 | return partitionSession; 18 | } 19 | 20 | @Override 21 | public long getCommittedOffset() { 22 | return committedOffset; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/read/impl/events/PartitionSessionClosedEventImpl.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.read.impl.events; 2 | 3 | import tech.ydb.topic.read.PartitionSession; 4 | import tech.ydb.topic.read.events.PartitionSessionClosedEvent; 5 | 6 | /** 7 | * @author Nikolay Perfilov 8 | */ 9 | public class PartitionSessionClosedEventImpl implements PartitionSessionClosedEvent { 10 | private final PartitionSession partitionSession; 11 | 12 | public PartitionSessionClosedEventImpl(PartitionSession partitionSession) { 13 | this.partitionSession = partitionSession; 14 | } 15 | 16 | @Override 17 | public PartitionSession getPartitionSession() { 18 | return partitionSession; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/read/impl/events/SessionStartedEvent.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.read.impl.events; 2 | 3 | /** 4 | * 5 | * @author Aleksandr Gorshenin 6 | */ 7 | public class SessionStartedEvent { 8 | private final String sessionId; 9 | 10 | public SessionStartedEvent(String sessionId) { 11 | this.sessionId = sessionId; 12 | } 13 | 14 | public String getSessionId() { 15 | return this.sessionId; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/read/impl/events/StopPartitionSessionEventImpl.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.read.impl.events; 2 | 3 | import tech.ydb.topic.read.PartitionSession; 4 | import tech.ydb.topic.read.events.StopPartitionSessionEvent; 5 | 6 | /** 7 | * @author Nikolay Perfilov 8 | */ 9 | public class StopPartitionSessionEventImpl implements StopPartitionSessionEvent { 10 | private final PartitionSession partitionSession; 11 | private final long committedOffset; 12 | private final Runnable confirmCallback; 13 | 14 | public StopPartitionSessionEventImpl(PartitionSession partitionSession, long committedOffset, 15 | Runnable confirmCallback) { 16 | this.partitionSession = partitionSession; 17 | this.committedOffset = committedOffset; 18 | this.confirmCallback = confirmCallback; 19 | } 20 | 21 | @Override 22 | public PartitionSession getPartitionSession() { 23 | return partitionSession; 24 | } 25 | 26 | @Override 27 | public long getPartitionSessionId() { 28 | return partitionSession.getId(); 29 | } 30 | 31 | @Override 32 | public long getCommittedOffset() { 33 | return committedOffset; 34 | } 35 | 36 | @Override 37 | public Long getPartitionId() { 38 | return partitionSession.getPartitionId(); 39 | } 40 | 41 | @Override 42 | public void confirm() { 43 | confirmCallback.run(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/settings/AutoPartitioningStrategy.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.settings; 2 | 3 | public enum AutoPartitioningStrategy { 4 | /** 5 | * The auto partitioning is disabled. 6 | * You cannot disable the auto partitioning after it has been enabled. 7 | * @see AutoPartitioningStrategy#PAUSED 8 | */ 9 | DISABLED, 10 | /** 11 | * The auto partitioning algorithm will increase the partition count depending on the load characteristics. 12 | * The auto partitioning algorithm will never decrease the number of partitions. 13 | * @see AlterAutoPartitioningWriteStrategySettings 14 | */ 15 | SCALE_UP, 16 | /** 17 | * The auto partitioning algorithm will both increase and decrease partitions count depending on the load characteristics. 18 | * @see AlterAutoPartitioningWriteStrategySettings 19 | */ 20 | SCALE_UP_AND_DOWN, 21 | /** 22 | * The auto partitioning is paused. 23 | */ 24 | PAUSED; 25 | } 26 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/settings/DescribeConsumerSettings.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.settings; 2 | 3 | import tech.ydb.core.settings.OperationSettings; 4 | 5 | /** 6 | * 7 | * @author Aleksandr Gorshenin 8 | */ 9 | public class DescribeConsumerSettings extends OperationSettings { 10 | private final boolean includeStats; 11 | private final boolean includeLocation; 12 | 13 | public DescribeConsumerSettings(Builder builder) { 14 | super(builder); 15 | this.includeStats = builder.includeStats; 16 | this.includeLocation = builder.includeLocation; 17 | } 18 | 19 | public boolean isIncludeStats() { 20 | return includeStats; 21 | } 22 | 23 | public boolean isIncludeLocation() { 24 | return includeLocation; 25 | } 26 | 27 | public static Builder newBuilder() { 28 | return new Builder(); 29 | } 30 | 31 | public static class Builder extends OperationBuilder { 32 | private boolean includeStats = false; 33 | private boolean includeLocation = false; 34 | 35 | public Builder withIncludeStats(boolean value) { 36 | this.includeStats = value; 37 | return this; 38 | } 39 | 40 | public Builder withIncludeLocation(boolean value) { 41 | this.includeLocation = value; 42 | return this; 43 | } 44 | 45 | @Override 46 | public DescribeConsumerSettings build() { 47 | return new DescribeConsumerSettings(this); 48 | } 49 | } 50 | } 51 | 52 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/settings/DescribeTopicSettings.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.settings; 2 | 3 | import tech.ydb.core.settings.OperationSettings; 4 | 5 | /** 6 | * @author Nikolay Perfilov 7 | */ 8 | public class DescribeTopicSettings extends OperationSettings { 9 | /* TODO: renew api and add stats 10 | private boolean includeStats = false; 11 | 12 | public DescribeTopicSettings(boolean includeStats) { 13 | this.includeStats = includeStats; 14 | } 15 | 16 | public void setIncludeStats(boolean includeStats) { 17 | this.includeStats = includeStats; 18 | } 19 | 20 | public boolean getIncludeStats() { 21 | return includeStats; 22 | }*/ 23 | 24 | private DescribeTopicSettings(Builder builder) { 25 | super(builder); 26 | } 27 | 28 | public static Builder newBuilder() { 29 | return new Builder(); 30 | } 31 | 32 | public static class Builder extends OperationBuilder { 33 | @Override 34 | public DescribeTopicSettings build() { 35 | return new DescribeTopicSettings(this); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/settings/DropTopicSettings.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.settings; 2 | 3 | import tech.ydb.core.settings.OperationSettings; 4 | 5 | /** 6 | * @author Nikolay Perfilov 7 | */ 8 | public class DropTopicSettings extends OperationSettings { 9 | private DropTopicSettings(Builder builder) { 10 | super(builder); 11 | } 12 | 13 | public static Builder newBuilder() { 14 | return new Builder(); 15 | } 16 | 17 | public static class Builder extends OperationBuilder { 18 | @Override 19 | public DropTopicSettings build() { 20 | return new DropTopicSettings(this); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/settings/ReadEventHandlersSettings.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.settings; 2 | 3 | import java.util.concurrent.Executor; 4 | 5 | import tech.ydb.topic.read.events.ReadEventHandler; 6 | 7 | /** 8 | * @author Nikolay Perfilov 9 | */ 10 | public class ReadEventHandlersSettings { 11 | private final Executor executor; 12 | private final ReadEventHandler eventHandler; 13 | 14 | private ReadEventHandlersSettings(Builder builder) { 15 | this.executor = builder.executor; 16 | this.eventHandler = builder.eventHandler; 17 | } 18 | 19 | public Executor getExecutor() { 20 | return executor; 21 | } 22 | 23 | public ReadEventHandler getEventHandler() { 24 | return eventHandler; 25 | } 26 | 27 | public static Builder newBuilder() { 28 | return new Builder(); 29 | } 30 | 31 | /** 32 | * BUILDER 33 | */ 34 | public static class Builder { 35 | private Executor executor; 36 | private ReadEventHandler eventHandler; 37 | 38 | public Builder setExecutor(Executor executor) { 39 | this.executor = executor; 40 | return this; 41 | } 42 | 43 | public Builder setEventHandler(ReadEventHandler eventHandler) { 44 | this.eventHandler = eventHandler; 45 | return this; 46 | } 47 | 48 | public ReadEventHandlersSettings build() { 49 | return new ReadEventHandlersSettings(this); 50 | } 51 | 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/settings/UpdateOffsetsInTransactionSettings.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.settings; 2 | 3 | import tech.ydb.core.settings.OperationSettings; 4 | 5 | /** 6 | * @author Nikolay Perfilov 7 | */ 8 | public class UpdateOffsetsInTransactionSettings extends OperationSettings { 9 | private UpdateOffsetsInTransactionSettings(Builder builder) { 10 | super(builder); 11 | } 12 | 13 | public static Builder newBuilder() { 14 | return new Builder(); 15 | } 16 | 17 | public static class Builder extends OperationBuilder { 18 | @Override 19 | public UpdateOffsetsInTransactionSettings build() { 20 | return new UpdateOffsetsInTransactionSettings(this); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/utils/ProtoUtils.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.utils; 2 | 3 | import tech.ydb.proto.topic.YdbTopic; 4 | import tech.ydb.topic.description.Codec; 5 | 6 | /** 7 | * @author Nikolay Perfilov 8 | */ 9 | public class ProtoUtils { 10 | 11 | private ProtoUtils() { } 12 | 13 | public static int toProto(Codec codec) { 14 | switch (codec) { 15 | case RAW: 16 | return YdbTopic.Codec.CODEC_RAW_VALUE; 17 | case GZIP: 18 | return YdbTopic.Codec.CODEC_GZIP_VALUE; 19 | case LZOP: 20 | return YdbTopic.Codec.CODEC_LZOP_VALUE; 21 | case ZSTD: 22 | return YdbTopic.Codec.CODEC_ZSTD_VALUE; 23 | case CUSTOM: 24 | return YdbTopic.Codec.CODEC_CUSTOM_VALUE; 25 | default: 26 | throw new RuntimeException("Cannot convert codec to proto. Unknown codec value: " + codec); 27 | } 28 | } 29 | 30 | public static Codec codecFromProto(int codec) { 31 | switch (codec) { 32 | case YdbTopic.Codec.CODEC_RAW_VALUE: 33 | return Codec.RAW; 34 | case YdbTopic.Codec.CODEC_GZIP_VALUE: 35 | return Codec.GZIP; 36 | case YdbTopic.Codec.CODEC_LZOP_VALUE: 37 | return Codec.LZOP; 38 | case YdbTopic.Codec.CODEC_ZSTD_VALUE: 39 | return Codec.ZSTD; 40 | case YdbTopic.Codec.CODEC_CUSTOM_VALUE: 41 | return Codec.CUSTOM; 42 | default: 43 | throw new RuntimeException("Unknown codec value from proto: " + codec); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/write/AsyncWriter.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.write; 2 | 3 | import java.util.concurrent.CompletableFuture; 4 | 5 | import tech.ydb.topic.settings.SendSettings; 6 | 7 | /** 8 | * @author Nikolay Perfilov 9 | */ 10 | public interface AsyncWriter { 11 | 12 | /** 13 | * Initialize internal threads in the background. Non-blocking 14 | * @return {@link CompletableFuture} with {@link InitResult} containing initialization data like lastSeqNo 15 | */ 16 | CompletableFuture init(); 17 | 18 | /** 19 | * Send message. Non-blocking 20 | * @param message message data to write 21 | * @return {@link CompletableFuture} with {@link WriteAck} for write acknowledgement 22 | */ 23 | CompletableFuture send(Message message) throws QueueOverflowException; 24 | 25 | /** 26 | * Send message. Non-blocking 27 | * @param message message data to write 28 | * @param settings send settings 29 | * @return {@link CompletableFuture} with {@link WriteAck} for write acknowledgement 30 | */ 31 | CompletableFuture send(Message message, SendSettings settings) throws QueueOverflowException; 32 | 33 | /** 34 | * Stops internal threads and makes cleanup in background. Non-blocking 35 | */ 36 | CompletableFuture shutdown(); 37 | } 38 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/write/InitResult.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.write; 2 | 3 | /** 4 | * @author Nikolay Perfilov 5 | */ 6 | public class InitResult { 7 | private final long seqNo; 8 | 9 | public InitResult(long seqNo) { 10 | this.seqNo = seqNo; 11 | } 12 | 13 | public long getSeqNo() { 14 | return seqNo; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/write/QueueOverflowException.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.write; 2 | 3 | /** 4 | * @author Nikolay Perfilov 5 | */ 6 | public class QueueOverflowException extends Exception { 7 | private static final long serialVersionUID = 2807265315663088217L; 8 | 9 | public QueueOverflowException(String errorMessage) { 10 | super(errorMessage); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/write/WriteAck.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.write; 2 | 3 | /** 4 | * @author Nikolay Perfilov 5 | */ 6 | public class WriteAck { 7 | private final long seqNo; 8 | private final State state; 9 | private final Details details; 10 | 11 | public WriteAck(long seqNo, State state, Details details) { 12 | this.seqNo = seqNo; 13 | this.state = state; 14 | this.details = details; 15 | } 16 | 17 | public enum State { 18 | WRITTEN, 19 | ALREADY_WRITTEN, 20 | WRITTEN_IN_TX 21 | } 22 | 23 | public static class Details { 24 | private final long offset; 25 | 26 | public Details(long offset) { 27 | this.offset = offset; 28 | } 29 | 30 | public long getOffset() { 31 | return offset; 32 | } 33 | } 34 | 35 | public long getSeqNo() { 36 | return seqNo; 37 | } 38 | 39 | public State getState() { 40 | return state; 41 | } 42 | 43 | /** 44 | * Get details about written offsets 45 | * @return {@link Details} with written offsets if state is {@link State#WRITTEN} or null otherwise 46 | */ 47 | public Details getDetails() { 48 | return details; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/write/impl/AsyncWriterImpl.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.write.impl; 2 | 3 | import java.util.concurrent.CompletableFuture; 4 | import java.util.concurrent.CompletionException; 5 | import java.util.concurrent.Executor; 6 | 7 | import tech.ydb.topic.TopicRpc; 8 | import tech.ydb.topic.settings.SendSettings; 9 | import tech.ydb.topic.settings.WriterSettings; 10 | import tech.ydb.topic.write.AsyncWriter; 11 | import tech.ydb.topic.write.InitResult; 12 | import tech.ydb.topic.write.Message; 13 | import tech.ydb.topic.write.QueueOverflowException; 14 | import tech.ydb.topic.write.WriteAck; 15 | 16 | /** 17 | * @author Nikolay Perfilov 18 | */ 19 | public class AsyncWriterImpl extends WriterImpl implements AsyncWriter { 20 | 21 | public AsyncWriterImpl(TopicRpc topicRpc, WriterSettings settings, Executor compressionExecutor) { 22 | super(topicRpc, settings, compressionExecutor); 23 | } 24 | 25 | @Override 26 | public CompletableFuture init() { 27 | return initImpl(); 28 | } 29 | 30 | @Override 31 | public CompletableFuture send(Message message, SendSettings settings) throws QueueOverflowException { 32 | try { 33 | return sendImpl(message, settings, true).join(); 34 | } catch (CompletionException e) { 35 | if (e.getCause() instanceof QueueOverflowException) { 36 | throw (QueueOverflowException) e.getCause(); 37 | } else { 38 | throw new RuntimeException(e); 39 | } 40 | } 41 | } 42 | 43 | @Override 44 | public CompletableFuture send(Message message) throws QueueOverflowException { 45 | return send(message, null); 46 | } 47 | 48 | @Override 49 | public CompletableFuture shutdown() { 50 | return shutdownImpl(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /topic/src/main/java/tech/ydb/topic/write/impl/WriteSession.java: -------------------------------------------------------------------------------- 1 | package tech.ydb.topic.write.impl; 2 | import org.slf4j.Logger; 3 | import org.slf4j.LoggerFactory; 4 | 5 | import tech.ydb.proto.topic.YdbTopic; 6 | import tech.ydb.proto.topic.YdbTopic.StreamWriteMessage.FromClient; 7 | import tech.ydb.proto.topic.YdbTopic.StreamWriteMessage.FromServer; 8 | import tech.ydb.topic.TopicRpc; 9 | import tech.ydb.topic.impl.SessionBase; 10 | 11 | /** 12 | * @author Nikolay Perfilov 13 | */ 14 | public abstract class WriteSession extends SessionBase { 15 | private static final Logger logger = LoggerFactory.getLogger(WriteSession.class); 16 | 17 | protected final String streamId; 18 | 19 | public WriteSession(TopicRpc rpc, String streamId) { 20 | super(rpc.writeSession(streamId)); 21 | this.streamId = streamId; 22 | } 23 | 24 | @Override 25 | protected Logger getLogger() { 26 | return logger; 27 | } 28 | 29 | @Override 30 | protected void sendUpdateTokenRequest(String token) { 31 | streamConnection.sendNext(YdbTopic.StreamWriteMessage.FromClient.newBuilder() 32 | .setUpdateTokenRequest(YdbTopic.UpdateTokenRequest.newBuilder() 33 | .setToken(token) 34 | .build()) 35 | .build() 36 | ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /topic/src/test/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | --------------------------------------------------------------------------------