-
Notifications
You must be signed in to change notification settings - Fork 2.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Txpool v2 features for futures connections with other modules #2216
Merged
Merged
Changes from all commits
Commits
Show all changes
183 commits
Select commit
Hold shift + click to select a range
2e07d37
Add skeleton txpool v2
AurelienFT 4cbb11c
Add basic interfaces and retrieve some functionnalities of the old pool.
AurelienFT bef4aff
Add all machinery to make the tests
AurelienFT 552af83
Add some logic that needs to be moved behind abstraction
AurelienFT 8d39499
Add all storages for transactions and clean code a bit
AurelienFT 3d1a1bb
Merge branch 'master' into txpool-v2
AurelienFT 3d65076
Fix compilation errors and add selection mecanism
AurelienFT 19830cb
Start thinking about traits
AurelienFT 795567e
Add all abstractions in txpool to clean code
AurelienFT 67afb9d
Split all logic across implementations and uncomment half of the tests
AurelienFT b956e2c
Add all tests
AurelienFT 9ed577e
Fmt + toml lint + spellcheck
AurelienFT 29ec06d
Resolves most of the TODO, remove unwrap and add test
AurelienFT 9a22983
Document and allow warnings on dead code/unused
AurelienFT ca38a25
Merge branch 'master' into txpool-v2
AurelienFT fe9e995
fix fuel-core-type usage in ttxpool v2
AurelienFT 34c7e07
Remove usage of txpool v2 in fuel-core
AurelienFT 4576797
fmt fix
AurelienFT c8e86ec
Don't allow dependencies on output and change and specify todos
AurelienFT 16a7e8f
Rework dependency between components
AurelienFT 60ada65
Simplify usage of the db trait
AurelienFT 0cf8835
update graph cumultative gas and tip
AurelienFT b328bc8
Docs fixes and config renaming
AurelienFT 0d69dc1
fmt
AurelienFT 29dd130
start definition of the pool
AurelienFT 75a9180
Use persistant storage instead of db and reuse a view provider
AurelienFT 4049dac
Merge branch 'txpool-v2' into txpool-v2-api
AurelienFT dd6f7c1
Add insertion skeleton
AurelienFT 87e5027
Fix comments in tests
AurelienFT 460beef
Add all the verifications in order. Still some todo and compil errors
AurelienFT 75fb598
Fix compil errors
AurelienFT 4e3e3ce
Update components trait to be more flexible.
AurelienFT 826f13e
Update tests and make the insert function more readable
AurelienFT bafbf75
remove over constraint on trait and rename a test.
AurelienFT ed2302a
Merge branch 'master' into txpool-v2
AurelienFT 054f648
Merge branch 'txpool-v2' into txpool-v2-api
AurelienFT a7666fc
Finish verification on all inputs
AurelienFT 4426134
fix verifications to make no copy
AurelienFT 86a7c86
Reorganize insertion and opti some code. Start rework of tests.
AurelienFT 96e0cc9
Update all the tests
AurelienFT cb635e8
Add heavy async work for insert
AurelienFT d4ebf3c
Change some documentation and remove a lot of dead code.
AurelienFT 45d5296
Merge branch 'master' into txpool-v2
AurelienFT 1c1e5db
Update cargo lock
AurelienFT e379a0c
Merge branch 'txpool-v2' into txpool-v2-api
AurelienFT e7dc924
Clean up of the code
AurelienFT c12ee38
Update changelog
AurelienFT 4f87fbd
fix clippy
AurelienFT fb83ef2
Add interface to get the executable transactions
AurelienFT f10ca86
Add new transactions notifier
AurelienFT a3e72fd
Add code in case of block import
AurelienFT 6e5c7f8
Merge branch 'master' into txpool-v2
AurelienFT 3f11941
Merge branch 'txpool-v2' into txpool-v2-api
AurelienFT e53ea28
Merge branch 'txpool-v2-api' into txpool-v2-block-producer-importer
AurelienFT bec7036
Add bunch of p2p related connexions and split shared state and servic…
AurelienFT 2e739a1
Add arc transaction in storage and broadcast tx
AurelienFT 2a5aabd
Merge branch 'master' into txpool-v2
AurelienFT e78544f
Fix changelog
AurelienFT 697cf4c
Merge branch 'txpool-v2' into txpool-v2-api
AurelienFT fbdd0d5
Merge branch 'txpool-v2-api' into txpool-v2-block-producer-importer
AurelienFT 430a2c8
Update changelog
AurelienFT 350cdbf
Add clippy allow
AurelienFT dd7c095
Merge branch 'master' into txpool-v2
AurelienFT fdd5f8a
Merge branch 'txpool-v2' into txpool-v2-api
AurelienFT df2978a
Merge branch 'txpool-v2-api' into txpool-v2-block-producer-importer
AurelienFT 14b9b53
Update crates/services/txpool_v2/src/lib.rs
AurelienFT 978d0b8
remove unused config
AurelienFT 68b1157
Remove unused parameters and secure the collisions subfields
AurelienFT 1074e5a
Rename functions add checks, and fix clippy
AurelienFT f89174f
fmt
AurelienFT 3ddea7e
Change max txs in chain rules
AurelienFT a5ff2ab
fmt
AurelienFT dd9ef6e
Moved collisions removal after checks
AurelienFT f0476e2
Add some caches to avoid more iteration and fix collission taken as d…
AurelienFT 2f5a199
Merge branch 'master' into txpool-v2
AurelienFT ade8569
Split two functions and optimize iterator returns
AurelienFT 6beb83d
Merge branch 'master' into txpool-v2
AurelienFT 3dde832
elllude lifetime
AurelienFT 72add0f
Merge branch 'txpool-v2' into txpool-v2-api
AurelienFT 8cd8d48
Merge branch 'txpool-v2-api' into txpool-v2-block-producer-importer
AurelienFT cf9e9eb
Change insertion checks to be simplified
AurelienFT 1c59fc7
Simplified insert
AurelienFT e859b60
Fix collision system to allow multiple collision to the same tx
AurelienFT 1f8aaf8
Fix some node that wasn't removed.
AurelienFT c7b3a29
format
AurelienFT 1eb58a9
Merge branch 'txpool-v2-api' into txpool-v2-block-producer-importer
AurelienFT 8ed3a5b
Txpool TTL (#2217)
AurelienFT bb739d3
fix changelog
AurelienFT 0ebfc5c
fix max size algo and add tests
AurelienFT 0614084
Merge branch 'txpool-v2-api' into txpool-v2-block-producer-importer
AurelienFT d5ddc3c
Add the update sender along with the tests
AurelienFT 4c542d9
add all p2p and service tests, not working yet, need to adapt the con…
AurelienFT c4690d7
Finalize all links and add tests
AurelienFT 4de9f9e
Remove allow unused and remove all dead code
AurelienFT 5f81c09
fmt toml
AurelienFT 82c9dd9
Update crates/services/txpool_v2/src/config.rs
AurelienFT 70a45e9
Update crates/services/txpool_v2/src/config.rs
AurelienFT 677a130
Change collision manager and add more info in error
AurelienFT 26871c8
Update pool check size
AurelienFT 76b2af4
Move logic from pool to storage
AurelienFT 13e6990
fmt and clippy
AurelienFT 149902a
Merge branch 'txpool-v2-api' into txpool-v2-block-producer-importer
AurelienFT 6249e5d
remove unused stream predicate verif
AurelienFT c391732
Merge branch 'txpool-v2-api' into txpool-v2-block-producer-importer
AurelienFT 65cbc14
format
AurelienFT 0543f60
Improve error type
AurelienFT f5ef031
update review comments
AurelienFT d6dea78
Merge branch 'txpool-v2' into txpool-v2-api
AurelienFT 2bd0382
Merge branch 'master' into txpool-v2
AurelienFT 83c56ae
Change way to get less worth it transactions
AurelienFT 4e77350
Merge branch 'txpool-v2-api' into txpool-v2-block-producer-importer
AurelienFT de44984
Fix clippy
AurelienFT e516353
Merge branch 'txpool-v2-api' into txpool-v2-block-producer-importer
AurelienFT 27e7001
Split the two heavy tasks to different pools
AurelienFT e9c78fc
remove wrong debug assert
AurelienFT f955ee5
Merge branch 'txpool-v2' of github.com:FuelLabs/fuel-core into txpool-v2
AurelienFT 2edff72
Merge branch 'txpool-v2' into txpool-v2-api
AurelienFT f632f66
Merge branch 'txpool-v2-api' into txpool-v2-block-producer-importer
AurelienFT 4f7b3fd
fix typo
AurelienFT 3be0fc7
Remove unused error in storage and change collisions to hashset.
AurelienFT 24cc034
change graph information stored in storedata
AurelienFT aa8cb24
Fix remove of a cache done in a case where it's not relevant
AurelienFT 0bbdaf5
Make sure to edit all dependencies when we remove a dependent subtree.
AurelienFT c128c75
Txpool v2 insertion (#2193)
AurelienFT aeb2935
Minimized the number of `Result` in the code in places where we can't…
xgreenx 8a746bf
Added fuzzer for TxPoolV1 and TxPoolV2 to create dependent graphs. It…
xgreenx 0fcb185
Applied comments from the review
xgreenx 88cec23
Make clippy happy
xgreenx 47ebb4c
Moved the logic of collision and depdednencies verificaiton to the po…
xgreenx eed0d13
Revert rocksdb
xgreenx d88a016
Fix tests
xgreenx 2fd7c15
Reuse direct dedpednencies.
xgreenx 99da36b
Merge branch 'refs/heads/master' into txpool-v2
xgreenx eef1db8
Merge branch 'txpool-v2' into txpool-v2-block-producer-importer
AurelienFT a540eda
Reject transactions that creates diamond dependencies. It allows simp…
xgreenx b25b832
Make limits less strict for fuzzer. It is okay since we don't need to…
xgreenx 07ff9ef
Fix a lot of cimpil error post merge
AurelienFT e880427
Merge branch 'txpool-v2' into txpool-v2-block-producer-importer
AurelienFT 82fa757
Fix all compil errors and conflicts with arc
AurelienFT 04d7cc5
add checks cfg on unused code
AurelienFT acf0ab5
add checks cfg on unused code
AurelienFT 15d1bc3
Merge branch 'txpool-v2' into txpool-v2-block-producer-importer
AurelienFT 6df300a
Applied comments from the PR
xgreenx d16424c
Added a comment for stabiltiy test
xgreenx 6fe6d98
Merge branch 'master' into txpool-v2
xgreenx 5def1d3
update tests following review
AurelienFT 3b7fc49
remove unused and change order verif
AurelienFT 692a5f1
Merge branch 'txpool-v2' into txpool-v2-block-producer-importer
AurelienFT 48090ea
fix tests
AurelienFT 0db90fc
Merge branch 'txpool-v2' into txpool-v2-block-producer-importer
AurelienFT 1cd89e4
Merge branch 'master' into txpool-v2
AurelienFT 6e27909
Change shared state to use message passing instead of rwlock
AurelienFT 1a96d77
update insert return type
AurelienFT fb7ae3d
Merge branch 'txpool-v2' into txpool-v2-block-producer-importer
AurelienFT 7917cb1
Merge branch 'master' into txpool-v2-block-producer-importer
AurelienFT 5f48e87
Fix compil error
AurelienFT 51a02a7
Re-add skipped transaction error propagation
AurelienFT 7a365b5
Fix spelling and ordering toml
AurelienFT f62ea4a
Add gas verif in selection
AurelienFT a4e2d01
Add removal of coin dependents transactions
AurelienFT 0087cf2
Merge branch 'master' into txpool-v2-block-producer-importer
AurelienFT 4f76445
lower the stability rounds to help CI.
AurelienFT 79cf576
fix test find
AurelienFT ab6aaba
Merge branch 'master' into txpool-v2-block-producer-importer
AurelienFT 4542511
Add mock db to predicate verif in tests
AurelienFT 2b038ab
Feature/refactoring service txpool v2 (#2307)
AurelienFT 918f377
Merge branch 'master' into txpool-v2-block-producer-importer
AurelienFT 6dbc31b
Merge branch 'refs/heads/master' into txpool-v2-block-producer-importer
xgreenx 02cc19e
remove unused test file
AurelienFT b9c9d95
Merge remote-tracking branch 'origin/txpool-v2-block-producer-importe…
xgreenx 8dfbf99
Merge branch 'master' into txpool-v2-block-producer-importer
AurelienFT d683d93
Merge remote-tracking branch 'origin/txpool-v2-block-producer-importe…
xgreenx dbc9206
Shuffle code)
xgreenx 9d73f89
fix compilation txpool
AurelienFT f28da55
Merge branch 'txpool-v2-block-producer-importer' of github.com:FuelLa…
AurelienFT 4e79e4a
Implemented sync and async processor. Used both in the TxPool to mana…
xgreenx d3dd371
Make CI happy
xgreenx 68df4bc
Mia
xgreenx 71213d9
fix tests old tx pool
AurelienFT 0533ee1
Fix wrong comparison max gas
AurelienFT feda383
Merge branch 'master' into txpool-v2-block-producer-importer
AurelienFT badb310
Change type to pub(crate)
AurelienFT 6d9c468
Merge branch 'txpool-v2-block-producer-importer' of github.com:FuelLa…
AurelienFT File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,258 @@ | ||
use std::{ | ||
future::Future, | ||
sync::Arc, | ||
}; | ||
use tokio::{ | ||
runtime, | ||
sync::{ | ||
OwnedSemaphorePermit, | ||
Semaphore, | ||
}, | ||
}; | ||
|
||
/// A processor that can execute async tasks with a limit on the number of tasks that can be | ||
/// executed concurrently. | ||
pub struct AsyncProcessor { | ||
semaphore: Arc<Semaphore>, | ||
thread_pool: runtime::Runtime, | ||
} | ||
|
||
/// A reservation for a task to be executed by the `AsyncProcessor`. | ||
pub struct AsyncReservation(OwnedSemaphorePermit); | ||
|
||
/// Out of capacity error. | ||
#[derive(Debug, PartialEq, Eq)] | ||
pub struct OutOfCapacity; | ||
|
||
impl AsyncProcessor { | ||
/// Create a new `AsyncProcessor` with the given number of threads and the number of pending | ||
/// tasks. | ||
pub fn new( | ||
number_of_threads: usize, | ||
number_of_pending_tasks: usize, | ||
) -> anyhow::Result<Self> { | ||
let thread_pool = runtime::Builder::new_multi_thread() | ||
.worker_threads(number_of_threads) | ||
.enable_all() | ||
.build() | ||
.map_err(|e| anyhow::anyhow!("Failed to create a tokio pool: {}", e))?; | ||
let semaphore = Arc::new(Semaphore::new(number_of_pending_tasks)); | ||
Ok(Self { | ||
thread_pool, | ||
semaphore, | ||
}) | ||
} | ||
|
||
/// Reserve a slot for a task to be executed. | ||
pub fn reserve(&self) -> Result<AsyncReservation, OutOfCapacity> { | ||
let permit = self.semaphore.clone().try_acquire_owned(); | ||
if let Ok(permit) = permit { | ||
Ok(AsyncReservation(permit)) | ||
} else { | ||
Err(OutOfCapacity) | ||
} | ||
} | ||
|
||
/// Spawn a task with a reservation. | ||
pub fn spawn_reserved<F>(&self, reservation: AsyncReservation, future: F) | ||
where | ||
F: Future<Output = ()> + Send + 'static, | ||
{ | ||
let permit = reservation.0; | ||
self.thread_pool.spawn(async move { | ||
let _drop = permit; | ||
future.await | ||
}); | ||
} | ||
|
||
/// Tries to spawn a task. If the task cannot be spawned, returns an error. | ||
pub fn try_spawn<F>(&self, future: F) -> Result<(), OutOfCapacity> | ||
where | ||
F: Future<Output = ()> + Send + 'static, | ||
{ | ||
let reservation = self.reserve()?; | ||
self.spawn_reserved(reservation, future); | ||
Ok(()) | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
#[allow(clippy::bool_assert_comparison)] | ||
mod tests { | ||
use super::*; | ||
use std::{ | ||
thread::sleep, | ||
time::Duration, | ||
}; | ||
use tokio::time::Instant; | ||
|
||
#[test] | ||
fn one_spawn_single_tasks_works() { | ||
// Given | ||
let number_of_pending_tasks = 1; | ||
let heavy_task_processor = | ||
AsyncProcessor::new(1, number_of_pending_tasks).unwrap(); | ||
|
||
// When | ||
let (sender, mut receiver) = tokio::sync::oneshot::channel(); | ||
let result = heavy_task_processor.try_spawn(async move { | ||
sender.send(()).unwrap(); | ||
}); | ||
|
||
// Then | ||
assert_eq!(result, Ok(())); | ||
sleep(Duration::from_secs(1)); | ||
receiver.try_recv().unwrap(); | ||
} | ||
|
||
#[test] | ||
fn second_spawn_fails_when_limit_is_one_and_first_in_progress() { | ||
// Given | ||
let number_of_pending_tasks = 1; | ||
let heavy_task_processor = | ||
AsyncProcessor::new(1, number_of_pending_tasks).unwrap(); | ||
let first_spawn_result = heavy_task_processor.try_spawn(async move { | ||
sleep(Duration::from_secs(1)); | ||
}); | ||
assert_eq!(first_spawn_result, Ok(())); | ||
|
||
// When | ||
let second_spawn_result = heavy_task_processor.try_spawn(async move { | ||
sleep(Duration::from_secs(1)); | ||
}); | ||
|
||
// Then | ||
assert_eq!(second_spawn_result, Err(OutOfCapacity)); | ||
} | ||
|
||
#[test] | ||
fn second_spawn_works_when_first_is_finished() { | ||
let number_of_pending_tasks = 1; | ||
let heavy_task_processor = | ||
AsyncProcessor::new(1, number_of_pending_tasks).unwrap(); | ||
|
||
// Given | ||
let (sender, receiver) = tokio::sync::oneshot::channel(); | ||
let first_spawn = heavy_task_processor.try_spawn(async move { | ||
sleep(Duration::from_secs(1)); | ||
sender.send(()).unwrap(); | ||
}); | ||
assert_eq!(first_spawn, Ok(())); | ||
futures::executor::block_on(async move { | ||
receiver.await.unwrap(); | ||
}); | ||
|
||
// When | ||
let second_spawn = heavy_task_processor.try_spawn(async move { | ||
sleep(Duration::from_secs(1)); | ||
}); | ||
|
||
// Then | ||
assert_eq!(second_spawn, Ok(())); | ||
} | ||
|
||
#[test] | ||
fn can_spawn_10_tasks_when_limit_is_10() { | ||
// Given | ||
let number_of_pending_tasks = 10; | ||
let heavy_task_processor = | ||
AsyncProcessor::new(1, number_of_pending_tasks).unwrap(); | ||
|
||
for _ in 0..number_of_pending_tasks { | ||
// When | ||
let result = heavy_task_processor.try_spawn(async move { | ||
tokio::time::sleep(Duration::from_secs(1)).await; | ||
}); | ||
|
||
// Then | ||
assert_eq!(result, Ok(())); | ||
} | ||
} | ||
|
||
#[test] | ||
fn executes_10_tasks_for_10_seconds_with_one_thread() { | ||
// Given | ||
let number_of_pending_tasks = 10; | ||
let number_of_threads = 1; | ||
let heavy_task_processor = | ||
AsyncProcessor::new(number_of_threads, number_of_pending_tasks).unwrap(); | ||
|
||
// When | ||
let (broadcast_sender, mut broadcast_receiver) = | ||
tokio::sync::broadcast::channel(1024); | ||
let instant = Instant::now(); | ||
for _ in 0..number_of_pending_tasks { | ||
let broadcast_sender = broadcast_sender.clone(); | ||
let result = heavy_task_processor.try_spawn(async move { | ||
sleep(Duration::from_secs(1)); | ||
broadcast_sender.send(()).unwrap(); | ||
}); | ||
assert_eq!(result, Ok(())); | ||
} | ||
drop(broadcast_sender); | ||
|
||
// Then | ||
futures::executor::block_on(async move { | ||
while broadcast_receiver.recv().await.is_ok() {} | ||
assert!(instant.elapsed() >= Duration::from_secs(10)); | ||
}); | ||
} | ||
|
||
#[test] | ||
fn executes_10_tasks_for_2_seconds_with_10_thread() { | ||
// Given | ||
let number_of_pending_tasks = 10; | ||
let number_of_threads = 10; | ||
let heavy_task_processor = | ||
AsyncProcessor::new(number_of_threads, number_of_pending_tasks).unwrap(); | ||
|
||
// When | ||
let (broadcast_sender, mut broadcast_receiver) = | ||
tokio::sync::broadcast::channel(1024); | ||
let instant = Instant::now(); | ||
for _ in 0..number_of_pending_tasks { | ||
let broadcast_sender = broadcast_sender.clone(); | ||
let result = heavy_task_processor.try_spawn(async move { | ||
sleep(Duration::from_secs(1)); | ||
broadcast_sender.send(()).unwrap(); | ||
}); | ||
assert_eq!(result, Ok(())); | ||
} | ||
drop(broadcast_sender); | ||
|
||
// Then | ||
futures::executor::block_on(async move { | ||
while broadcast_receiver.recv().await.is_ok() {} | ||
assert!(instant.elapsed() <= Duration::from_secs(2)); | ||
}); | ||
} | ||
|
||
#[test] | ||
fn executes_10_tasks_for_2_seconds_with_1_thread() { | ||
// Given | ||
let number_of_pending_tasks = 10; | ||
let number_of_threads = 10; | ||
let heavy_task_processor = | ||
AsyncProcessor::new(number_of_threads, number_of_pending_tasks).unwrap(); | ||
|
||
// When | ||
let (broadcast_sender, mut broadcast_receiver) = | ||
tokio::sync::broadcast::channel(1024); | ||
let instant = Instant::now(); | ||
for _ in 0..number_of_pending_tasks { | ||
let broadcast_sender = broadcast_sender.clone(); | ||
let result = heavy_task_processor.try_spawn(async move { | ||
tokio::time::sleep(Duration::from_secs(1)).await; | ||
broadcast_sender.send(()).unwrap(); | ||
}); | ||
assert_eq!(result, Ok(())); | ||
} | ||
drop(broadcast_sender); | ||
|
||
// Then | ||
futures::executor::block_on(async move { | ||
while broadcast_receiver.recv().await.is_ok() {} | ||
assert!(instant.elapsed() <= Duration::from_secs(2)); | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the purpose of this aliasing dance? We import the crate under a type alias and then alias it to
_
. This feels weird, but I guess we must achieve something by doing this.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@xgreenx
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was done to enable feature by default during testing