From e984850bdbe85eeab34d582766b0a3915b5d9ec6 Mon Sep 17 00:00:00 2001 From: Iuga Mihai Date: Tue, 29 Aug 2023 16:01:23 +0300 Subject: [PATCH 1/6] indexer service --- docs/sdk-and-tools/elastic-search.md | 11 +++ docs/sdk-and-tools/indexer.md | 143 +++++++++++++++++++++++++++ sidebars.js | 1 + 3 files changed, 155 insertions(+) create mode 100644 docs/sdk-and-tools/indexer.md diff --git a/docs/sdk-and-tools/elastic-search.md b/docs/sdk-and-tools/elastic-search.md index 86cb859bc..04c0aca31 100644 --- a/docs/sdk-and-tools/elastic-search.md +++ b/docs/sdk-and-tools/elastic-search.md @@ -19,6 +19,17 @@ Our implementation uses a concept of a queue and makes sure that everything is b ## Setup +### Option 1 + +Set up four observers, each corresponding to a shard, with the `WebSocketHost` enabled, and create an instance of the `elasticindexer` service. +Follow the instructions provided on [this](/sdk-and-tools/indexer) page to accomplish this. + +### Option 2 + +:::warning +this Option will be removed on the release `rc/v1.7.0` +::: + In order to set up an observer that indexes in Elasticsearch, one has to update the `external.toml` file from the node's configuration directory. A minimum configuration would have `Enabled` set to `true` and the rest of the fields updated accordingly (`URL`, `Username`, `Password`). diff --git a/docs/sdk-and-tools/indexer.md b/docs/sdk-and-tools/indexer.md new file mode 100644 index 000000000..71d6f28ba --- /dev/null +++ b/docs/sdk-and-tools/indexer.md @@ -0,0 +1,143 @@ +--- +id: indexer +title: Elasticindexer service +--- + +[comment]: # (mx-abstract) + +## Overview + +A MultiversX observer node can send messages over `WebSocket` to an elastic indexer service, which will process and index the data in an Elasticsearch database. + +The GitHub repository for the notifier service can be found [here](https://github.com/multiversx/mx-chain-es-indexer-go). + +## Architectural Overview + +The observer node in the network will be connected to `elasticindexer` service. + +:::important +Set up one observer for each shard in order to handle all the data in the chain. +::: + +![img](/technology/indexer.png) + + +In the figure above: +- The observer nodes will send WebSocket messages to the `elasticindexer` service. +- The `elasticindexer` service will receive and process the WebSocket messages and index data in an Elasticsearch cluster. + + +[comment]: # (mx-context-auto) + +## Set up observer and notifier + +[comment]: # (mx-context-auto) + +### Observer Client + +On the observer side, there is a WebSocket host that will send messages to the elasticindexer service. + +In the observer node's configuration directory, `external.toml` config file can be configured +to enable host driver config. The config file can be found +[here](https://github.com/multiversx/mx-chain-go/blob/master/cmd/node/config/external.toml). + +The supported config variables are as follows: + +- `Enabled`: signals whether a driver should be attached when launching the node. +- `Mode`: this flag will start the WebSocket connector as server or client (can be "client" or "server") +- `URL`: this value represents the IP address and port number that the WebSocket client or server will use to establish a connection +- `WithAcknowledge`: after a message will be sent it will wait for an ack message if this flag is enabled +- `AcknowledgeTimeoutInSec`: the duration in seconds to wait for an acknowledgment message, after this time passes an error will be returned +- `MarshallerType`: possible values: json, gogo protobuf, should be compatible with elasticindexer config +- `RetryDurationInSec`: the number of seconds when the client will try again to send the data +- `BlockingAckOnError`: sets if, in case of data payload processing error, we should block or not the advancement to the next processing event. Set this to true if you wish the node to stop processing blocks if the client/server encounters errors while processing requests +- `DropMessagesIfNoConnection`: set to true to drop messages if there is no active WebSocket connection to send to. + + + +The corresponding config section for enabling the driver: + +```toml +[[HostDriversConfig]] + # This flag shall only be used for observer nodes + Enabled = true + # This flag will start the WebSocket connector as server or client (can be "client" or "server") + Mode = "client" + # URL for the WebSocket client/server connection + # This value represents the IP address and port number that the WebSocket client or server will use to establish a connection. + URL = "127.0.0.1:22111" + # After a message will be sent it will wait for an ack message if this flag is enabled + WithAcknowledge = true + # The duration in seconds to wait for an acknowledgment message, after this time passes an error will be returned + AcknowledgeTimeoutInSec = 60 + # Possible values: json, gogo protobuf. Should be compatible with mx-chain-es-indexer-go config + MarshallerType = "json" + # The number of seconds when the client will try again to send the data + RetryDurationInSec = 5 + # Sets if, in case of data payload processing error, we should block or not the advancement to the next processing event. Set this to true if you wish the node to stop processing blocks if the client/server encounters errors while processing requests. + BlockingAckOnError = true + # Set to true to drop messages if there is no active WebSocket connection to send to. + DropMessagesIfNoConnection = false +``` + + +### Elasticindexer service + +In the `elasticindexer` configuration directory (`cmd/elasticindexer/config`), there is the `prefs.toml` +file that can be used to configure the service. + +The supported config variables for web-socket section are: +- `url`: URL for the WebSocket client/server connection + as the port in the `ProxyUrl` described above. +- `mode`: this flag describes the mode to start the WebSocket connector. Can be "client" or "server" +- `data-marshaller-type`: possible values: json, gogo protobuf, should be compatible with observer host driver config +- `retry-duration-in-seconds`: retry duration (receive/send ack signal) in seconds +- `with-acknowledge`: after a message will be sent it will wait for an ack message if this flag is enabled +- `blocking-ack-on-error`: signals if in case of data payload processing error, we should send the ack signal or not +- `acknowledge-timeout-in-seconds`: the duration in seconds to wait for an acknowledgment message, after this time passes an error will be returned + +The `config.web-socket` section has to be aligned with the one from observer node: + +```toml +[config] + disabled-indices = [] + [config.web-socket] + # URL for the WebSocket client/server connection + # This value represents the IP address and port number that the WebSocket client or server will use to establish a connection. + url = "localhost:22111" + # This flag describes the mode to start the WebSocket connector. Can be "client" or "server" + mode = "server" + # Possible values: json, gogo protobuf. Should be compatible with mx-chain-node outport driver config + data-marshaller-type = "json" + # Retry duration (receive/send ack signal) in seconds + retry-duration-in-seconds = 5 + # Signals if in case of data payload processing error, we should send the ack signal or not + blocking-ack-on-error = true + # After a message will be sent it will wait for an ack message if this flag is enabled + with-acknowledge = true + # The duration in seconds to wait for an acknowledgment message, after this time passes an error will be returned + acknowledge-timeout-in-seconds = 50 +``` + + +The supported config variables for the `elastic-cluster` section: +- `url`: the url of the Elasticsearch cluster +- `username`: username for authentication (leave empty if not required) +- `password`: password associated with the username (leave empty if not required) +- `bulk-request-max-size-in-bytes`: maximum size of a bulk request in bytes + + +The corresponding config section for the Elasticsearch section: + +```toml +[config.elastic-cluster] + use-kibana = false + url = "http://localhost:9200" + username = "" + password = "" + bulk-request-max-size-in-bytes = 4194304 # 4MB +``` + + +For more details on `elasticindexer` service setup, please follow the **Install** and **Launching** +sections from [README](https://github.com/multiversx/mx-chain-es-indexer-go) in the repository. diff --git a/sidebars.js b/sidebars.js index c1ddc8be3..96dc6cd24 100644 --- a/sidebars.js +++ b/sidebars.js @@ -171,6 +171,7 @@ const sidebars = { label: "Elasticsearch", items: [ "sdk-and-tools/elastic-search", + "sdk-and-tools/indexer", "sdk-and-tools/es-index-wrong-mapping", { type: "category", From 15f8c9d08089691b858b3d3a01039c4a00e42b37 Mon Sep 17 00:00:00 2001 From: Iuga Mihai Date: Tue, 29 Aug 2023 16:03:32 +0300 Subject: [PATCH 2/6] bot markers --- .../developer-reference/serialization-format.md | 8 ++++++++ docs/sdk-and-tools/elastic-search.md | 4 ++++ docs/sdk-and-tools/indexer.md | 10 +++------- .../sdk-dapp/internal-processes/guardians.md | 5 +++-- docs/validators/node-configuration.md | 6 ++++++ docs/wallet/web-wallet.md | 5 ++++- docs/wallet/xportal.md | 3 ++- 7 files changed, 30 insertions(+), 11 deletions(-) diff --git a/docs/developers/developer-reference/serialization-format.md b/docs/developers/developer-reference/serialization-format.md index 81866af14..76418a7c5 100644 --- a/docs/developers/developer-reference/serialization-format.md +++ b/docs/developers/developer-reference/serialization-format.md @@ -574,8 +574,12 @@ export const ExampleTable = () => ( ); +[comment]: # (mx-context-auto) + ## Defaults +[comment]: # (mx-context-auto) + ### Built-in defaults The serialization format naturally supports defaults for most types. @@ -606,6 +610,8 @@ For instance, for all numeric types, zero is the default value, because we repre | `DayOfWeek` (see example above) | `DayOfWeek::Monday` | | `EnumWithEverything` (see example above) | `EnumWithEverything::Default` | +[comment]: # (mx-context-auto) + ### Types that have no defaults Certain types have no values that can be represented as an empty buffer, and therefore they have no default value. @@ -637,6 +643,8 @@ If you need the default, one workaround is to place these structures inside an ` There is, however, another way to do it: for custom structures it is possible to define custom defaults, as we will see in the next section. +[comment]: # (mx-context-auto) + ### Custom defaults A structure that does not have a natural default value can receive one via custom code. First of all this applies to structures, but it can also be useful for some enums. diff --git a/docs/sdk-and-tools/elastic-search.md b/docs/sdk-and-tools/elastic-search.md index 04c0aca31..c5a03c63a 100644 --- a/docs/sdk-and-tools/elastic-search.md +++ b/docs/sdk-and-tools/elastic-search.md @@ -19,11 +19,15 @@ Our implementation uses a concept of a queue and makes sure that everything is b ## Setup +[comment]: # (mx-context-auto) + ### Option 1 Set up four observers, each corresponding to a shard, with the `WebSocketHost` enabled, and create an instance of the `elasticindexer` service. Follow the instructions provided on [this](/sdk-and-tools/indexer) page to accomplish this. +[comment]: # (mx-context-auto) + ### Option 2 :::warning diff --git a/docs/sdk-and-tools/indexer.md b/docs/sdk-and-tools/indexer.md index 71d6f28ba..6255b6081 100644 --- a/docs/sdk-and-tools/indexer.md +++ b/docs/sdk-and-tools/indexer.md @@ -11,6 +11,8 @@ A MultiversX observer node can send messages over `WebSocket` to an elastic inde The GitHub repository for the notifier service can be found [here](https://github.com/multiversx/mx-chain-es-indexer-go). +[comment]: # (mx-context-auto) + ## Architectural Overview The observer node in the network will be connected to `elasticindexer` service. @@ -21,12 +23,10 @@ Set up one observer for each shard in order to handle all the data in the chain. ![img](/technology/indexer.png) - In the figure above: - The observer nodes will send WebSocket messages to the `elasticindexer` service. - The `elasticindexer` service will receive and process the WebSocket messages and index data in an Elasticsearch cluster. - [comment]: # (mx-context-auto) ## Set up observer and notifier @@ -53,8 +53,6 @@ The supported config variables are as follows: - `BlockingAckOnError`: sets if, in case of data payload processing error, we should block or not the advancement to the next processing event. Set this to true if you wish the node to stop processing blocks if the client/server encounters errors while processing requests - `DropMessagesIfNoConnection`: set to true to drop messages if there is no active WebSocket connection to send to. - - The corresponding config section for enabling the driver: ```toml @@ -80,6 +78,7 @@ The corresponding config section for enabling the driver: DropMessagesIfNoConnection = false ``` +[comment]: # (mx-context-auto) ### Elasticindexer service @@ -119,14 +118,12 @@ The `config.web-socket` section has to be aligned with the one from observer nod acknowledge-timeout-in-seconds = 50 ``` - The supported config variables for the `elastic-cluster` section: - `url`: the url of the Elasticsearch cluster - `username`: username for authentication (leave empty if not required) - `password`: password associated with the username (leave empty if not required) - `bulk-request-max-size-in-bytes`: maximum size of a bulk request in bytes - The corresponding config section for the Elasticsearch section: ```toml @@ -138,6 +135,5 @@ The corresponding config section for the Elasticsearch section: bulk-request-max-size-in-bytes = 4194304 # 4MB ``` - For more details on `elasticindexer` service setup, please follow the **Install** and **Launching** sections from [README](https://github.com/multiversx/mx-chain-es-indexer-go) in the repository. diff --git a/docs/sdk-and-tools/sdk-dapp/internal-processes/guardians.md b/docs/sdk-and-tools/sdk-dapp/internal-processes/guardians.md index 2f75d8741..ddfc2f447 100644 --- a/docs/sdk-and-tools/sdk-dapp/internal-processes/guardians.md +++ b/docs/sdk-and-tools/sdk-dapp/internal-processes/guardians.md @@ -30,11 +30,14 @@ transaction.setOptions(TransactionOptions.withOptions({ })); ``` +[comment]: # (mx-context-auto) + ### Signing the transaction Once these fields are set, the transaction must be signed by both Guardian (adding the `guardianSignuature` field) and UserSigner (adding the `signature` field). All signing providers (except Ledger) take care internally of formatting the transaction, as described above (excluding adding the extra `gasLimit`). +[comment]: # (mx-context-auto) #### Signing the transaction with Ledger @@ -43,7 +46,6 @@ After formatting the transaction and applying the signature provided by the Ledg ```js import { WalletProvider } from '@multiversx/sdk-web-wallet-provider'; - const walletProvider = new WalletProvider('https://www.wallet.multiversx.com/dapp/init'); walletProvider.guardTransactions(transactions, { callbackUrl: encodeURIComponent('https://my-dapp.com'), @@ -55,4 +57,3 @@ Once transactions are back from the web wallet, they can be retrieved as follows const signedTransactions = new WalletProvider('https://www.wallet.multiversx.com/dapp/init').getTransactionsFromWalletUrl(); ``` - diff --git a/docs/validators/node-configuration.md b/docs/validators/node-configuration.md index a0ae86264..1ffd14e8c 100644 --- a/docs/validators/node-configuration.md +++ b/docs/validators/node-configuration.md @@ -3,11 +3,15 @@ id: node-configuration title: Node Configuration --- +[comment]: # (mx-context-auto) + ## Introduction The node relies on some configuration files that are meant to allow the node operator to easily change some values that won't require a code change, a new release, or so on. +[comment]: # (mx-context-auto) + ## Configuration files All the configuration files are located by default in the `config` directory that resides near the node's binary. The paths can be changed @@ -73,6 +77,8 @@ Below you can find an example of how the configuration files look like for the ` - `ratings.toml` contains the parameters used for the nodes' rating mechanism, for example, the start rating, decrease steps, and so on - `systemSmartContractsConfig.toml` contains System Smart Contracts configurable values, such as parameters for Staking, ESDT, or Governance +[comment]: # (mx-context-auto) + ### Overriding config.toml values As mentioned in the above descriptions, `prefs.toml` is not overwritten by the installation scripts when performing an upgrade. diff --git a/docs/wallet/web-wallet.md b/docs/wallet/web-wallet.md index fef5661d5..1354fa24c 100644 --- a/docs/wallet/web-wallet.md +++ b/docs/wallet/web-wallet.md @@ -257,6 +257,8 @@ The Guardians feature allows you to change your guardian in situations where you This can be achieved by clicking th *Change Guardian* button from the Guardian's main dashboard. Afterwards you will be faced with two options: +[comment]: # (mx-context-auto) + #### **Changing guardian with 20 epochs pre-registration time** 1. **If you have lost access to the authenticator app**, you can address this issue by selecting the option *"I cannot access my guardian"* from the window mentioned below. @@ -287,7 +289,6 @@ Showcasing the details of the request: ![img](/wallet/web-wallet/guardian_change6.png) - If you were the one who initiated the request to change the guardian and you still have access to the currently active guardian, you will encounter two additional options: - Skip the cooldown period by clicking the **Confirm Change** button: By selecting this option, you can proceed with the change of the guardian without waiting for the cooldown period to elapse. @@ -304,6 +305,8 @@ If it was not you the one triggering the change of the guardian, it may be the c We recommend the first solution. Even though you have your funds staked, the unbound period (10 epochs) is shorther than the guardian activation period so that you have enough time to unstake and safely move them to a safe account. ::: +[comment]: # (mx-context-auto) + #### **Instantly changing guardian** To instantly change your guardian you must use the Change Guardian. You must follow a different set of steps compared to the previous *Change Guardian* way: diff --git a/docs/wallet/xportal.md b/docs/wallet/xportal.md index 4b7af72bb..9f1e54fd7 100644 --- a/docs/wallet/xportal.md +++ b/docs/wallet/xportal.md @@ -53,7 +53,7 @@ Yes, the Invisible Guardian can be changed, and there are two ways in which this - If the user has access to the current Guardian the change can be done immediately by signing a transaction; - If the user doesn’t have access to the current Guardian the process implies a 20-day cooldown period before the change of Guardian takes place. - + [comment]: # (mx-context-auto) ## Why do I have to wait 20 days to activate or change an Invisible Guardian? @@ -75,6 +75,7 @@ Aside from the extra security and the peace of mind that goes hand in hand with ## What if something happens to my device or I change it? The Invisible Guardian is stored locally on your device, but the first step of setting it up is creating an encrypted backup containing the Guardian. This makes importing it on a different device as easy as it gets, all you need to do is to provide the password associated with the guarded backup. + [comment]: # (mx-context-auto) ## What happens if my secret phrase is compromised? From d7fd5538127fa540d82857f80193382dee6632ba Mon Sep 17 00:00:00 2001 From: Iuga Mihai Date: Tue, 29 Aug 2023 16:11:17 +0300 Subject: [PATCH 3/6] fixes --- docs/sdk-and-tools/indexer.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/sdk-and-tools/indexer.md b/docs/sdk-and-tools/indexer.md index 6255b6081..ddc83b225 100644 --- a/docs/sdk-and-tools/indexer.md +++ b/docs/sdk-and-tools/indexer.md @@ -9,7 +9,7 @@ title: Elasticindexer service A MultiversX observer node can send messages over `WebSocket` to an elastic indexer service, which will process and index the data in an Elasticsearch database. -The GitHub repository for the notifier service can be found [here](https://github.com/multiversx/mx-chain-es-indexer-go). +The GitHub repository for the `elasticindexer` service can be found [here](https://github.com/multiversx/mx-chain-es-indexer-go). [comment]: # (mx-context-auto) @@ -29,7 +29,7 @@ In the figure above: [comment]: # (mx-context-auto) -## Set up observer and notifier +## Set up observer and elasticindexer [comment]: # (mx-context-auto) From 2b6475e36c5b1a0254e2ee41386020182478e3db Mon Sep 17 00:00:00 2001 From: Iuga Mihai Date: Wed, 30 Aug 2023 09:10:11 +0300 Subject: [PATCH 4/6] commit diagram --- static/technology/indexer.png | Bin 0 -> 56433 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 static/technology/indexer.png diff --git a/static/technology/indexer.png b/static/technology/indexer.png new file mode 100644 index 0000000000000000000000000000000000000000..b954f179c104b0cf4409a127d95f0945fea4e320 GIT binary patch literal 56433 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 m9b9$hZ@&-t3Sqk_X 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 Date: Wed, 30 Aug 2023 10:30:30 +0300 Subject: [PATCH 5/6] fixes after review --- .../{indexer.md => elastic-indexer.md} | 36 ++++--------------- docs/sdk-and-tools/elastic-search.md | 2 +- 2 files changed, 8 insertions(+), 30 deletions(-) rename docs/sdk-and-tools/{indexer.md => elastic-indexer.md} (63%) diff --git a/docs/sdk-and-tools/indexer.md b/docs/sdk-and-tools/elastic-indexer.md similarity index 63% rename from docs/sdk-and-tools/indexer.md rename to docs/sdk-and-tools/elastic-indexer.md index ddc83b225..1993d625b 100644 --- a/docs/sdk-and-tools/indexer.md +++ b/docs/sdk-and-tools/elastic-indexer.md @@ -7,9 +7,14 @@ title: Elasticindexer service ## Overview +:::tip +This feature will work starting from `rc/v1.6.0` version of the node +::: + + A MultiversX observer node can send messages over `WebSocket` to an elastic indexer service, which will process and index the data in an Elasticsearch database. -The GitHub repository for the `elasticindexer` service can be found [here](https://github.com/multiversx/mx-chain-es-indexer-go). +The GitHub repository for the `elasticindexer` service can be found [here](https://github.com/multiversx/mx-chain-es-indexer-go/tree/rc/v1.6.0). [comment]: # (mx-context-auto) @@ -39,19 +44,7 @@ On the observer side, there is a WebSocket host that will send messages to the e In the observer node's configuration directory, `external.toml` config file can be configured to enable host driver config. The config file can be found -[here](https://github.com/multiversx/mx-chain-go/blob/master/cmd/node/config/external.toml). - -The supported config variables are as follows: - -- `Enabled`: signals whether a driver should be attached when launching the node. -- `Mode`: this flag will start the WebSocket connector as server or client (can be "client" or "server") -- `URL`: this value represents the IP address and port number that the WebSocket client or server will use to establish a connection -- `WithAcknowledge`: after a message will be sent it will wait for an ack message if this flag is enabled -- `AcknowledgeTimeoutInSec`: the duration in seconds to wait for an acknowledgment message, after this time passes an error will be returned -- `MarshallerType`: possible values: json, gogo protobuf, should be compatible with elasticindexer config -- `RetryDurationInSec`: the number of seconds when the client will try again to send the data -- `BlockingAckOnError`: sets if, in case of data payload processing error, we should block or not the advancement to the next processing event. Set this to true if you wish the node to stop processing blocks if the client/server encounters errors while processing requests -- `DropMessagesIfNoConnection`: set to true to drop messages if there is no active WebSocket connection to send to. +[here](https://github.com/multiversx/mx-chain-go/blob/rc/v1.6.0/cmd/node/config/external.toml). The corresponding config section for enabling the driver: @@ -85,15 +78,6 @@ The corresponding config section for enabling the driver: In the `elasticindexer` configuration directory (`cmd/elasticindexer/config`), there is the `prefs.toml` file that can be used to configure the service. -The supported config variables for web-socket section are: -- `url`: URL for the WebSocket client/server connection - as the port in the `ProxyUrl` described above. -- `mode`: this flag describes the mode to start the WebSocket connector. Can be "client" or "server" -- `data-marshaller-type`: possible values: json, gogo protobuf, should be compatible with observer host driver config -- `retry-duration-in-seconds`: retry duration (receive/send ack signal) in seconds -- `with-acknowledge`: after a message will be sent it will wait for an ack message if this flag is enabled -- `blocking-ack-on-error`: signals if in case of data payload processing error, we should send the ack signal or not -- `acknowledge-timeout-in-seconds`: the duration in seconds to wait for an acknowledgment message, after this time passes an error will be returned The `config.web-socket` section has to be aligned with the one from observer node: @@ -118,12 +102,6 @@ The `config.web-socket` section has to be aligned with the one from observer nod acknowledge-timeout-in-seconds = 50 ``` -The supported config variables for the `elastic-cluster` section: -- `url`: the url of the Elasticsearch cluster -- `username`: username for authentication (leave empty if not required) -- `password`: password associated with the username (leave empty if not required) -- `bulk-request-max-size-in-bytes`: maximum size of a bulk request in bytes - The corresponding config section for the Elasticsearch section: ```toml diff --git a/docs/sdk-and-tools/elastic-search.md b/docs/sdk-and-tools/elastic-search.md index c5a03c63a..af942116c 100644 --- a/docs/sdk-and-tools/elastic-search.md +++ b/docs/sdk-and-tools/elastic-search.md @@ -31,7 +31,7 @@ Follow the instructions provided on [this](/sdk-and-tools/indexer) page to accom ### Option 2 :::warning -this Option will be removed on the release `rc/v1.7.0` +We plan to remove this option in the release `rc/v1.7.0` ::: In order to set up an observer that indexes in Elasticsearch, one has to update the `external.toml` file from the node's From dee1fb7b27c992676cb54a85628a33e95c832019 Mon Sep 17 00:00:00 2001 From: Iuga Mihai Date: Wed, 30 Aug 2023 12:34:00 +0300 Subject: [PATCH 6/6] small fix --- docs/sdk-and-tools/elastic-search.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sdk-and-tools/elastic-search.md b/docs/sdk-and-tools/elastic-search.md index af942116c..b7a008217 100644 --- a/docs/sdk-and-tools/elastic-search.md +++ b/docs/sdk-and-tools/elastic-search.md @@ -31,7 +31,7 @@ Follow the instructions provided on [this](/sdk-and-tools/indexer) page to accom ### Option 2 :::warning -We plan to remove this option in the release `rc/v1.7.0` +We plan to remove this option in the `rc/v1.7.0` release. ::: In order to set up an observer that indexes in Elasticsearch, one has to update the `external.toml` file from the node's