Giter Site home page Giter Site logo

ydb-nodejs-sdk's Introduction

Roadmap

You can take a look at our Roadmap for the near future here.

How to use

Install package from NPM

npm install ydb-sdk

Install dependencies and compile library

npm ci
npm run build

Set environment variables

Variables which should not be set for a specific installation are explicitly set to an empty value, so that startup script correctly detects which installation you are aiming at.

Common variables

export YDB_SDK_LOGLEVEL=debug
export IAM_ENDPOINT= # for Yandex.Cloud, by default it is iam.api.cloud.yandex.net:443

Credential variables

For the typical cases of using these variables, see below:

export YDB_ACCESS_TOKEN_CREDENTIALS= # here comes your token from `yc iam create-token`

export YDB_ANONYMOUS_CREDENTIALS=1 # try anonymous access

export YDB_METADATA_CREDENTIALS=1 #  try local metadata service authentication

export YDB_SERVICE_ACCOUNT_KEY_FILE_CREDENTIALS = # here should be the path to the service account key file from 'yc iam key create --folder-id <folder_id> --service-account-name <sa_name> --output ~/.ydb/sa_name.json'

Access to internal YDB cluster

export YDB_ACCESS_TOKEN_CREDENTIALS= # here comes your oauth token

Access to Yandex.Cloud YDB cluster from local machine

Serverless DB

export YDB_ACCESS_TOKEN_CREDENTIALS= # here comes your token from `yc iam create-token`

Dedicated DB

export YDB_ACCESS_TOKEN_CREDENTIALS= # here comes your token from `yc iam create-token`
export YDB_SSL_ROOT_CERTIFICATES_FILE= # here should be the path to ssl root certificate for YDB installation

Access to Yandex.Cloud YDB cluster from virtual machine

export YDB_SERVICE_ACCOUNT_KEY_FILE_CREDENTIALS= # here should be the path to the service account key file from 'yc iam key create --folder-id <folder_id> --service-account-name <sa_name> --output ~/.ydb/sa_name.json'

Run basic-example script

cd examples
npm ci
npm run build
npm run basic-v1 -- --connection-string grpcs://your.cloud.endpoint.hostname?database=your-cloud-db-name

ydb-nodejs-sdk's People

Contributors

alexv-smirnov avatar davyjohnes avatar dependabot[bot] avatar doochik avatar esseswann avatar gayratvg avatar impressionableraccoon avatar mcheshkov avatar mihanixa avatar murka avatar rrewll avatar solovboy avatar tsufiev avatar valeras avatar yandex-cloud-bot avatar ydb-platform-bot avatar ydbdev avatar zeruk avatar zork33 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ydb-nodejs-sdk's Issues

bulkUpsert не реализован

Если я правильно понял - то bulkUpsert должен быть в объекте Session (по аналогии с executeQuery)
Просьба добавить bulkUpsert в Session

Если я неправильно понял - то напишите пожалуйста способ вызова bulkUpsert

feat: Add topics support

Feature Request

Describe the Feature Request

Add topics support

docs: https://ydb.tech/en/docs/concepts/topic

Describe Preferred Solution

Describe Alternatives

Related Code

Additional Context

If the feature request is approved, would you be willing to submit a PR?
Yes / No (Help can be provided if you need assistance submitting a PR)

Yandex Database права на директорию

В Yandex Database NodeJS SDk в примере есть непонятный для меня фрагмент по назначению прав:

https://github.com/ydb-platform/ydb-nodejs-sdk/blob/master/examples/scheme-client/index.ts#L20

await driver.schemeClient.modifyPermissions(
        'example-path/subpath',
        [{
            grant: {
                subject: 'tsufiev@staff',
                permissionNames: ['read', 'use']
            }
        }]
    );

В документации по поводу управления доступом нашел только раздел: Управление доступом в Yandex Database

https://cloud.yandex.ru/docs/ydb/security/start_auth

но там речь ведется про пользователей Yandex облака.

Расскажите пожалуйста - в вышеприведенном примере кому даются права и на что они влияют ?

TS2507: Type 'typeof EventEmitter' is not a constructor function type.

ydb-sdk/build/table.d.ts

Error:(43, 38) TS2507: Type 'typeof EventEmitter' is not a constructor function type.
Error:(66, 42) TS2507: Type 'typeof EventEmitter' is not a constructor function type.
Error:(87, 42) TS2507: Type 'typeof EventEmitter' is not a constructor function type.

Maybe you mean EventEmitter. EventEmitter?

Ошибка - инициализированный драйвер вылетает с ошибкой

Для воспроизведения ошибки надо запустить простой express сервер (запускался на VPS), проинициализировать Driver YDB (в моем случае с помощью SA_KEY_FILE), подождать несколько часов.
Код:

(async () => {
  await initDbLocal();
})();

app.get('/', (_req, res) => {  res.send(`Hello World! test app\n`);});

app.listen(port, () => {   console.log(`Example app listening on port ${port}`); });

Через несколько часов сервер падает с ошибкой.
Видно что сервер запустился, инициализировался, отработал обращение по curl, потом я его оставил на несколько часов и он упал.

{"level":30,"time":1659495396676,"pid":5519,"hostname":"cp2","msg":"Driver initializing..."}
Example app listening on port 3020
{"level":30,"time":1659495396847,"pid":5519,"hostname":"cp2","msg":"Done"}
/apptest
/apptest
/apptest
/var/www/makeupkitchen.ga/node/node_modules/@grpc/grpc-js/src/call.ts:81
  const error = new Error(message);
                ^
Error: 14 UNAVAILABLE: Stream refused by server
    at Object.callErrorFromStatus (/var/www/makeupkitchen.ga/node/node_modules/@grpc/grpc-js/src/call.ts:81:17)
    at Object.onReceiveStatus (/var/www/makeupkitchen.ga/node/node_modules/@grpc/grpc-js/src/client.ts:352:36)
    at Object.onReceiveStatus (/var/www/makeupkitchen.ga/node/node_modules/@grpc/grpc-js/src/client-interceptors.ts:462:34)
    at Object.onReceiveStatus (/var/www/makeupkitchen.ga/node/node_modules/@grpc/grpc-js/src/client-interceptors.ts:424:48)
    at /var/www/makeupkitchen.ga/node/node_modules/@grpc/grpc-js/src/call-stream.ts:330:24
    at processTicksAndRejections (node:internal/process/task_queues:78:11)
for call at
    at Client.makeUnaryRequest (/var/www/makeupkitchen.ga/node/node_modules/@grpc/grpc-js/src/client.ts:324:26)
    at IamTokenService.rpcImpl (/var/www/makeupkitchen.ga/node/node_modules/ydb-sdk/build/cjs/utils.js:71:20)
    at IamTokenService.rpcCall (/var/www/makeupkitchen.ga/node/node_modules/protobufjs/src/rpc/service.js:94:21)
    at executor (/var/www/makeupkitchen.ga/node/node_modules/@protobufjs/aspromise/index.js:44:16)
    at new Promise (<anonymous>)
    at Object.asPromise (/var/www/makeupkitchen.ga/node/node_modules/@protobufjs/aspromise/index.js:28:12)
    at IamTokenService.rpcCall (/var/www/makeupkitchen.ga/node/node_modules/protobufjs/src/rpc/service.js:86:21)
    at IamTokenService.Create (/var/www/makeupkitchen.ga/node/node_modules/ydb-sdk-proto/proto/bundle.js:92967:37)
    at IamAuthService.sendTokenRequest (/var/www/makeupkitchen.ga/node/node_modules/ydb-sdk/build/cjs/credentials.js:88:39)
    at IamAuthService.updateToken (/var/www/makeupkitchen.ga/node/node_modules/ydb-sdk/build/cjs/credentials.js:92:41) {  code: 14,
  details: 'Stream refused by server',
  metadata: Metadata { internalRepr: Map(0) {}, options: {} }
}

кодогенератор

Для работы с данными требуется писать существенные куски кода, описывающие типы таблиц.
Я имею в виду файлы data-helpers.ts

Просьба разработать кодогенератор, который читает готовую структуру таблиц имеющейся базы данных и геренрует файл data-helpers.ts по базе данных.

dev: TypeORM for ydb-nodejs-sdk

Make YDB support in TypeORM (https://typeorm.io).

Since the topic is large, the work is divided into stages

Legend:

    □ - need to be written and tested

    ± - in the code, but not tested yet

    🗸 - done and tested
  1. □ Add support for Generic Query Service, which will be used to retrieve data for TypeORM (#337).

  2. □ Implement a minimal set of methods to support functionality listed in the TypeORM Quick start (https://typeorm.io/#quick-start)
    Keep already existing code from https://github.com/ydb-platform/typeorm and test it.
    Interface methods required for the Quick start are collected by trace - for details see https://github.com/Zork33/typeorm/tree/planning-steps-for-implementation

  • #351
  • ± YdbDriver:buildTableName
  • ± YdbDriver:connect
  • ± YdbDriver:disconnect
  • ± YdbDriver:createGeneratedMap
  • □ YdbDriver:createParameter
  • ± YdbDriver:createQueryRunner
  • ± YdbDriver:createSchemaBuilder
  • ± YdbDriver:escape
  • ± YdbDriver:escapeQueryWithParameters
  • □ YdbDriver:findChangedColumns
  • □ YdbDriver:getColumnLength
  • □ YdbDriver:isReturningSqlSupported
  • □ YdbDriver:normalizeDefault
  • □ YdbDriver:normalizeIsUnique
  • ± YdbDriver:normalizeType
  • □ YdbDriver:obtainMasterConnection
  • ± YdbDriver:parseTableName
  • □ YdbDriver:prepareHydratedValue
  • □ YdbDriver:preparePersistentValue
  • ± YdbQueryRunner:commitTransaction
  • ± YdbQueryRunner:connect
  • □ YdbQueryRunner:getCurrentDatabase
  • □ YdbQueryRunner:getCurrentSchema
  • □ YdbQueryRunner:hasTable
  • ± YdbQueryRunner:rollbackTransaction
  • ± YdbQueryRunner:query
  • □ YdbQueryRunner:release
  • ± YdbQueryRunner:startTransaction
  1. □ Realize the generation of migrations scripts based on the existing Postgres example

  2. □ Make an example of seeding (initial filling of dictionaries) on the basis of migrations scripts.

  3. □ It is desirable that the model of types was as close as possible to postgres implementation, to facilitate the transition

6... Further implement the rest of YdbDriver and YdbQueryRunner methods. There are less than half of them in the initial list

Depends from:

feat: logger customization

В моём приложении есть логер - использую winston. Я бы хотел его передать в ydb-sdk, но не могу, так как там используется pino. Логи sdk могут быть полезны для отладки проблем.

Для winston я реализовал свой транспорт для передачи логов в Cloud Logging в Yandex Cloud. Я хотел реализовать интерфейс pino поверх winston, но он оказался чересчур сложным.

Можно ли сделать кастомный интерфейс, в котором будет необходимый минимум для логирования внутри ydb-sdk?

Ошибка при доступе к сертификату

Error: ENOENT: no such file or directory, open '\node_modules\ydb-sdk\build\certs\internal.pem'

Ошибка заключается в том, что в пакете данный файл лежит тут:
\node_modules\ydb-sdk\certs\internal.pem

для решения надо либо поправить
fixup.sh
и добавить в него копирование директории certs

либо поправить файл
src/ssl-credentials.ts
указав в нем правильный путь

[Question] How to connect to database using serverless/cloud function.

Hi, I read all documentation that I found, but still can't connect to ydb. I use serverless to deploy the stack.

I use following code to connect:

      const driver = new Driver({
          endpoint: "grpcs://ydb.serverless.yandexcloud.net:2135",
          database: "/ru-central1/b1g5f2a3d9hru8cnrec5/etnsmorj75fl505b6t4g",
          authService: new MetadataAuthService(),
      });

      const ready = await driver.ready(5);

      return {
          statusCode: 200,
          headers: {
              'Content-Type': 'text/plain',
          },
          body: "ready: " + ready,
      }

However when I try to execute the handler, I have following error:

No certificate found
It seems that you are using grpcs (secure) endpoint in a bundled environment.
Either provide YDB_SSL_ROOT_CERTIFICATES_FILE environment variable
or copy contents of ydb-nodejs-sdk/certs to ./certs path relative to the bundled file

This message looks really weird for me. Because:

  1. The npm package is called 'ydb-sdk' not a 'ydb-nodejs-sdk'
  2. There is no such folder 'ydb-sdk/certs'
  3. I found the 'certs' folder in this repository, but next 'copy contents of ydb-nodejs-sdk/certs to ./certs path relative to the bundled file'. How I can do it with serverless? I think it's not trivial.
  4. Anyway why I need to deal with certs if I build a cloud solution? I have aws background, so if I have a role to access the database then I can access it without auth, that is.

For accessing database my cloud function have '-editor' role, but no luck. Can you help me?

P. S. The examples I found looks outdated, and not well structured.

Missing JSON_DOCUMENT type

Proto file does not contain JSON_DOCUMENT that should have value 4612:

        enum PrimitiveTypeId {
            PRIMITIVE_TYPE_ID_UNSPECIFIED = 0,
            BOOL = 6,
            INT8 = 7,
            UINT8 = 5,
            INT16 = 8,
            UINT16 = 9,
            INT32 = 1,
            UINT32 = 2,
            INT64 = 3,
            UINT64 = 4,
            FLOAT = 33,
            DOUBLE = 32,
            DATE = 48,
            DATETIME = 49,
            TIMESTAMP = 50,
            INTERVAL = 51,
            TZ_DATE = 52,
            TZ_DATETIME = 53,
            TZ_TIMESTAMP = 54,
            STRING = 4097,
            UTF8 = 4608,
            YSON = 4609,
            JSON = 4610,
            UUID = 4611
        }

JSON_DOCUMENT exists in other sdk (for example in go sdk)

Ошибка при работе с grpc укладывает приложение

Иногда приложение просто падает с такой ошибкой:

/usr/src/app/node_modules/@grpc/grpc-js/build/src/call.js:31
    return Object.assign(new Error(message), status);
                         ^

Error: 14 UNAVAILABLE: Connection dropped
    at Object.callErrorFromStatus (/usr/src/app/node_modules/@grpc/grpc-js/build/src/call.js:31:26)
    at Object.onReceiveStatus (/usr/src/app/node_modules/@grpc/grpc-js/build/src/client.js:189:52)
    at Object.onReceiveStatus (/usr/src/app/node_modules/@grpc/grpc-js/build/src/client-interceptors.js:365:141)
    at Object.onReceiveStatus (/usr/src/app/node_modules/@grpc/grpc-js/build/src/client-interceptors.js:328:181)
    at /usr/src/app/node_modules/@grpc/grpc-js/build/src/call-stream.js:187:78
    at processTicksAndRejections (node:internal/process/task_queues:78:11) {
  code: 14,
  details: 'Connection dropped',
  metadata: Metadata { internalRepr: Map(0) {}, options: {} }
}

Где ловить непонятно. GRPC используется только в ydb sdk.

How to get Date from YDB

запустил session.executeQuery на таблицу в которой одна из колонок имеет тип Date

в результате получил columns в котором указан тип 48 (Date)
и rows в котором для соответсвующей колонки написано :

{
"uint32Value": 17596
}

В types.ts есть специальная функция objectFromValue (она без export) которая конвертирует такое поле в date
https://github.com/ydb-platform/ydb-nodejs-sdk/blob/main/src/types.ts#L436

также нашел функцию:
function convertYdbValueToNative(

Скажите пожалуйста что надо сделать чтобы получить нативный date из базы ?
Видимо после executeQuery надо на результат вызвать какую то функцию ?

streamReadTable и createNativeObjects на только что созданной таблице

Чтение из только что созданной таблицы с созданием объектов с помощью createNativeObjects падает с ошибкой TypeError: Cannot destructure property 'rows' of 'resultSet' as it is undefined.

Минимальный воспроизводимый пример:

public runSession<T>(callback: (session: Session) => Promise<T>, timeout?: number) {
    return this.driver.tableClient.withSession(callback, timeout);
}

await this.ydb.runSession(async s => {
    await s.createTable(`main/test`,
        new TableDescription()
            .withColumns(
                new Column("name", Types.optional(Types.STRING))
            ).withPrimaryKeys("name")
     )
            
    let set: Ydb.IResultSet;
    await s.streamReadTable(`main/test`, res => {set = res.resultSet})
    console.log(set) //undefined
    return User.createNativeObjects(set) as User[]
})

Временная починка: добавить ?? {} после set при вызове createNativeObjects

return User.createNativeObjects(set ?? {}) as User[]

И тогда функция вернёт ожидаемый пустой список.

Возможно стоит возвращать внутри callback у streamReadTable пустой объект или добавить проверку на такое в самом createNativeObjects https://github.com/ydb-platform/ydb-nodejs-sdk/blob/main/src/types.ts#L655

feat: Add static credentials authentication mechanism

Feature Request

Describe the Feature Request

Add static credentials authentication mechanism

Describe Preferred Solution

Describe Alternatives

Related Code

Additional Context

If the feature request is approved, would you be willing to submit a PR?
Yes / No (Help can be provided if you need assistance submitting a PR)

Сломана работа с типом Decimal

Пример запроса:

SELECT CAST('1.1' as Decimal(22,9)) as val;

Падает с

Error: Got empty typeId, type is {"optionalType":{"item":{"decimalType":{"precision":22,"scale":9}}}}, value is {"low_128":"1100000000"}

При попытке вставить какое-нибудь decimal значение получаю следующую ошибку от SDK.

RangeError: The number 1.429 cannot be converted to a BigInt because it is not an integer

feat: export more error types

Feature Request

Describe the Feature Request

Describe Preferred Solution

Describe Alternatives

Related Code

Additional Context

If the feature request is approved, would you be willing to submit a PR?
Yes / No (Help can be provided if you need assistance submitting a PR)

withRetries - что означают параметры для RetryParameters

При вызове withRetries в нее вторым параметром передаются параметры для создания стратегии повтрения.

Среди этих параметров есть параметры backoffCeiling и backoffSlotDuration

Объясните пожалуйста - что они означают ?

withSession и withRetries вопрос

Для получения сессии есть два метода:

withSession и
withSessionRetry

единственное отличие этих методов - это параметр maxRetries, который присутствует во втором методе.
При наличии параметра maxRetries служебный метод _withSession пробует исполнить запрос еще раз не более maxRetries раз с другой сессией.

В примерах Тимур использует withSession и оборачивает исполненение запроса в функцию withRetries которая по умолчанию устанавливает maxRetries=10 и далее вызывается метод retry класса RetryStrategy

Скажите пожалуйста в чем отличие работы withSessionRetry с установленыым параметром maxRetries =10 от работы RetryStrategy.retry ?

Timur Sufiev, [17.11.2021 14:49]
[В ответ на Гайрат Власов]
в том, что RetryStrategy.retry делает ретраи на errors.Unavailable, errors.Aborted, errors.NotFound и errors.Overloaded (для последней бэкоффы больше), а withSession делает ретраи только на 2 ошибки: BadSession и SessionBusy - и без бэкоффов б) RetryStrategy.retry не пересоздает сессию в случае ошибок

Timur Sufiev, [17.11.2021 14:50]
декоратором @retryable, вызывающим RetryStragegy.retry, обёрнуты многие методы базовых классов работы с таблицами, в то время как withSession предполагает более высокий уровень - на куски кода, которые, если пофейлятся, должны быть перевыполнены заново в рамках новой сессии

Timur Sufiev, [17.11.2021 14:49]
[В ответ на Гайрат Власов]
в том, что RetryStrategy.retry делает ретраи на errors.Unavailable, errors.Aborted, errors.NotFound и errors.Overloaded (для последней бэкоффы больше), а withSession делает ретраи только на 2 ошибки: BadSession и SessionBusy - и без бэкоффов б) RetryStrategy.retry не пересоздает сессию в случае ошибок

Timur Sufiev, [17.11.2021 14:50]
декоратором @retryable, вызывающим RetryStragegy.retry, обёрнуты многие методы базовых классов работы с таблицами, в то время как withSession предполагает более высокий уровень - на куски кода, которые, если пофейлятся, должны быть перевыполнены заново в рамках новой сессии

Гайрат Власов, [17.11.2021 15:04]
[В ответ на Timur Sufiev]

Скажите пожалуйста - почему на executeQuery Вы не поставили @retryable - а обрабатываете его отдельно в рамках withRetries ?

Правильно ли я понимаю что сам ретрай нужен потому, что на базу может быть установлено ограничение по пропускной способности, RU/с и в случае большой нагрузки на запрос может прийти отказ - поэтому его может так случиться что запрос надо повторить без изменений.
Почему тогда в ретраях Вы не ставите некий таймаут?

Если в момент передачи запроса пропадет интернет соединение (мобильный телефон) - то это значит что прервется сессия ?
Следует ли из этого что надо совместно использовать withSessionRetry и withRetries ?

Make camel-casing of property names optional

Here:

https://github.com/yandex-cloud/ydb-nodejs-sdk/blob/a1cc0fc0ac4c9677b62fa69ce5733b0b91d3c09e/src/types.ts#L284

you explicitly camel-case TypedData object properties. This is very counter-intuitive and breaks things. What if I do want to use snake_cased properties in my models? How come the library doesn't even allow me to do that? It should be agnostic to naming conventions. For those who want that conversion, you can provide a static meta property or something else.

lost dbName attribute in AnonymousAuthService

In debug mode with ydb docker container dbName is not specified in auth service and i get error when i try to make SELECT request

I created simple fix snippet with below code and it works fine
Maybe I use wrong auth service with docker container


При отладке в тестовой среде через docker контейнер при использовании auth сервиса я получаю ошибку, когда пытаюсь выполнить SELECT запрос

Попробовал применить небольшой фикс ниже и все заработало отлично
Возможно я использую неверный auth сервис для авторизации с docker, поправьте меня


environement
node-container: node:14.17.6-buster-slim
ydb-sdk: 2.5.0

error

Cannot find table 'db.[request]' because it does not exist or you do not have access permissions. Please check correctness of table path and user permissions.

fix-snippet

    authService = new AnonymousAuthService()
    authService.getAuthMetadata = function () {
      const grpc = require('grpc')
      const metadata = new grpc.Metadata()
      metadata.add('x-ydb-database', '/local')
      return Promise.resolve(metadata)
    }

Type of bytesValue?

On 21075 line of node_modules/ydb-sdk-proto/proto/bundle.d.ts I see:

/** Value bytesValue */
bytesValue?: (Uint8Array|null);

But when I run simple queries like:

const result = await session.executeQuery(`
SELECT id FROM table;
`)

It shows that result.resultSets[0].rows[0].bytesValue is actually Buffer, not Uint8Array.
Is this a mistake?

feat: divide package into two: esm and cjs

Feature Request

Describe the Feature Request

It will possibly decrease package size as much as twice, but will complicate build and release process

Describe Preferred Solution

Describe Alternatives

Related Code

Additional Context

If the feature request is approved, would you be willing to submit a PR?
Yes / No (Help can be provided if you need assistance submitting a PR)

Prisma ORM for ydb-sdk

Feature Request

Implement ydb-sdk in Prisma ORM

Describe the Feature Request

Describe Preferred Solution

Describe Alternatives

Related Code

Additional Context

If the feature request is approved, would you be willing to submit a PR?
Yes / No (Help can be provided if you need assistance submitting a PR)

Добавьте ссылку на NPM в readme

Было бы полезно указать, что этот SDK можно установить напрямую из NPM, так как я об этом узнал только когда разбирал примеры в этом репозитории.

memory leak in v3

I've created a simple nodejs app with express:

require('dotenv').config();
const express = require('express');
const app = express();
var ydb_sdk = require('ydb-sdk');

app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.get('/api/player/get', async (req, res) => {
  let result = await getPlayer();
  res.send(result);
});
app.listen(3000);

async function getPlayer() {
  let query = 'select * from Players where id = 10';
  const logger = ydb_sdk.getLogger();
  const authService = ydb_sdk.getCredentialsFromEnv(logger);
  const database = process.env.DATABASE;
  const endpoint = process.env.ENDPOINT;
  const driver = new ydb_sdk.Driver({endpoint, database, authService, logger});
  if (!(await driver.ready(10000))) {
    process.exit(1);
  }
  let result
  await driver.tableClient.withSession(async (session) => {
    const preparedQuery = await session.prepareQuery(query);
    const response = await session.executeQuery(preparedQuery);
    const response_json = response.toJSON(); 
    result = response_json;
  });
  return result;
}

After every HTTP GET I see an app memory usage increase. After several requests I did a heap snapshot and see that there are same size objects accumulating:
image

node version: v16.14.0
ydb-sdk version: 3.1.1

dropTable не возвращает значение результата

Вызов dropTable на отсутствующей таблице не возвращает никакой ошибки

await driver.tableClient.withSession(async (session) => {
    // public async dropTable(tablePath: string, settings?: DropTableSettings): Promise<void> {
    try {
      await session.dropTable(`api/oGRKpx06wJkh`);
    } catch (e) {
      console.log('Ошибка');
    }
  });

Allow to pass SSL root certificates for IamAuthService ssl clients

It seems that the only use of that class is IamAuthService, which subclasses it. I do not know, why it does work without passing rootCertificates into grpc.credentials.createSsl() - but I am not sure whether that always be true. We need to check this assumption with our YDB colleagues, if that happened by sheer luck, pass rootCertificates here as well.

Originally posted by @tsufiev in #135 (comment)

bulk upsert

Тимур, скажите пожалуйста - почему Вы bulkupsert не опубликовали ?

У меня где то аналогичный код - вроде бы все работает.

YDB Node.js SDK v3

Changes:

  • Replace grpc with @grpc/js

  • Driver constructor reorganization: using IDriverSettings dynamic parameter instead of tuple of parameters.
    Before: new Driver(entryPoint, dbName, authService, ...)
    After: new Driver({connectionString: "...", authService: ..., ...}) or new Driver({endpoint: "...", database: "...", authService: "...", ...})

  • Simplifcation of authentication support:

    • database and rootCertificates are no longer needed in *AuthService constructors (rootCertificates is now initialized in the driver if it's neccessary)
      Before: const authService = new MetadataAuthService(dbName, makeSslCredentials());
      After: const authService = new MetadataAuthService();

    • getCredentialsFromEnv() is simplifed:
      Before: const authService = getCredentialsFromEnv(endpoint, database, logger);
      After: const authService = getCredentialsFromEnv(); (logger is optional)

    • Old credential environment variables are no longer supported
      .

  • Types:

    • Fix existing (tz datetime types, uuid) and support new types (decimal, container types)

    • TypedData.createNativeObjects() now supports non-primitive values (decimal, optional, container types) in incoming result sets

    • Introduce Types helper class to construct primitive and container types
      Before: @declareType({optionalType: {item: {typeId: Ydb.Type.PrimitiveTypeId.UINT64}}})
      After: @declareType(Types.optional(Types.UINT64))
      Before: new Column('series_id', Ydb.Type.create({optionalType: {item: {typeId: Ydb.Type.PrimitiveTypeId.UINT64}}}))
      After: new Column('series_id', Types.optional(Types.UINT64))

    • Introduce TypedValues helper class (instead of Primitive) to construct query parameters and key ranges (in readTable requests) without TypedData
      Before: {'$param': typedObj.getTypedValue('param')}
      After: {'$param': TypedValues.utf8(param)}

  • Table and Scheme clients: unify signature of client methods and introduce optional *Settings classes to avoid collisions in case of new optional parameters and simplify the usage.
    Before: session.executeQuery(query, {}, TX_AUTO, undefined, undefined, QueryStatsCollection.Mode.FULL)
    After: session.executeQuery(query, {}, TX_AUTO, new ExecuteQuerySettings.withCollectStats(QueryStatsCollection.Mode.FULL))

  • Fix bug when bulkUpsert and readTable methods require a table path with database prefix
    Before: session.readTable(database + '/' + tablePath)
    After: session.readTable(tablePath)

  • Refactoring and renaming:

    • rename entryPoint -> endpoint, dbName -> database in SDK code end examples
    • most of all interfaces have "I" prefix
    • Example npm commands moved from main package.json to examples + fix snippets in auth examples.
    • Reduce the number of exports from internal implementation

feat: Sequelize for YDB

Feature Request

Describe the Feature Request

Add sequelize support of YDB.

Describe Alternatives

Also possible to add other popular ORM, like TypeORM (#192)

Выборка данных, где в качестве параметра используется переменная типа String, всегда возвращает пустой результат

Версия библиотеки 1.9.0

Описание ошибки

Допустим, имеем таблицу tbl с колонкой id типа String:

id (String) value (Double)
abc 10
efg 20

Запрос вида:

class Entity extends TypedData {
  @declareType({ typeId: Ydb.Type.PrimitiveTypeId.STRING })
  id: string;

  @declareType({ typeId: Ydb.Type.PrimitiveTypeId.DOUBLE})
  value: number;
}

// --------

const query = `

      DECLARE $id AS String;

      SELECT id, value
        FROM \`tbl\`
       WHERE id = $id;
    `;

// --------

const preparedQuery = await session.prepareQuery(query);
const paramEntity = new Entity({id: 'efg'}); 
const queryResult = await session.executeQuery(
              preparedQuery,
              {$id: paramEntity.getTypedValue('id')} // value.bytesValue присваивается значение 'efg'
            );

вернёт пустой результат:

queryResult.resultSets[0].rows.length === 0
-> true

хотя должен был вернуть вторую строчку таблицы.

Предварительное решение

Удалось корректно получать данные из таблицы, если дополнительно преобразовывать value.bytesValue в base64, например так:

const paramEntity = new Entity({id: Buffer.from('efg').toString('base64')}); 

В коде для bytesValue есть обратное преобразование при получении данных с сервера, но нет при передаче параметров запроса на сервер (см. функцию preparePrimitiveValue)

просьба добавить поддержку параметра collectStats

table.ts
Session.executeQuery

просьба добавить поддержку параметра collectStats при вызове
this.api.executeDataQuery(request);

Это позволит получить статистику вызова запроса по аналогии с ydb.cli

Statistics:
query_phases {
duration_us: 1042
table_access {
name: "/ru-central1/.../messages"
reads {
rows: 1

bytes: 8
}
partitions_count: 1
}
cpu_time_us: 511
affected_shards: 1
}
compilation {
duration_us: 44141
cpu_time_us: 9013
}
process_cpu_time_us: 162

feat: add objection.js ORM

Feature Request

Describe the Feature Request

https://vincit.github.io/objection.js/

Describe Preferred Solution

Describe Alternatives

Related Code

Additional Context

If the feature request is approved, would you be willing to submit a PR?
Yes / No (Help can be provided if you need assistance submitting a PR)

Driver.destroy() не убивает driver

Драйвером можно успешно пользоваться после вызова метода .destroy()

Пример кода:

await driver.destroy();
await driver.tableClient.withSession(async (session) => {
    console.log(session);
})

Вот что в логе:

[1587455375471] DEBUG (6537 on mihanix-it-OSX): Destroying driver...
[1587455375472] DEBUG (6537 on mihanix-it-OSX): Destroying pool...
[1587455375472] DEBUG (6537 on mihanix-it-OSX): Pool has been destroyed.
[1587455375476] DEBUG (6537 on mihanix-it-OSX): Driver has been destroyed.
[1587455375616] DEBUG (6537 on mihanix-it-OSX): Acquired session ydb://session/3...

После беглого ознакомления с кодом, увидел что .destroy() только очищает текущие сессии в tableClient

Может так и задумывалось, конечно :)

ydb/core/ydb_convert/ydb_convert.cpp:202: Unknown protobuf type

При выполнении следующего кода получил ошибку где-то в недрах ядра YDB.

const result = await driver.tableClient.withSession(async (session) => {
        return await withRetries(async () => {
            const query = `DECLARE $phone_number AS Utf8;

                           SELECT COUNT(*) FROM call_password
                           WHERE phone_number = $phone_number AND created_at > CurrentUtcTimestamp() - Interval("PT10M");
                            
                           SELECT COUNT(*) FROM call_password
                           WHERE phone_number = $phone_number AND created_at > CurrentUtcTimestamp() - Interval("PT1H");
                            
                           SELECT COUNT(*) FROM call_password
                           WHERE phone_number = $phone_number AND created_at > CurrentUtcTimestamp() - Interval("P1D");`;

            const preparedQuery = await session.prepareQuery(query);
            return await session.executeQuery(preparedQuery, {
                '$phone_number': ctx.request.query.number
            });
        });
    });

Ошибка:

Error: BadRequest: [
     {
       "message": "Failed to parse query parameters.",
       "issues": [
         {
           "message": "ydb/core/ydb_convert/ydb_convert.cpp:202: Unknown protobuf type: ",
           "issueCode": 1
         }
       ]
     }
   ]
at Function.checkStatus (/usr/src/app/node_modules/ydb-sdk/build/errors.js:56:27)
at Object.getOperationPayload (/usr/src/app/node_modules/ydb-sdk/build/utils.js:127:27)
at Session.executeQuery (/usr/src/app/node_modules/ydb-sdk/build/table.js:391:37)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async Session.descriptor.value (/usr/src/app/node_modules/ydb-sdk/build/utils.js:157:20)
at async file:///usr/src/app/src/phone.js:77:20
at async RetryStrategy.retry (/usr/src/app/node_modules/ydb-sdk/build/retries.js:70:24)
at async withRetries (/usr/src/app/node_modules/ydb-sdk/build/retries.js:126:12)
at async file:///usr/src/app/src/phone.js:64:16
at async SessionPool._withSession (/usr/src/app/node_modules/ydb-sdk/build/table.js:643:32)

Есть идеи, где может быть проблема?

Убрать зависимость от `yandex-cloud`

yandex-cloud устаревший пакет, который зависит от c-based grpc реализации. Ранее в SDK убрали прямую зависимость (#128), так же стоит избавиться и от транзитивной.

Сейчас этот пакет используется лишь в одном месте для импорта TokenService.
https://github.com/ydb-platform/ydb-nodejs-sdk/blob/main/src/credentials.ts#L5

Вероятно, его можно заменить на аналогичный импорт из нового пакета:

import {MetadataTokenService} from '@yandex-cloud/nodejs-sdk/dist/token-service/metadata-token-service';

Мне кажется, это поможет решить и проблему #145, так как больше не придётся билдить grpc из исходников.

feat: add all available params for indexes

Feature Request

Add all available params for TableIndex, now available only indexColumns, but there are also:

  • globalIndex
  • globalAsyncIndex
  • dataColumns

Describe the Feature Request

Describe Preferred Solution

Describe Alternatives

Related Code

Place where indexes are absent
https://github.com/ydb-platform/ydb-nodejs-sdk/blob/main/src/table.ts#L1096

Additional Context

If the feature request is approved, would you be willing to submit a PR?
Yes / No (Help can be provided if you need assistance submitting a PR)

Add option to configure grpc.max_receive_message_length

I have query result more than 4MB and get the error
Error: 8 RESOURCE_EXHAUSTED: Received message larger than max (4324396 vs. 4194304)

I think you should add an option to configure grpc.max_receive_message_length.

https://github.com/yandex-cloud/ydb-nodejs-sdk/blob/8fb772f1518a209455aa5bf219fb5150bdae8716/src/utils.ts#L88

Example

new grpc.Client(host, grpc.credentials.createInsecure(), {
    "grpc.max_receive_message_length": 1024 * 1024 * 100,
    "grpc.max_send_message_length": 1024 * 1024 * 100
});

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.