From 4ec09d3886eace33d2cd079d8644483c73179ba7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 28 Feb 2025 09:14:59 -0600 Subject: [PATCH 1/7] build(deps): bump actions/cache from 4.2.1 to 4.2.2 (#735) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/pr-checks.yaml | 2 +- .github/workflows/smoke-test.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr-checks.yaml b/.github/workflows/pr-checks.yaml index 8020a11f8..7fcb057ad 100644 --- a/.github/workflows/pr-checks.yaml +++ b/.github/workflows/pr-checks.yaml @@ -67,7 +67,7 @@ jobs: java-version: "21.0.6" - name: Cache Gradle packages - uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1 + uses: actions/cache@d4323d4df104b026a6aa633fdb11d772146be0bf # v4.2.2 with: path: | ~/.gradle/caches diff --git a/.github/workflows/smoke-test.yaml b/.github/workflows/smoke-test.yaml index 43c3fb897..857b5350e 100644 --- a/.github/workflows/smoke-test.yaml +++ b/.github/workflows/smoke-test.yaml @@ -55,7 +55,7 @@ jobs: rm grpcurl.tar.gz - name: Cache Gradle packages - uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1 + uses: actions/cache@d4323d4df104b026a6aa633fdb11d772146be0bf # v4.2.2 with: path: | ~/.gradle/caches From 0de778c3e78e980c98338be5d0bf054c1b148055 Mon Sep 17 00:00:00 2001 From: Alfredo Gutierrez Date: Sat, 1 Mar 2025 18:39:10 -0600 Subject: [PATCH 2/7] chore: Update metrics suffix and dashboards from hedera to hiero (#746) Signed-off-by: Alfredo Gutierrez --- .../dashboards/block-node-server.json | 92 +++++++++---------- .../metrics/dashboards/block-node-server.json | 92 +++++++++---------- .../block-stream-simulator-consumer.json | 4 +- .../block-stream-simulator-publisher.json | 8 +- .../server/metrics/MetricsServiceImpl.java | 2 +- .../simulator/metrics/MetricsServiceImpl.java | 2 +- 6 files changed, 100 insertions(+), 100 deletions(-) diff --git a/charts/block-node-server/dashboards/block-node-server.json b/charts/block-node-server/dashboards/block-node-server.json index aab0e7ea3..afc9631d9 100644 --- a/charts/block-node-server/dashboards/block-node-server.json +++ b/charts/block-node-server/dashboards/block-node-server.json @@ -91,7 +91,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "hedera_block_node_live_block_stream_mediator_error_total", + "expr": "hiero_block_node_live_block_stream_mediator_error_total", "instant": false, "legendFormat": "Block Item Errors", "range": true, @@ -190,7 +190,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "rate( hedera_block_node_live_block_stream_mediator_error_total [$__rate_interval])", + "expr": "rate( hiero_block_node_live_block_stream_mediator_error_total [$__rate_interval])", "instant": false, "legendFormat": "Mediator Errors", "range": true, @@ -260,7 +260,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "hedera_block_node_stream_persistence_handler_error_total", + "expr": "hiero_block_node_stream_persistence_handler_error_total", "instant": false, "legendFormat": "__auto", "range": true, @@ -355,7 +355,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "rate(hedera_block_node_stream_persistence_handler_error_total [$__rate_interval])", + "expr": "rate(hiero_block_node_stream_persistence_handler_error_total [$__rate_interval])", "instant": false, "legendFormat": "Stream Persistence Errors", "range": true, @@ -421,7 +421,7 @@ { "disableTextWrap": false, "editorMode": "code", - "expr": "last_over_time(hedera_block_node_verification_blocks_failed_total[$__interval])", + "expr": "last_over_time(hiero_block_node_verification_blocks_failed_total[$__interval])", "fullMetaSearch": false, "includeNullMetadata": true, "legendFormat": "Total Failed Verifications", @@ -519,7 +519,7 @@ { "disableTextWrap": false, "editorMode": "code", - "expr": "rate(hedera_block_node_verification_blocks_failed_total[$__rate_interval])", + "expr": "rate(hiero_block_node_verification_blocks_failed_total[$__rate_interval])", "fullMetaSearch": false, "includeNullMetadata": true, "legendFormat": "Total Failed Verifications", @@ -586,7 +586,7 @@ "targets": [ { "editorMode": "code", - "expr": "hedera_block_node_block_persistence_error_total", + "expr": "hiero_block_node_block_persistence_error_total", "legendFormat": "Block Persistence Error", "range": true, "refId": "A" @@ -679,7 +679,7 @@ "targets": [ { "editorMode": "code", - "expr": "rate( hedera_block_node_block_persistence_error_total [$__rate_interval])", + "expr": "rate( hiero_block_node_block_persistence_error_total [$__rate_interval])", "legendFormat": "Block Persistence Errors", "range": true, "refId": "A" @@ -758,7 +758,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "hedera_block_node_live_block_items_received_total", + "expr": "hiero_block_node_live_block_items_received_total", "instant": false, "legendFormat": "BlockItems", "range": true, @@ -862,7 +862,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "rate( hedera_block_node_live_block_items_received_total [$__rate_interval])", + "expr": "rate( hiero_block_node_live_block_items_received_total [$__rate_interval])", "instant": false, "legendFormat": "BlockItems", "range": true, @@ -928,7 +928,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "hedera_block_node_live_block_items_total", + "expr": "hiero_block_node_live_block_items_total", "instant": false, "legendFormat": "BlockItems", "range": true, @@ -1031,7 +1031,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "rate( hedera_block_node_live_block_items_total [$__rate_interval])", + "expr": "rate( hiero_block_node_live_block_items_total [$__rate_interval])", "instant": false, "legendFormat": "BlockItems", "range": true, @@ -1097,7 +1097,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "hedera_block_node_live_block_items_consumed_total", + "expr": "hiero_block_node_live_block_items_consumed_total", "instant": false, "legendFormat": "BlockItems Consumed", "range": true, @@ -1200,7 +1200,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "rate( hedera_block_node_live_block_items_consumed_total [$__rate_interval])", + "expr": "rate( hiero_block_node_live_block_items_consumed_total [$__rate_interval])", "instant": false, "legendFormat": "BlockItems", "range": true, @@ -1271,7 +1271,7 @@ "targets": [ { "editorMode": "code", - "expr": "hedera_block_node_current_block_number_outbound", + "expr": "hiero_block_node_current_block_number_outbound", "hide": true, "legendFormat": "__auto", "range": true, @@ -1283,7 +1283,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "hedera_block_node_current_block_number_inbound", + "expr": "hiero_block_node_current_block_number_inbound", "hide": true, "instant": false, "legendFormat": "__auto", @@ -1296,7 +1296,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "hedera_block_node_consumers", + "expr": "hiero_block_node_consumers", "hide": true, "instant": false, "legendFormat": "__auto", @@ -1402,7 +1402,7 @@ "targets": [ { "editorMode": "code", - "expr": "hedera_block_node_current_block_number_outbound", + "expr": "hiero_block_node_current_block_number_outbound", "hide": true, "legendFormat": "Outbound Blocks", "range": true, @@ -1414,7 +1414,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "hedera_block_node_current_block_number_inbound", + "expr": "hiero_block_node_current_block_number_inbound", "hide": true, "instant": false, "legendFormat": "Inbound Blocks", @@ -1427,7 +1427,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "hedera_block_node_consumers", + "expr": "hiero_block_node_consumers", "hide": true, "instant": false, "legendFormat": "Consumers", @@ -1515,7 +1515,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "hedera_block_node_mediator_ring_buffer_remaining_capacity", + "expr": "hiero_block_node_mediator_ring_buffer_remaining_capacity", "instant": false, "legendFormat": "Mediator Remaining Capacity", "range": true, @@ -1614,7 +1614,7 @@ }, "disableTextWrap": false, "editorMode": "code", - "expr": "min(hedera_block_node_mediator_ring_buffer_remaining_capacity)", + "expr": "min(hiero_block_node_mediator_ring_buffer_remaining_capacity)", "fullMetaSearch": false, "includeNullMetadata": true, "instant": false, @@ -1693,7 +1693,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "hedera_block_node_notifier_ring_buffer_remaining_capacity", + "expr": "hiero_block_node_notifier_ring_buffer_remaining_capacity", "instant": false, "legendFormat": "Notifier Remaining Capacity", "range": true, @@ -1791,7 +1791,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "min(hedera_block_node_notifier_ring_buffer_remaining_capacity)", + "expr": "min(hiero_block_node_notifier_ring_buffer_remaining_capacity)", "instant": false, "legendFormat": "__auto", "range": true, @@ -1863,7 +1863,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "hedera_block_node_producers", + "expr": "hiero_block_node_producers", "instant": false, "legendFormat": "Producers", "range": true, @@ -1936,7 +1936,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "hedera_block_node_consumers", + "expr": "hiero_block_node_consumers", "instant": false, "legendFormat": "Consumers", "range": true, @@ -2016,7 +2016,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "hedera_block_node_blocks_persisted_total", + "expr": "hiero_block_node_blocks_persisted_total", "instant": false, "legendFormat": "Block Persistence Counter", "range": true, @@ -2119,7 +2119,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "rate(hedera_block_node_blocks_persisted_total[$__rate_interval])", + "expr": "rate(hiero_block_node_blocks_persisted_total[$__rate_interval])", "instant": false, "legendFormat": "Block Persistence Counter", "range": true, @@ -2198,7 +2198,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "hedera_block_node_successful_pub_stream_resp_total", + "expr": "hiero_block_node_successful_pub_stream_resp_total", "instant": false, "legendFormat": "PublishStreamResponses", "range": true, @@ -2296,7 +2296,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "rate( hedera_block_node_successful_pub_stream_resp_total [$__rate_interval])", + "expr": "rate( hiero_block_node_successful_pub_stream_resp_total [$__rate_interval])", "instant": false, "legendFormat": "PublishStreamResponses", "range": true, @@ -2360,7 +2360,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "hedera_block_node_successful_pub_stream_resp_sent_total", + "expr": "hiero_block_node_successful_pub_stream_resp_sent_total", "instant": false, "legendFormat": "PublishStreamResponses", "range": true, @@ -2454,7 +2454,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "rate(hedera_block_node_successful_pub_stream_resp_sent_total[$__rate_interval])", + "expr": "rate(hiero_block_node_successful_pub_stream_resp_sent_total[$__rate_interval])", "instant": false, "legendFormat": "PublishStreamResponses", "range": true, @@ -2529,7 +2529,7 @@ { "disableTextWrap": false, "editorMode": "builder", - "expr": "last_over_time(hedera_block_node_verification_blocks_verified_total[$__interval])", + "expr": "last_over_time(hiero_block_node_verification_blocks_verified_total[$__interval])", "fullMetaSearch": false, "includeNullMetadata": true, "legendFormat": "__auto", @@ -2626,7 +2626,7 @@ { "disableTextWrap": false, "editorMode": "code", - "expr": "last_over_time(hedera_block_node_verification_blocks_verified_total[$__interval])", + "expr": "last_over_time(hiero_block_node_verification_blocks_verified_total[$__interval])", "fullMetaSearch": false, "includeNullMetadata": true, "legendFormat": "Blocks Verified over time", @@ -2698,7 +2698,7 @@ { "disableTextWrap": false, "editorMode": "code", - "expr": "(last_over_time(hedera_block_node_verification_block_time_total[$__interval]) / last_over_time(hedera_block_node_verification_blocks_verified_total[$__interval]) )", + "expr": "(last_over_time(hiero_block_node_verification_block_time_total[$__interval]) / last_over_time(hiero_block_node_verification_blocks_verified_total[$__interval]) )", "fullMetaSearch": false, "includeNullMetadata": true, "legendFormat": "__auto", @@ -2808,7 +2808,7 @@ { "disableTextWrap": false, "editorMode": "code", - "expr": "(last_over_time(hedera_block_node_verification_block_time_total[$__interval]) / last_over_time(hedera_block_node_verification_blocks_verified_total[$__interval]) )", + "expr": "(last_over_time(hiero_block_node_verification_block_time_total[$__interval]) / last_over_time(hiero_block_node_verification_blocks_verified_total[$__interval]) )", "fullMetaSearch": false, "includeNullMetadata": true, "legendFormat": "Average Block Verification Time in ms", @@ -2893,7 +2893,7 @@ { "disableTextWrap": false, "editorMode": "code", - "expr": "hedera_block_node_live_block_items_received_total / hedera_block_node_verification_blocks_verified_total", + "expr": "hiero_block_node_live_block_items_received_total / hiero_block_node_verification_blocks_verified_total", "fullMetaSearch": false, "includeNullMetadata": true, "legendFormat": "__auto", @@ -3007,7 +3007,7 @@ { "disableTextWrap": false, "editorMode": "code", - "expr": "hedera_block_node_live_block_items_received_total / hedera_block_node_verification_blocks_verified_total", + "expr": "hiero_block_node_live_block_items_received_total / hiero_block_node_verification_blocks_verified_total", "fullMetaSearch": false, "includeNullMetadata": true, "legendFormat": "__auto", @@ -3097,7 +3097,7 @@ { "disableTextWrap": false, "editorMode": "builder", - "expr": "last_over_time(hedera_block_node_acked_blocked_total[$__interval])", + "expr": "last_over_time(hiero_block_node_acked_blocked_total[$__interval])", "fullMetaSearch": false, "includeNullMetadata": true, "legendFormat": "__auto", @@ -3194,7 +3194,7 @@ { "disableTextWrap": false, "editorMode": "code", - "expr": "last_over_time(hedera_block_node_acked_blocked_total[$__interval])", + "expr": "last_over_time(hiero_block_node_acked_blocked_total[$__interval])", "fullMetaSearch": false, "includeNullMetadata": true, "legendFormat": "Blocks Acked over time", @@ -3280,7 +3280,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "hedera_block_node_single_blocks_retrieved_total", + "expr": "hiero_block_node_single_blocks_retrieved_total", "instant": false, "legendFormat": "Single Blocks Retrieved", "range": true, @@ -3379,7 +3379,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "rate(hedera_block_node_single_blocks_retrieved_total[$__rate_interval])", + "expr": "rate(hiero_block_node_single_blocks_retrieved_total[$__rate_interval])", "instant": false, "legendFormat": "RPS of Single Blocks Retrieval", "range": true, @@ -3449,7 +3449,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "hedera_block_node_single_blocks_not_found_total", + "expr": "hiero_block_node_single_blocks_not_found_total", "instant": false, "legendFormat": "Single Blocks Not Found", "range": true, @@ -3548,7 +3548,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "rate( hedera_block_node_single_blocks_not_found_total [$__rate_interval])", + "expr": "rate( hiero_block_node_single_blocks_not_found_total [$__rate_interval])", "instant": false, "legendFormat": "Single Blocks Not Found", "range": true, @@ -3609,7 +3609,7 @@ "targets": [ { "editorMode": "code", - "expr": "hedera_block_node_closed_range_historic_blocks_retrieved_total", + "expr": "hiero_block_node_closed_range_historic_blocks_retrieved_total", "legendFormat": "Closed Range Historic Blocks", "range": true, "refId": "A" @@ -3699,7 +3699,7 @@ "targets": [ { "editorMode": "code", - "expr": "rate(hedera_block_node_closed_range_historic_blocks_retrieved_total[$__rate_interval])", + "expr": "rate(hiero_block_node_closed_range_historic_blocks_retrieved_total[$__rate_interval])", "legendFormat": "Stream Closed-Range Historical Blocks", "range": true, "refId": "A" diff --git a/server/docker/metrics/dashboards/block-node-server.json b/server/docker/metrics/dashboards/block-node-server.json index aab0e7ea3..afc9631d9 100644 --- a/server/docker/metrics/dashboards/block-node-server.json +++ b/server/docker/metrics/dashboards/block-node-server.json @@ -91,7 +91,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "hedera_block_node_live_block_stream_mediator_error_total", + "expr": "hiero_block_node_live_block_stream_mediator_error_total", "instant": false, "legendFormat": "Block Item Errors", "range": true, @@ -190,7 +190,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "rate( hedera_block_node_live_block_stream_mediator_error_total [$__rate_interval])", + "expr": "rate( hiero_block_node_live_block_stream_mediator_error_total [$__rate_interval])", "instant": false, "legendFormat": "Mediator Errors", "range": true, @@ -260,7 +260,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "hedera_block_node_stream_persistence_handler_error_total", + "expr": "hiero_block_node_stream_persistence_handler_error_total", "instant": false, "legendFormat": "__auto", "range": true, @@ -355,7 +355,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "rate(hedera_block_node_stream_persistence_handler_error_total [$__rate_interval])", + "expr": "rate(hiero_block_node_stream_persistence_handler_error_total [$__rate_interval])", "instant": false, "legendFormat": "Stream Persistence Errors", "range": true, @@ -421,7 +421,7 @@ { "disableTextWrap": false, "editorMode": "code", - "expr": "last_over_time(hedera_block_node_verification_blocks_failed_total[$__interval])", + "expr": "last_over_time(hiero_block_node_verification_blocks_failed_total[$__interval])", "fullMetaSearch": false, "includeNullMetadata": true, "legendFormat": "Total Failed Verifications", @@ -519,7 +519,7 @@ { "disableTextWrap": false, "editorMode": "code", - "expr": "rate(hedera_block_node_verification_blocks_failed_total[$__rate_interval])", + "expr": "rate(hiero_block_node_verification_blocks_failed_total[$__rate_interval])", "fullMetaSearch": false, "includeNullMetadata": true, "legendFormat": "Total Failed Verifications", @@ -586,7 +586,7 @@ "targets": [ { "editorMode": "code", - "expr": "hedera_block_node_block_persistence_error_total", + "expr": "hiero_block_node_block_persistence_error_total", "legendFormat": "Block Persistence Error", "range": true, "refId": "A" @@ -679,7 +679,7 @@ "targets": [ { "editorMode": "code", - "expr": "rate( hedera_block_node_block_persistence_error_total [$__rate_interval])", + "expr": "rate( hiero_block_node_block_persistence_error_total [$__rate_interval])", "legendFormat": "Block Persistence Errors", "range": true, "refId": "A" @@ -758,7 +758,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "hedera_block_node_live_block_items_received_total", + "expr": "hiero_block_node_live_block_items_received_total", "instant": false, "legendFormat": "BlockItems", "range": true, @@ -862,7 +862,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "rate( hedera_block_node_live_block_items_received_total [$__rate_interval])", + "expr": "rate( hiero_block_node_live_block_items_received_total [$__rate_interval])", "instant": false, "legendFormat": "BlockItems", "range": true, @@ -928,7 +928,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "hedera_block_node_live_block_items_total", + "expr": "hiero_block_node_live_block_items_total", "instant": false, "legendFormat": "BlockItems", "range": true, @@ -1031,7 +1031,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "rate( hedera_block_node_live_block_items_total [$__rate_interval])", + "expr": "rate( hiero_block_node_live_block_items_total [$__rate_interval])", "instant": false, "legendFormat": "BlockItems", "range": true, @@ -1097,7 +1097,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "hedera_block_node_live_block_items_consumed_total", + "expr": "hiero_block_node_live_block_items_consumed_total", "instant": false, "legendFormat": "BlockItems Consumed", "range": true, @@ -1200,7 +1200,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "rate( hedera_block_node_live_block_items_consumed_total [$__rate_interval])", + "expr": "rate( hiero_block_node_live_block_items_consumed_total [$__rate_interval])", "instant": false, "legendFormat": "BlockItems", "range": true, @@ -1271,7 +1271,7 @@ "targets": [ { "editorMode": "code", - "expr": "hedera_block_node_current_block_number_outbound", + "expr": "hiero_block_node_current_block_number_outbound", "hide": true, "legendFormat": "__auto", "range": true, @@ -1283,7 +1283,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "hedera_block_node_current_block_number_inbound", + "expr": "hiero_block_node_current_block_number_inbound", "hide": true, "instant": false, "legendFormat": "__auto", @@ -1296,7 +1296,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "hedera_block_node_consumers", + "expr": "hiero_block_node_consumers", "hide": true, "instant": false, "legendFormat": "__auto", @@ -1402,7 +1402,7 @@ "targets": [ { "editorMode": "code", - "expr": "hedera_block_node_current_block_number_outbound", + "expr": "hiero_block_node_current_block_number_outbound", "hide": true, "legendFormat": "Outbound Blocks", "range": true, @@ -1414,7 +1414,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "hedera_block_node_current_block_number_inbound", + "expr": "hiero_block_node_current_block_number_inbound", "hide": true, "instant": false, "legendFormat": "Inbound Blocks", @@ -1427,7 +1427,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "hedera_block_node_consumers", + "expr": "hiero_block_node_consumers", "hide": true, "instant": false, "legendFormat": "Consumers", @@ -1515,7 +1515,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "hedera_block_node_mediator_ring_buffer_remaining_capacity", + "expr": "hiero_block_node_mediator_ring_buffer_remaining_capacity", "instant": false, "legendFormat": "Mediator Remaining Capacity", "range": true, @@ -1614,7 +1614,7 @@ }, "disableTextWrap": false, "editorMode": "code", - "expr": "min(hedera_block_node_mediator_ring_buffer_remaining_capacity)", + "expr": "min(hiero_block_node_mediator_ring_buffer_remaining_capacity)", "fullMetaSearch": false, "includeNullMetadata": true, "instant": false, @@ -1693,7 +1693,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "hedera_block_node_notifier_ring_buffer_remaining_capacity", + "expr": "hiero_block_node_notifier_ring_buffer_remaining_capacity", "instant": false, "legendFormat": "Notifier Remaining Capacity", "range": true, @@ -1791,7 +1791,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "min(hedera_block_node_notifier_ring_buffer_remaining_capacity)", + "expr": "min(hiero_block_node_notifier_ring_buffer_remaining_capacity)", "instant": false, "legendFormat": "__auto", "range": true, @@ -1863,7 +1863,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "hedera_block_node_producers", + "expr": "hiero_block_node_producers", "instant": false, "legendFormat": "Producers", "range": true, @@ -1936,7 +1936,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "hedera_block_node_consumers", + "expr": "hiero_block_node_consumers", "instant": false, "legendFormat": "Consumers", "range": true, @@ -2016,7 +2016,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "hedera_block_node_blocks_persisted_total", + "expr": "hiero_block_node_blocks_persisted_total", "instant": false, "legendFormat": "Block Persistence Counter", "range": true, @@ -2119,7 +2119,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "rate(hedera_block_node_blocks_persisted_total[$__rate_interval])", + "expr": "rate(hiero_block_node_blocks_persisted_total[$__rate_interval])", "instant": false, "legendFormat": "Block Persistence Counter", "range": true, @@ -2198,7 +2198,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "hedera_block_node_successful_pub_stream_resp_total", + "expr": "hiero_block_node_successful_pub_stream_resp_total", "instant": false, "legendFormat": "PublishStreamResponses", "range": true, @@ -2296,7 +2296,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "rate( hedera_block_node_successful_pub_stream_resp_total [$__rate_interval])", + "expr": "rate( hiero_block_node_successful_pub_stream_resp_total [$__rate_interval])", "instant": false, "legendFormat": "PublishStreamResponses", "range": true, @@ -2360,7 +2360,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "hedera_block_node_successful_pub_stream_resp_sent_total", + "expr": "hiero_block_node_successful_pub_stream_resp_sent_total", "instant": false, "legendFormat": "PublishStreamResponses", "range": true, @@ -2454,7 +2454,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "rate(hedera_block_node_successful_pub_stream_resp_sent_total[$__rate_interval])", + "expr": "rate(hiero_block_node_successful_pub_stream_resp_sent_total[$__rate_interval])", "instant": false, "legendFormat": "PublishStreamResponses", "range": true, @@ -2529,7 +2529,7 @@ { "disableTextWrap": false, "editorMode": "builder", - "expr": "last_over_time(hedera_block_node_verification_blocks_verified_total[$__interval])", + "expr": "last_over_time(hiero_block_node_verification_blocks_verified_total[$__interval])", "fullMetaSearch": false, "includeNullMetadata": true, "legendFormat": "__auto", @@ -2626,7 +2626,7 @@ { "disableTextWrap": false, "editorMode": "code", - "expr": "last_over_time(hedera_block_node_verification_blocks_verified_total[$__interval])", + "expr": "last_over_time(hiero_block_node_verification_blocks_verified_total[$__interval])", "fullMetaSearch": false, "includeNullMetadata": true, "legendFormat": "Blocks Verified over time", @@ -2698,7 +2698,7 @@ { "disableTextWrap": false, "editorMode": "code", - "expr": "(last_over_time(hedera_block_node_verification_block_time_total[$__interval]) / last_over_time(hedera_block_node_verification_blocks_verified_total[$__interval]) )", + "expr": "(last_over_time(hiero_block_node_verification_block_time_total[$__interval]) / last_over_time(hiero_block_node_verification_blocks_verified_total[$__interval]) )", "fullMetaSearch": false, "includeNullMetadata": true, "legendFormat": "__auto", @@ -2808,7 +2808,7 @@ { "disableTextWrap": false, "editorMode": "code", - "expr": "(last_over_time(hedera_block_node_verification_block_time_total[$__interval]) / last_over_time(hedera_block_node_verification_blocks_verified_total[$__interval]) )", + "expr": "(last_over_time(hiero_block_node_verification_block_time_total[$__interval]) / last_over_time(hiero_block_node_verification_blocks_verified_total[$__interval]) )", "fullMetaSearch": false, "includeNullMetadata": true, "legendFormat": "Average Block Verification Time in ms", @@ -2893,7 +2893,7 @@ { "disableTextWrap": false, "editorMode": "code", - "expr": "hedera_block_node_live_block_items_received_total / hedera_block_node_verification_blocks_verified_total", + "expr": "hiero_block_node_live_block_items_received_total / hiero_block_node_verification_blocks_verified_total", "fullMetaSearch": false, "includeNullMetadata": true, "legendFormat": "__auto", @@ -3007,7 +3007,7 @@ { "disableTextWrap": false, "editorMode": "code", - "expr": "hedera_block_node_live_block_items_received_total / hedera_block_node_verification_blocks_verified_total", + "expr": "hiero_block_node_live_block_items_received_total / hiero_block_node_verification_blocks_verified_total", "fullMetaSearch": false, "includeNullMetadata": true, "legendFormat": "__auto", @@ -3097,7 +3097,7 @@ { "disableTextWrap": false, "editorMode": "builder", - "expr": "last_over_time(hedera_block_node_acked_blocked_total[$__interval])", + "expr": "last_over_time(hiero_block_node_acked_blocked_total[$__interval])", "fullMetaSearch": false, "includeNullMetadata": true, "legendFormat": "__auto", @@ -3194,7 +3194,7 @@ { "disableTextWrap": false, "editorMode": "code", - "expr": "last_over_time(hedera_block_node_acked_blocked_total[$__interval])", + "expr": "last_over_time(hiero_block_node_acked_blocked_total[$__interval])", "fullMetaSearch": false, "includeNullMetadata": true, "legendFormat": "Blocks Acked over time", @@ -3280,7 +3280,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "hedera_block_node_single_blocks_retrieved_total", + "expr": "hiero_block_node_single_blocks_retrieved_total", "instant": false, "legendFormat": "Single Blocks Retrieved", "range": true, @@ -3379,7 +3379,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "rate(hedera_block_node_single_blocks_retrieved_total[$__rate_interval])", + "expr": "rate(hiero_block_node_single_blocks_retrieved_total[$__rate_interval])", "instant": false, "legendFormat": "RPS of Single Blocks Retrieval", "range": true, @@ -3449,7 +3449,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "hedera_block_node_single_blocks_not_found_total", + "expr": "hiero_block_node_single_blocks_not_found_total", "instant": false, "legendFormat": "Single Blocks Not Found", "range": true, @@ -3548,7 +3548,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "rate( hedera_block_node_single_blocks_not_found_total [$__rate_interval])", + "expr": "rate( hiero_block_node_single_blocks_not_found_total [$__rate_interval])", "instant": false, "legendFormat": "Single Blocks Not Found", "range": true, @@ -3609,7 +3609,7 @@ "targets": [ { "editorMode": "code", - "expr": "hedera_block_node_closed_range_historic_blocks_retrieved_total", + "expr": "hiero_block_node_closed_range_historic_blocks_retrieved_total", "legendFormat": "Closed Range Historic Blocks", "range": true, "refId": "A" @@ -3699,7 +3699,7 @@ "targets": [ { "editorMode": "code", - "expr": "rate(hedera_block_node_closed_range_historic_blocks_retrieved_total[$__rate_interval])", + "expr": "rate(hiero_block_node_closed_range_historic_blocks_retrieved_total[$__rate_interval])", "legendFormat": "Stream Closed-Range Historical Blocks", "range": true, "refId": "A" diff --git a/server/docker/metrics/dashboards/block-stream-simulator-consumer.json b/server/docker/metrics/dashboards/block-stream-simulator-consumer.json index 3e01de06e..b2d0d97f0 100644 --- a/server/docker/metrics/dashboards/block-stream-simulator-consumer.json +++ b/server/docker/metrics/dashboards/block-stream-simulator-consumer.json @@ -91,7 +91,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "hedera_block_node_simulator_live_blocks_consumed_total{instance_type=\"$instance_type\"}", + "expr": "hiero_block_node_simulator_live_blocks_consumed_total{instance_type=\"$instance_type\"}", "instant": false, "legendFormat": "Blocks Consumed", "range": true, @@ -183,7 +183,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "rate(hedera_block_node_simulator_live_blocks_consumed_total{instance_type=\"$instance_type\"}[$__rate_interval])", + "expr": "rate(hiero_block_node_simulator_live_blocks_consumed_total{instance_type=\"$instance_type\"}[$__rate_interval])", "instant": false, "legendFormat": "Blocks Consume Rate", "range": true, diff --git a/server/docker/metrics/dashboards/block-stream-simulator-publisher.json b/server/docker/metrics/dashboards/block-stream-simulator-publisher.json index 8b7dddcdb..68ad953f9 100644 --- a/server/docker/metrics/dashboards/block-stream-simulator-publisher.json +++ b/server/docker/metrics/dashboards/block-stream-simulator-publisher.json @@ -91,7 +91,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "hedera_block_node_simulator_live_block_items_sent_total{instance_type=\"$instance_type\"}", + "expr": "hiero_block_node_simulator_live_block_items_sent_total{instance_type=\"$instance_type\"}", "instant": false, "legendFormat": "Block Items Sent", "range": true, @@ -183,7 +183,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "rate(hedera_block_node_simulator_live_block_items_sent_total{instance_type=\"$instance_type\"}[$__rate_interval])", + "expr": "rate(hiero_block_node_simulator_live_block_items_sent_total{instance_type=\"$instance_type\"}[$__rate_interval])", "instant": false, "legendFormat": "Block Items Send Rate", "range": true, @@ -262,7 +262,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "hedera_block_node_simulator_live_blocks_sent_total{instance_type=\"$instance_type\"}", + "expr": "hiero_block_node_simulator_live_blocks_sent_total{instance_type=\"$instance_type\"}", "instant": false, "legendFormat": "Blocks Sent", "range": true, @@ -354,7 +354,7 @@ "uid": "prometheus" }, "editorMode": "code", - "expr": "rate(hedera_block_node_simulator_live_blocks_sent_total{instance_type=\"$instance_type\"}[$__rate_interval])", + "expr": "rate(hiero_block_node_simulator_live_blocks_sent_total{instance_type=\"$instance_type\"}[$__rate_interval])", "instant": false, "legendFormat": "Blocks Send Rate", "range": true, diff --git a/server/src/main/java/com/hedera/block/server/metrics/MetricsServiceImpl.java b/server/src/main/java/com/hedera/block/server/metrics/MetricsServiceImpl.java index 31a46b237..54e9e5343 100644 --- a/server/src/main/java/com/hedera/block/server/metrics/MetricsServiceImpl.java +++ b/server/src/main/java/com/hedera/block/server/metrics/MetricsServiceImpl.java @@ -16,7 +16,7 @@ * example, to increment a counter, call {@link Counter#increment()}. */ public final class MetricsServiceImpl implements MetricsService { - private static final String CATEGORY = "hedera_block_node"; + private static final String CATEGORY = "hiero_block_node"; private final EnumMap counters = new EnumMap<>(BlockNodeMetricTypes.Counter.class); private final EnumMap gauges = diff --git a/simulator/src/main/java/com/hedera/block/simulator/metrics/MetricsServiceImpl.java b/simulator/src/main/java/com/hedera/block/simulator/metrics/MetricsServiceImpl.java index 74bb87878..63faa5792 100644 --- a/simulator/src/main/java/com/hedera/block/simulator/metrics/MetricsServiceImpl.java +++ b/simulator/src/main/java/com/hedera/block/simulator/metrics/MetricsServiceImpl.java @@ -15,7 +15,7 @@ */ public class MetricsServiceImpl implements MetricsService { - private static final String CATEGORY = "hedera_block_node_simulator"; + private static final String CATEGORY = "hiero_block_node_simulator"; private final EnumMap counters = new EnumMap<>(SimulatorMetricTypes.Counter.class); From 0b918d938a2c5a325fbaaa8decddd6491d682fd5 Mon Sep 17 00:00:00 2001 From: Alfredo Gutierrez Date: Sat, 1 Mar 2025 18:40:58 -0600 Subject: [PATCH 3/7] fix: Improvements and fixes to Helm charts and docker compose (#745) Signed-off-by: Alfredo Gutierrez --- charts/block-node-server/values.yaml | 25 ++++++++----------- .../templates/deployment.yaml | 2 +- .../values-overrides/consumer.yaml | 7 ++++++ charts/blockstream-simulator/values.yaml | 11 ++++++-- simulator/docker/update-env.sh | 2 +- 5 files changed, 29 insertions(+), 18 deletions(-) create mode 100644 charts/blockstream-simulator/values-overrides/consumer.yaml diff --git a/charts/block-node-server/values.yaml b/charts/block-node-server/values.yaml index d7f333d58..61235fe08 100644 --- a/charts/block-node-server/values.yaml +++ b/charts/block-node-server/values.yaml @@ -58,8 +58,8 @@ ingress: resources: requests: - cpu: "2" - memory: "8Gi" + cpu: "8" + memory: "24Gi" nodeSelector: {} @@ -73,8 +73,14 @@ blockNode: config: # Add any additional env configuration here # key: value - BLOCKNODE_STORAGE_ROOT_PATH: "/app/storage" JAVA_TOOL_OPTIONS: "-Djava.util.logging.config.file=/app/logs/config/logging.properties" + JAVA_OPTS: "-Xms16G -Xmx16G" + # PRODUCER_TYPE: "NO_OP" + # PERSISTENCE_STORAGE_TYPE: "NO_OP" + # VERIFICATION_TYPE: "NO_OP" + # MEDIATOR_TYPE: "NO_OP" + MEDIATOR_RING_BUFFER_SIZE: "4096" + secret: PRIVATE_KEY: "fake_private_key" health: @@ -84,18 +90,12 @@ blockNode: endpoint: "/healthz/livez" metrics: port: 9999 - resources: - limits: - cpu: "8" - memory: "16Gi" - requests: - cpu: "2" - memory: "8Gi" logs: # Available Levels are (from most verbose to least verbose): # ALL FINEST FINER FINE CONFIG INFO WARNING SEVERE OFF level: "INFO" loggingProperties: + # com.hedera.block.server.producer.ProducerBlockItemObserver.level: "FINE" io.helidon.webserver.level: "INFO" io.helidon.webserver.access.level: "INFO" io.helidon.config.level: "SEVERE" @@ -121,10 +121,7 @@ blockNode: # %4$ - log level # %5$ - log message # %6$ - throwable trace - # - # Example to produce a line such as: - # 2025-01-04 00:34:43 INFO [com.hedera.block.server.Server main] Starting BlockNode Server - java.util.logging.SimpleFormatter.format: "%1$tF %1$tT %4$-7s [%2$s] %5$s %n" + java.util.logging.SimpleFormatter.format: "%TF % Date: Mon, 3 Mar 2025 10:13:38 -0700 Subject: [PATCH 4/7] build(deps): bump com.github.spotbugs:spotbugs-annotations from 4.9.1 to 4.9.2 in /hiero-dependency-versions (#756) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- hiero-dependency-versions/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hiero-dependency-versions/build.gradle.kts b/hiero-dependency-versions/build.gradle.kts index 74f33432a..8db95170b 100644 --- a/hiero-dependency-versions/build.gradle.kts +++ b/hiero-dependency-versions/build.gradle.kts @@ -17,7 +17,7 @@ dependencies.constraints { val swirldsVersion = "0.58.4" api("com.github.luben:zstd-jni:1.5.7-1") { because("com.github.luben.zstd_jni") } - api("com.github.spotbugs:spotbugs-annotations:4.9.1") { + api("com.github.spotbugs:spotbugs-annotations:4.9.2") { because("com.github.spotbugs.annotations") } api("com.google.auto.service:auto-service-annotations:1.1.1") { From 3236bb925b6fca9e0ab1de424693d73fd35853a4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Mar 2025 10:14:35 -0700 Subject: [PATCH 5/7] build(deps): bump org.testcontainers:testcontainers from 1.20.4 to 1.20.5 in /hiero-dependency-versions (#754) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- hiero-dependency-versions/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hiero-dependency-versions/build.gradle.kts b/hiero-dependency-versions/build.gradle.kts index 8db95170b..34cfedf36 100644 --- a/hiero-dependency-versions/build.gradle.kts +++ b/hiero-dependency-versions/build.gradle.kts @@ -70,7 +70,7 @@ dependencies.constraints { api("org.mockito:mockito-core:5.15.2") { because("org.mockito") } api("org.mockito:mockito-junit-jupiter:5.15.2") { because("org.mockito.junit.jupiter") } api("org.testcontainers:junit-jupiter:1.20.5") { because("org.testcontainers.junit.jupiter") } - api("org.testcontainers:testcontainers:1.20.4") { because("org.testcontainers") } + api("org.testcontainers:testcontainers:1.20.5") { because("org.testcontainers") } api("com.google.auto.service:auto-service:1.1.1") { because("com.google.auto.service.processor") From 2528d6818ffe949f41607d8a62a305cea62ea9f4 Mon Sep 17 00:00:00 2001 From: Alfredo Gutierrez Date: Mon, 3 Mar 2025 15:54:50 -0600 Subject: [PATCH 6/7] build(deps): Upgrade Swirlds dependency to `0.59.2` (#761) Signed-off-by: Alfredo Gutierrez Grajeda --- hiero-dependency-versions/build.gradle.kts | 2 +- .../server/config/TestConfigBuilder.java | 223 ----------------- .../logging/ConfigurationLoggingImplTest.java | 16 +- .../StreamPersistenceHandlerImplTest.java | 6 +- .../archive/LocalGroupZipArchiveTaskTest.java | 17 +- .../block/server/util/TestConfigUtil.java | 7 +- .../com/hedera/block/simulator/TestUtils.java | 11 +- .../simulator/config/TestConfigBuilder.java | 225 ------------------ 8 files changed, 35 insertions(+), 472 deletions(-) delete mode 100644 server/src/test/java/com/hedera/block/server/config/TestConfigBuilder.java delete mode 100644 simulator/src/test/java/com/hedera/block/simulator/config/TestConfigBuilder.java diff --git a/hiero-dependency-versions/build.gradle.kts b/hiero-dependency-versions/build.gradle.kts index 34cfedf36..fe350ec65 100644 --- a/hiero-dependency-versions/build.gradle.kts +++ b/hiero-dependency-versions/build.gradle.kts @@ -14,7 +14,7 @@ dependencies.constraints { val helidonVersion = "4.1.6" val pbjVersion = "0.9.17" val protobufVersion = "4.29.3" - val swirldsVersion = "0.58.4" + val swirldsVersion = "0.59.2" api("com.github.luben:zstd-jni:1.5.7-1") { because("com.github.luben.zstd_jni") } api("com.github.spotbugs:spotbugs-annotations:4.9.2") { diff --git a/server/src/test/java/com/hedera/block/server/config/TestConfigBuilder.java b/server/src/test/java/com/hedera/block/server/config/TestConfigBuilder.java deleted file mode 100644 index 6a4c3f277..000000000 --- a/server/src/test/java/com/hedera/block/server/config/TestConfigBuilder.java +++ /dev/null @@ -1,223 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -package com.hedera.block.server.config; - -import com.swirlds.common.threading.locks.AutoClosableLock; -import com.swirlds.common.threading.locks.Locks; -import com.swirlds.common.threading.locks.locked.Locked; -import com.swirlds.config.api.ConfigData; -import com.swirlds.config.api.Configuration; -import com.swirlds.config.api.ConfigurationBuilder; -import com.swirlds.config.api.converter.ConfigConverter; -import com.swirlds.config.api.source.ConfigSource; -import com.swirlds.config.api.validation.ConfigValidator; -import com.swirlds.config.extensions.sources.SimpleConfigSource; -import edu.umd.cs.findbugs.annotations.NonNull; -import edu.umd.cs.findbugs.annotations.Nullable; -import java.util.Objects; - -/** - * Helper for use the config in test and change the config for specific tests. Instance can be used - * per class or per test. - */ -public class TestConfigBuilder { - - private final AutoClosableLock configLock = Locks.createAutoLock(); - - private Configuration configuration = null; - - private final ConfigurationBuilder builder; - - /** - * Creates a new instance and automatically registers all config data records (see {@link - * ConfigData}) on classpath / modulepath that are part of the packages {@code com.swirlds} and - * {@code com.hedera}. - */ - public TestConfigBuilder() { - this(true); - } - - /** - * Creates a new instance and automatically registers all given config data records. This call - * will not do a class scan for config data records on classpath / modulepath like some of the - * other constructors do. - * - * @param dataTypes - */ - public TestConfigBuilder(@Nullable final Class dataTypes) { - this(false); - if (dataTypes != null) { - this.builder.withConfigDataTypes(dataTypes); - } - } - - /** - * Creates a new instance and automatically registers all config data records (see {@link - * ConfigData}) on classpath / modulepath that are part of the packages {@code com.swirlds} and - * {@code com.hedera}. if the {@code registerAllTypes} param is true. - * - * @param registerAllTypes if true all config data records on classpath will automatically be - * registered - */ - public TestConfigBuilder(final boolean registerAllTypes) { - if (registerAllTypes) { - this.builder = ConfigurationBuilder.create().autoDiscoverExtensions(); - } else { - this.builder = ConfigurationBuilder.create(); - } - } - - /** - * Sets the value for the config. - * - * @param propertyName name of the property - * @param value the value - * @return the {@link TestConfigBuilder} instance (for fluent API) - */ - @NonNull - public TestConfigBuilder withValue(@NonNull final String propertyName, @Nullable final String value) { - return withSource(new SimpleConfigSource(propertyName, value)); - } - - /** - * Sets the value for the config. - * - * @param propertyName name of the property - * @param value the value - * @return the {@link TestConfigBuilder} instance (for fluent API) - */ - @NonNull - public TestConfigBuilder withValue(@NonNull final String propertyName, final int value) { - return withSource(new SimpleConfigSource(propertyName, value)); - } - - /** - * Sets the value for the config. - * - * @param propertyName name of the property - * @param value the value - * @return the {@link TestConfigBuilder} instance (for fluent API) - */ - @NonNull - public TestConfigBuilder withValue(@NonNull final String propertyName, final double value) { - return withSource(new SimpleConfigSource(propertyName, value)); - } - - /** - * Sets the value for the config. - * - * @param propertyName name of the property - * @param value the value - * @return the {@link TestConfigBuilder} instance (for fluent API) - */ - @NonNull - public TestConfigBuilder withValue(@NonNull final String propertyName, final long value) { - return withSource(new SimpleConfigSource(propertyName, value)); - } - - /** - * Sets the value for the config. - * - * @param propertyName name of the property - * @param value the value - * @return the {@link TestConfigBuilder} instance (for fluent API) - */ - @NonNull - public TestConfigBuilder withValue(@NonNull final String propertyName, final boolean value) { - return withSource(new SimpleConfigSource(propertyName, value)); - } - - /** - * Sets the value for the config. - * - * @param propertyName name of the property - * @param value the value - * @return the {@link TestConfigBuilder} instance (for fluent API) - */ - @NonNull - public TestConfigBuilder withValue(@NonNull final String propertyName, @NonNull final Object value) { - Objects.requireNonNull(value, "value must not be null"); - return withSource(new SimpleConfigSource(propertyName, value.toString())); - } - - /** - * This method returns the {@link Configuration} instance. If the method is called for the first - * time the {@link Configuration} instance will be created. All values that have been set (see - * {@link #withValue(String, int)}) methods will be part of the config. Next to this the config - * will support all config data record types (see {@link ConfigData}) that are on the classpath. - * - * @return the created configuration - */ - @NonNull - @SuppressWarnings({"removal"}) - public Configuration getOrCreateConfig() { - try (final Locked ignore = configLock.lock()) { - if (configuration == null) { - configuration = builder.build(); - } - return configuration; - } - } - - private void checkConfigState() { - try (final Locked ignore = configLock.lock()) { - if (configuration != null) { - throw new IllegalStateException("Configuration already created!"); - } - } - } - - /** - * Adds the given config source to the builder - * - * @param configSource the config source that will be added - * @return the {@link TestConfigBuilder} instance (for fluent API) - */ - @NonNull - public TestConfigBuilder withSource(@NonNull final ConfigSource configSource) { - checkConfigState(); - builder.withSource(configSource); - return this; - } - - /** - * Adds the given config converter to the builder - * - * @param converterType the type of the config converter - * @param converter the config converter that will be added - * @return the {@link TestConfigBuilder} instance (for fluent API) - */ - @NonNull - public TestConfigBuilder withConverter( - @NonNull final Class converterType, @NonNull final ConfigConverter converter) { - checkConfigState(); - builder.withConverter(converterType, converter); - return this; - } - - /** - * Adds the given config validator to the builder - * - * @param validator the config validator that will be added - * @return the {@link TestConfigBuilder} instance (for fluent API) - */ - @NonNull - public TestConfigBuilder withValidator(@NonNull final ConfigValidator validator) { - checkConfigState(); - builder.withValidator(validator); - return this; - } - - /** - * Adds the given config data type to the builder - * - * @param type the config data type that will be added - * @param the type of the config data type - * @return the {@link TestConfigBuilder} instance (for fluent API) - */ - @NonNull - public TestConfigBuilder withConfigDataType(@NonNull final Class type) { - checkConfigState(); - builder.withConfigDataType(type); - return this; - } -} diff --git a/server/src/test/java/com/hedera/block/server/config/logging/ConfigurationLoggingImplTest.java b/server/src/test/java/com/hedera/block/server/config/logging/ConfigurationLoggingImplTest.java index cfbadf984..867f4d3d7 100644 --- a/server/src/test/java/com/hedera/block/server/config/logging/ConfigurationLoggingImplTest.java +++ b/server/src/test/java/com/hedera/block/server/config/logging/ConfigurationLoggingImplTest.java @@ -5,9 +5,9 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.fail; -import com.hedera.block.server.config.TestConfigBuilder; import com.hedera.block.server.consumer.ConsumerConfig; import com.swirlds.config.api.Configuration; +import com.swirlds.config.api.ConfigurationBuilder; import com.swirlds.config.extensions.sources.ClasspathFileConfigSource; import edu.umd.cs.findbugs.annotations.NonNull; import java.io.IOException; @@ -59,8 +59,9 @@ public void testMaxLineLength() { private static Configuration getTestConfig(@NonNull Map customProperties) throws IOException { // create test configuration - TestConfigBuilder testConfigBuilder = - new TestConfigBuilder(true).withSource(new ClasspathFileConfigSource(Path.of("app.properties"))); + ConfigurationBuilder testConfigBuilder = ConfigurationBuilder.create() + .autoDiscoverExtensions() + .withSource(new ClasspathFileConfigSource(Path.of("app.properties"))); for (Map.Entry entry : customProperties.entrySet()) { String key = entry.getKey(); @@ -69,14 +70,15 @@ private static Configuration getTestConfig(@NonNull Map customPr } testConfigBuilder = testConfigBuilder.withConfigDataType(ConsumerConfig.class); - return testConfigBuilder.getOrCreateConfig(); + return testConfigBuilder.build(); } private static Configuration getTestConfigWithSecret() throws IOException { - TestConfigBuilder testConfigBuilder = - new TestConfigBuilder(true).withSource(new ClasspathFileConfigSource(Path.of("app.properties"))); + ConfigurationBuilder testConfigBuilder = ConfigurationBuilder.create() + .autoDiscoverExtensions() + .withSource(new ClasspathFileConfigSource(Path.of("app.properties"))); testConfigBuilder = testConfigBuilder.withConfigDataType(TestSecretConfig.class); - return testConfigBuilder.getOrCreateConfig(); + return testConfigBuilder.build(); } } diff --git a/server/src/test/java/com/hedera/block/server/persistence/StreamPersistenceHandlerImplTest.java b/server/src/test/java/com/hedera/block/server/persistence/StreamPersistenceHandlerImplTest.java index 298b838c5..d3d8775d0 100644 --- a/server/src/test/java/com/hedera/block/server/persistence/StreamPersistenceHandlerImplTest.java +++ b/server/src/test/java/com/hedera/block/server/persistence/StreamPersistenceHandlerImplTest.java @@ -12,7 +12,6 @@ import com.hedera.block.server.ack.AckHandler; import com.hedera.block.server.config.BlockNodeContext; -import com.hedera.block.server.config.TestConfigBuilder; import com.hedera.block.server.events.ObjectEvent; import com.hedera.block.server.mediator.SubscriptionHandler; import com.hedera.block.server.metrics.MetricsService; @@ -23,6 +22,7 @@ import com.hedera.block.server.service.ServiceStatus; import com.hedera.hapi.block.BlockItemUnparsed; import com.swirlds.config.api.Configuration; +import com.swirlds.config.api.ConfigurationBuilder; import java.io.IOException; import java.nio.file.Path; import java.util.List; @@ -70,10 +70,10 @@ class StreamPersistenceHandlerImplTest { @BeforeEach void setUp() { - final TestConfigBuilder configBuilder = new TestConfigBuilder(PersistenceStorageConfig.class); + final ConfigurationBuilder configBuilder = ConfigurationBuilder.create().autoDiscoverExtensions(); configBuilder.withValue(PERSISTENCE_STORAGE_LIVE_ROOT_PATH_KEY, testTempDir.toString()); configBuilder.withValue(PERSISTENCE_STORAGE_ARCHIVE_ROOT_PATH_KEY, testTempDir.toString()); - final Configuration config = configBuilder.getOrCreateConfig(); + final Configuration config = configBuilder.build(); persistenceStorageConfig = config.getConfigData(PersistenceStorageConfig.class); } diff --git a/server/src/test/java/com/hedera/block/server/persistence/storage/archive/LocalGroupZipArchiveTaskTest.java b/server/src/test/java/com/hedera/block/server/persistence/storage/archive/LocalGroupZipArchiveTaskTest.java index b939c3a4c..b74756b89 100644 --- a/server/src/test/java/com/hedera/block/server/persistence/storage/archive/LocalGroupZipArchiveTaskTest.java +++ b/server/src/test/java/com/hedera/block/server/persistence/storage/archive/LocalGroupZipArchiveTaskTest.java @@ -9,7 +9,6 @@ import static org.assertj.core.api.Assertions.assertThatIOException; import com.hedera.block.common.utils.FileUtilities; -import com.hedera.block.server.config.TestConfigBuilder; import com.hedera.block.server.persistence.storage.PersistenceStorageConfig; import com.hedera.block.server.persistence.storage.path.ArchiveBlockPath; import com.hedera.block.server.persistence.storage.path.BlockAsLocalFilePathResolver; @@ -22,6 +21,7 @@ import com.hedera.pbj.runtime.UncheckedParseException; import com.hedera.pbj.runtime.io.buffer.Bytes; import com.swirlds.config.api.Configuration; +import com.swirlds.config.api.ConfigurationBuilder; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -53,12 +53,19 @@ class LocalGroupZipArchiveTaskTest { @BeforeEach void setUp() throws IOException { - final Configuration config = new TestConfigBuilder(PersistenceStorageConfig.class) + + final Configuration config = ConfigurationBuilder.create() + .autoDiscoverExtensions() .withValue(PERSISTENCE_STORAGE_COMPRESSION_TYPE, "NONE") .withValue(PERSISTENCE_STORAGE_ARCHIVE_BATCH_SIZE, String.valueOf(ARCHIVE_GROUP_SIZE)) - .withValue(PERSISTENCE_STORAGE_LIVE_ROOT_PATH_KEY, testTempDir.resolve("live")) - .withValue(PERSISTENCE_STORAGE_ARCHIVE_ROOT_PATH_KEY, testTempDir.resolve("archive")) - .getOrCreateConfig(); + .withValue( + PERSISTENCE_STORAGE_LIVE_ROOT_PATH_KEY, + testTempDir.resolve("live").toString()) + .withValue( + PERSISTENCE_STORAGE_ARCHIVE_ROOT_PATH_KEY, + testTempDir.resolve("archive").toString()) + .build(); + persistenceStorageConfig = config.getConfigData(PersistenceStorageConfig.class); // using spy for path resolver because we should test with actual logic for path resolution // also asserts would be based on the findLive/findArchive methods, which are unit tested themselves diff --git a/server/src/test/java/com/hedera/block/server/util/TestConfigUtil.java b/server/src/test/java/com/hedera/block/server/util/TestConfigUtil.java index 4913884f6..fe453585d 100644 --- a/server/src/test/java/com/hedera/block/server/util/TestConfigUtil.java +++ b/server/src/test/java/com/hedera/block/server/util/TestConfigUtil.java @@ -2,12 +2,12 @@ package com.hedera.block.server.util; import com.hedera.block.server.config.BlockNodeContext; -import com.hedera.block.server.config.TestConfigBuilder; import com.hedera.block.server.consumer.ConsumerConfig; import com.hedera.block.server.metrics.MetricsService; import com.hedera.block.server.metrics.MetricsServiceImpl; import com.swirlds.common.metrics.platform.DefaultMetricsProvider; import com.swirlds.config.api.Configuration; +import com.swirlds.config.api.ConfigurationBuilder; import com.swirlds.config.extensions.sources.ClasspathFileConfigSource; import com.swirlds.metrics.api.Metrics; import edu.umd.cs.findbugs.annotations.NonNull; @@ -28,7 +28,8 @@ public static BlockNodeContext getTestBlockNodeContext(@NonNull Map entry : customProperties.entrySet()) { @@ -39,7 +40,7 @@ public static BlockNodeContext getTestBlockNodeContext(@NonNull Map customProperties) throws IOException { - // create test configuration - TestConfigBuilder testConfigBuilder = new TestConfigBuilder(true) + + ConfigurationBuilder configurationBuilder = ConfigurationBuilder.create() + .autoDiscoverExtensions() .withSource(new ClasspathFileConfigSource(Path.of(TEST_APP_PROPERTIES_FILE))); for (Map.Entry entry : customProperties.entrySet()) { String key = entry.getKey(); String value = entry.getValue(); - testConfigBuilder = testConfigBuilder.withSource(new SimpleConfigSource(key, value).withOrdinal(500)); + configurationBuilder.withSource(new SimpleConfigSource(key, value).withOrdinal(500)); } - return testConfigBuilder.getOrCreateConfig(); + return configurationBuilder.build(); } public static Configuration getTestConfiguration() throws IOException { diff --git a/simulator/src/test/java/com/hedera/block/simulator/config/TestConfigBuilder.java b/simulator/src/test/java/com/hedera/block/simulator/config/TestConfigBuilder.java deleted file mode 100644 index 8c167cfd6..000000000 --- a/simulator/src/test/java/com/hedera/block/simulator/config/TestConfigBuilder.java +++ /dev/null @@ -1,225 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -package com.hedera.block.simulator.config; - -import com.swirlds.common.config.singleton.ConfigurationHolder; -import com.swirlds.common.threading.locks.AutoClosableLock; -import com.swirlds.common.threading.locks.Locks; -import com.swirlds.common.threading.locks.locked.Locked; -import com.swirlds.config.api.ConfigData; -import com.swirlds.config.api.Configuration; -import com.swirlds.config.api.ConfigurationBuilder; -import com.swirlds.config.api.converter.ConfigConverter; -import com.swirlds.config.api.source.ConfigSource; -import com.swirlds.config.api.validation.ConfigValidator; -import com.swirlds.config.extensions.sources.SimpleConfigSource; -import edu.umd.cs.findbugs.annotations.NonNull; -import edu.umd.cs.findbugs.annotations.Nullable; -import java.util.Objects; - -/** - * Helper for use the config in test and change the config for specific tests. Instance can be used - * per class or per test. - */ -public class TestConfigBuilder { - - private final AutoClosableLock configLock = Locks.createAutoLock(); - - private Configuration configuration; - - private final ConfigurationBuilder builder; - - /** - * Creates a new instance and automatically registers all config data records (see {@link - * ConfigData}) on classpath / modulepath that are part of the packages {@code com.swirlds} and - * {@code com.hedera}. - */ - public TestConfigBuilder() { - this(true); - } - - /** - * Creates a new instance and automatically registers all given config data records. This call - * will not do a class scan for config data records on classpath / modulepath like some of the - * other constructors do. - * - * @param dataTypes - */ - public TestConfigBuilder(@Nullable final Class dataTypes) { - this(false); - if (dataTypes != null) { - this.builder.withConfigDataTypes(dataTypes); - } - } - - /** - * Creates a new instance and automatically registers all config data records (see {@link - * ConfigData}) on classpath / modulepath that are part of the packages {@code com.swirlds} and - * {@code com.hedera}. if the {@code registerAllTypes} param is true. - * - * @param registerAllTypes if true all config data records on classpath will automatically be - * registered - */ - public TestConfigBuilder(final boolean registerAllTypes) { - if (registerAllTypes) { - this.builder = ConfigurationBuilder.create().autoDiscoverExtensions(); - } else { - this.builder = ConfigurationBuilder.create(); - } - } - - /** - * Sets the value for the config. - * - * @param propertyName name of the property - * @param value the value - * @return the {@link TestConfigBuilder} instance (for fluent API) - */ - @NonNull - public TestConfigBuilder withValue(@NonNull final String propertyName, @Nullable final String value) { - return withSource(new SimpleConfigSource(propertyName, value)); - } - - /** - * Sets the value for the config. - * - * @param propertyName name of the property - * @param value the value - * @return the {@link TestConfigBuilder} instance (for fluent API) - */ - @NonNull - public TestConfigBuilder withValue(@NonNull final String propertyName, final int value) { - return withSource(new SimpleConfigSource(propertyName, value)); - } - - /** - * Sets the value for the config. - * - * @param propertyName name of the property - * @param value the value - * @return the {@link TestConfigBuilder} instance (for fluent API) - */ - @NonNull - public TestConfigBuilder withValue(@NonNull final String propertyName, final double value) { - return withSource(new SimpleConfigSource(propertyName, value)); - } - - /** - * Sets the value for the config. - * - * @param propertyName name of the property - * @param value the value - * @return the {@link TestConfigBuilder} instance (for fluent API) - */ - @NonNull - public TestConfigBuilder withValue(@NonNull final String propertyName, final long value) { - return withSource(new SimpleConfigSource(propertyName, value)); - } - - /** - * Sets the value for the config. - * - * @param propertyName name of the property - * @param value the value - * @return the {@link TestConfigBuilder} instance (for fluent API) - */ - @NonNull - public TestConfigBuilder withValue(@NonNull final String propertyName, final boolean value) { - return withSource(new SimpleConfigSource(propertyName, value)); - } - - /** - * Sets the value for the config. - * - * @param propertyName name of the property - * @param value the value - * @return the {@link TestConfigBuilder} instance (for fluent API) - */ - @NonNull - public TestConfigBuilder withValue(@NonNull final String propertyName, @NonNull final Object value) { - Objects.requireNonNull(value, "value must not be null"); - return withSource(new SimpleConfigSource(propertyName, value.toString())); - } - - /** - * This method returns the {@link Configuration} instance. If the method is called for the first - * time the {@link Configuration} instance will be created. All values that have been set (see - * {@link #withValue(String, int)}) methods will be part of the config. Next to this the config - * will support all config data record types (see {@link ConfigData}) that are on the classpath. - * - * @return the created configuration - */ - @NonNull - @SuppressWarnings({"removal"}) - public Configuration getOrCreateConfig() { - try (final Locked ignore = configLock.lock()) { - if (configuration == null) { - configuration = builder.build(); - ConfigurationHolder.getInstance().setConfiguration(configuration); - } - return configuration; - } - } - - private void checkConfigState() { - try (final Locked ignore = configLock.lock()) { - if (configuration != null) { - throw new IllegalStateException("Configuration already created!"); - } - } - } - - /** - * Adds the given config source to the builder - * - * @param configSource the config source that will be added - * @return the {@link TestConfigBuilder} instance (for fluent API) - */ - @NonNull - public TestConfigBuilder withSource(@NonNull final ConfigSource configSource) { - checkConfigState(); - builder.withSource(configSource); - return this; - } - - /** - * Adds the given config converter to the builder - * - * @param converterType the type of the config converter - * @param converter the config converter that will be added - * @return the {@link TestConfigBuilder} instance (for fluent API) - */ - @NonNull - public TestConfigBuilder withConverter( - @NonNull final Class converterType, @NonNull final ConfigConverter converter) { - checkConfigState(); - builder.withConverter(converterType, converter); - return this; - } - - /** - * Adds the given config validator to the builder - * - * @param validator the config validator that will be added - * @return the {@link TestConfigBuilder} instance (for fluent API) - */ - @NonNull - public TestConfigBuilder withValidator(@NonNull final ConfigValidator validator) { - checkConfigState(); - builder.withValidator(validator); - return this; - } - - /** - * Adds the given config data type to the builder - * - * @param type the config data type that will be added - * @param the type of the config data type - * @return the {@link TestConfigBuilder} instance (for fluent API) - */ - @NonNull - public TestConfigBuilder withConfigDataType(@NonNull final Class type) { - checkConfigState(); - builder.withConfigDataType(type); - return this; - } -} From ab846e5b0763cb24986c09c8882498709a5fd422 Mon Sep 17 00:00:00 2001 From: "Joseph S." <121976561+jsync-swirlds@users.noreply.github.com> Date: Mon, 3 Mar 2025 16:01:51 -0700 Subject: [PATCH 7/7] chore: Document some thoughts for nano-service approach (#691) Signed-off-by: Joseph Sinclair <121976561+jsync-swirlds@users.noreply.github.com> --- docs/design/Nano-Service-Approach.md | 126 ++++++++++++++++++ .../assets/Block-Node-Nano-Services.svg | 1 + 2 files changed, 127 insertions(+) create mode 100644 docs/design/Nano-Service-Approach.md create mode 100644 docs/design/assets/Block-Node-Nano-Services.svg diff --git a/docs/design/Nano-Service-Approach.md b/docs/design/Nano-Service-Approach.md new file mode 100644 index 000000000..745326fb7 --- /dev/null +++ b/docs/design/Nano-Service-Approach.md @@ -0,0 +1,126 @@ +# Block Node Nano-Service Approach + +## Abstract + +To date, block node has been developed under pressure and with changing, incomplete, or inaccurate requirements. +As a result, the system is tightly interconnected, and suffers from a difficulty making changes to +one segment of the system without also impacting unrelated segments. To address this, and ensure +the Block Node is able to be extended, enhanced, and deployed in the manner required for all +current identified usage, a modified structure of the system is herein detailed. + +## Revised Diagram + +![Module/Service Diagram](assets/Block-Node-Nano-Services.svg) + +## Definitions + +
+
Event
+
A Java object defined by the messaging service that enables each other service +to publish a service-defined object with content specific to that service. Note, +the name of this object is not defined in this document. "Event" is a generic term.
+
Service
+
A Java module that is deployed with a particular installation of the Hiero +Block Node. In most cases these modules are housed in independent jars to make +adding and removing services (in a custom deployment) easier.
+
+ +## Core Concepts + +1. Helidon and API objects are restricted to the API layer. + * The less we flow these externally defined interfaces and classes through + the system, the more easily we can potentially make outward facing API + changes without reworking the internal design. +2. Most services are not required to be present in every deployment of the block node. +3. No service should depend on classes or interfaces from another service. + * That service might not be deployed, and each service should be removable + without breaking other services. The exception is the Messaging service. + * To this end, services should be independent modules with clearly defined + and carefully controlled interactions. +4. Two services are required for all deployments, Messaging and Status + * Only Messaging should offer any internal API at all. + * Basically, Messaging is where data and events are published (presumably + via LMAX Disruptor instances) among other services. + * The Status service is only required because it is specified as always + present for a block node client to query via gRPC API. + * The Messaging service should _not_ have any external (i.e. gRPC) API. + * We must remain vigilant to avoid packing these two services with interfaces or extra classes. + * These services should be as slim as possible, and interactions between + services should be based on a very limited set of `Record` messages ("Events") + that are passed between services (blindly) by the Messaging service + rather than interfaces or direct method calls. +5. There is an assumption in this approach that Messaging offers both "push" + and "pull" options for receiving messages, and each service may choose the + most appropriate interaction for that specific service. + * A persistence service, for instance, might use "push" for simplicity and + because it does not benefit from holding items within Messaging, but + a streaming client service might use "pull" in order to allow each of + many remote clients to be receiving data at slightly varying rates and + more easily switch from live to historical and back if a particular + client falls behind and later "catches up". +6. Most services both publish and observe the service "event" messages + * By listening for events, any service can react to changes in any other + service, but also behave reasonably when another service does not exist. + * Publishing an event (rather than calling an API) makes it easy for each + service to focus entirely on its own function and not try to work out the + highly complex possible interactions with all other possible services. + * Some services (e.g. Archive service) won't make sense if _nothing_ publishes + a particular event, but even then the service need not be concerned with + the how/what/why of a event, and need only react if and when a event is + encountered with the relevant type and content. +7. Many services will _also_ listen to the main data messages (List) + which is the primary data flowing through the system. + * Note that Publisher service is also not required, so this flow of data might + be empty, or might be produced from some other source. + * There _might_ also be a stream of "historical" blocks used to serve client + requests for those blocks. This is still to be determined. +8. Configuration for a service is entirely restricted to that service, and does + not determine what "version" of a service or whether a service is running. + * It _might_ assist multiple loaded "versions" to identify a conflict. +9. The JVM `ServiceLoader` is used to load every service that is present, this + may include multiple services of the same "type" (e.g. multiple archive + services, multiple persistence services, etc...). + * It is up to the particular services to ensure that either multiple + different versions cooperate properly or an error is published on + startup that multiple incompatible services are loaded. Generally it's + cleanest if multiple services of the same type are able to work + independently without issues. If that isn't possible, a service- + specific configuration is a good alternative. + +## Expected Benefits + +1. Services are decomposed to small units, often what is thought of as a single + process is accomplished by multiple nano-services. This makes each such + service both simple and focused. This also makes adding, removing, and + modifying these services much easier and faster. + * It's also much easier to test services with nothing more than a mock of the + "Messaging" service; which further improves velocity. +2. Composing services may be easier to reason about than composing interfaces, + and systems composed of independent services are easier to modify and revise + than systems with many interacting method calls or complex module + interactions. +3. It is much easier to reason about concurrency for a single focused service + than it is for a larger and more interconnected set of components. + +## Considerations and Possible Concerns + +1. Sending messages between services is not as efficient as calling a method. + * This is true, but publishing a message consumed by an unknown set of (potentially) + several services is significantly more efficient than trying to manage an uncertain + (and possibly large) number of direct method calls. We are electing to + prioritize emergent behavior and capability over direct-call efficiency. +2. Some services may not make any sense without other services. For example, + a Content Proof service might not be able to function without a State + Management service and/or State Snapshot service. + * If a particular service requires other services, it should document the + expected events (e.g. publish "Need Snapshot For Instant{date/time}" and + expect "Deliver Snapshot For Instant{date1/time1}") and also document + behavior if the response-type event is not published. + * Every service should function, at least to the level of not throwing + exceptions, regardless of which other services are, or are not, present. + * While a service may require certain _messages_ to function correctly + (e.g. a "Deliver Snapshot For Instant..." message in the example above), + the service _must not_ concern itself with _what_ produces those messages + or _how_. This ensures that all services function as intended even if + other services are replaced with completely different, but _compatible_ + services. diff --git a/docs/design/assets/Block-Node-Nano-Services.svg b/docs/design/assets/Block-Node-Nano-Services.svg new file mode 100644 index 000000000..5701d930a --- /dev/null +++ b/docs/design/assets/Block-Node-Nano-Services.svg @@ -0,0 +1 @@ + \ No newline at end of file