Skip to content
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

Add API endpoints to ConfigDBConnector to support pre-loading data without blackout #587

Merged
merged 8 commits into from
Mar 30, 2022

Conversation

alexrallen
Copy link
Contributor

Currently if someone wishes to use ConfigDBConnector to operate on updates coming from CONFIG_DB AND they wish to pull all the initial data from the table to initialize their only option is to pull the data and then run the listen() method on ConfigDBConnector.

This creates a "blackout" period where between the time the tables are downloaded and the listen() method is called, any new updates to CONFIG_DB will not be handled.

To resolve this I have changed two things in ConfigDBConnector. All of which are 100% backwards compatible...

  1. I split listen() into listen() and process() where listen() may now be called with start=False as an argument which does not start immediately processing updates from CONFIG_DB and calling handlers. This allows you to call listen() first and then download table data and then call process() to start processing updates. This way no updates will be missed as they will be queued by redis while the table data is being downloaded by the consumer.
  2. I added a cache argument to process in which you pass any initial table data your system is operating on. When a table update is processed the system checks if that keys value is different than what is stored in the cache (if it is present) and only fires the callback handler in the case that the data has changes (added / deleted / updated). This prevents the same data from being processed multiple times.

dgsudharsan
dgsudharsan previously approved these changes Mar 7, 2022
renukamanavalan
renukamanavalan previously approved these changes Mar 8, 2022
common/configdb.h Outdated Show resolved Hide resolved
common/configdb.h Outdated Show resolved Hide resolved
common/configdb.h Outdated Show resolved Hide resolved
common/configdb.h Outdated Show resolved Hide resolved
common/configdb.h Outdated Show resolved Hide resolved
common/configdb.h Outdated Show resolved Hide resolved
@alexrallen alexrallen dismissed stale reviews from renukamanavalan and dgsudharsan via ce9b471 March 16, 2022 02:30
common/configdb.h Outdated Show resolved Hide resolved
common/configdb.h Outdated Show resolved Hide resolved
common/configdb.h Outdated Show resolved Hide resolved
common/configdb.h Outdated Show resolved Hide resolved
qiluo-msft
qiluo-msft previously approved these changes Mar 24, 2022
client.flushdb()

# Init table data
config_db.set_entry(table_name_1, test_key, test_data_1)
Copy link
Contributor

@qiluo-msft qiluo-msft Mar 29, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test_data_1

Please check unit test failure:
NameError: global name 'test_data_1' is not defined
#Closed

@qiluo-msft qiluo-msft self-requested a review March 29, 2022 23:14
@alexrallen
Copy link
Contributor Author

@qiluo-msft Checkers are passing please take a look. Thanks.

@dgsudharsan
Copy link
Collaborator

@qiluo-msft Can you please help to merge this PR?

@qiluo-msft qiluo-msft merged commit 36e1f61 into sonic-net:master Mar 30, 2022
qiluo-msft pushed a commit to sonic-net/sonic-buildimage that referenced this pull request Apr 7, 2022
… updates (#10168)

#### Why I did it

As of sonic-net/sonic-swss-common#587 the blackout issue in ConfigDBConnector has been resolved. 

In the past hostcfgd was refactored to use SubscriberStateTable instead of ConfigDBConnector for subscribing to CONFIG_DB updates due to a "blackout" period between hostcfgd pulling the table data down and running the initialization and actually calling `listen()` on ConfigDBConnector which starts the update handler. 

However SusbscriberStateTable creates many file descriptors against the redis DB which is inefficient compared to ConfigDBConnector which only opens a single file descriptor. 

With the new fix to ConfigDBConnector I refactored hostcfgd to take advantage of these updates.

#### How I did it

Replaced SubscriberStateTable with ConfigDBConnector

#### How to verify it

The functionality of hostcfgd can be verified by booting the switch and verifying that NTP is properly configured.

To check the blackout period you can add a delay in the hostcfgd `load()` function and also add a print statement before and after the load so you know when it occurs. Then restart hostcfgd and wait for the load to start, then during the load push a partial change to the FEATURE table and verify that the change is picked up and the feature is enabled after the load period finishes. 

#### Description for the changelog
[hostcfgd] Move hostcfgd back to ConfigDBConnector for subscribing to updates
ganglyu pushed a commit to sonic-net/sonic-host-services that referenced this pull request Jul 12, 2022
… updates (#10168)

#### Why I did it

As of sonic-net/sonic-swss-common#587 the blackout issue in ConfigDBConnector has been resolved. 

In the past hostcfgd was refactored to use SubscriberStateTable instead of ConfigDBConnector for subscribing to CONFIG_DB updates due to a "blackout" period between hostcfgd pulling the table data down and running the initialization and actually calling `listen()` on ConfigDBConnector which starts the update handler. 

However SusbscriberStateTable creates many file descriptors against the redis DB which is inefficient compared to ConfigDBConnector which only opens a single file descriptor. 

With the new fix to ConfigDBConnector I refactored hostcfgd to take advantage of these updates.

#### How I did it

Replaced SubscriberStateTable with ConfigDBConnector

#### How to verify it

The functionality of hostcfgd can be verified by booting the switch and verifying that NTP is properly configured.

To check the blackout period you can add a delay in the hostcfgd `load()` function and also add a print statement before and after the load so you know when it occurs. Then restart hostcfgd and wait for the load to start, then during the load push a partial change to the FEATURE table and verify that the change is picked up and the feature is enabled after the load period finishes. 

#### Description for the changelog
[hostcfgd] Move hostcfgd back to ConfigDBConnector for subscribing to updates
itamar-talmon pushed a commit to itamar-talmon/sonic-swss-common that referenced this pull request Jul 19, 2022
…thout blackout (sonic-net#587)

Currently if someone wishes to use ConfigDBConnector to operate on updates coming from CONFIG_DB AND they wish to pull all the initial data from the table to initialize their only option is to pull the data and then run the `listen()` method on ConfigDBConnector.

This creates a "blackout" period where between the time the tables are downloaded and the `listen()` method is called, any new updates to CONFIG_DB will not be handled.

To resolve this I have changed two things in ConfigDBConnector. All of which are 100% backwards compatible...
1. I split `listen()` into `listen()` and `process()` where `listen()` may now be called with `start=False` as an argument which does not start immediately processing updates from CONFIG_DB and calling handlers. This allows you to call `listen()` *first* and then download table data and then call `process()` to start processing updates. This way no updates will be missed as they will be queued by redis while the table data is being downloaded by the consumer. 
2. I added a `cache` argument to `process` in which you pass any initial table data your system is operating on. When a table update is processed the system checks if that keys value is different than what is stored in the cache (if it is present) and only fires the callback handler in the case that the data has changes (added / deleted / updated). This prevents the same data from being processed multiple times.
qiluo-msft pushed a commit that referenced this pull request Jul 10, 2023
**What I did**
Fix the issue of ignoring callback calls for removed keys.

**Why I did it**
ConfigDBConnector.listen method has a caching mechanism (added in #587 PR) that preloads the DB state before starting. When the notification about the changed key is received the listen method gets key data from the DB (in all cases when the key was added, updated, or removed) and compares the data with the cache. It fires the callback only if data differ from the cache. Otherwise, the callback is ignored. 

If the `client.hgetall(key)` is called for the removed key it returns an empty dictionary (`{}`). This can be confused with the data of the key with no attributes. For example: `{"TABLE": {"KEY": {}}}`. 

So if preloaded data contains a key with no attributes and the listener method receives a notification about the removal of such key the callback is not called. The listener will simply remove the key from the cache without calling the callback. This leads to the situation when the removal of the key is not handled.

The solution is to get data for the added or updated keys, and for the removed keys use `None` instead. This will ensure that the comparison with the cache will work as expected.

**How I verified it**
Compile the package and run the unit test. Unit tests are extended to cover the expected behavior.
qiluo-msft pushed a commit that referenced this pull request Aug 29, 2023
**What I did**
Fix the issue of ignoring callback calls for removed keys.

**Why I did it**
ConfigDBConnector.listen method has a caching mechanism (added in #587 PR) that preloads the DB state before starting. When the notification about the changed key is received the listen method gets key data from the DB (in all cases when the key was added, updated, or removed) and compares the data with the cache. It fires the callback only if data differ from the cache. Otherwise, the callback is ignored. 

If the `client.hgetall(key)` is called for the removed key it returns an empty dictionary (`{}`). This can be confused with the data of the key with no attributes. For example: `{"TABLE": {"KEY": {}}}`. 

So if preloaded data contains a key with no attributes and the listener method receives a notification about the removal of such key the callback is not called. The listener will simply remove the key from the cache without calling the callback. This leads to the situation when the removal of the key is not handled.

The solution is to get data for the added or updated keys, and for the removed keys use `None` instead. This will ensure that the comparison with the cache will work as expected.

**How I verified it**
Compile the package and run the unit test. Unit tests are extended to cover the expected behavior.
SviatoslavBoichuk pushed a commit to SviatoslavBoichuk/sonic-swss-common that referenced this pull request Sep 7, 2023
…#789)

**What I did**
Fix the issue of ignoring callback calls for removed keys.

**Why I did it**
ConfigDBConnector.listen method has a caching mechanism (added in sonic-net#587 PR) that preloads the DB state before starting. When the notification about the changed key is received the listen method gets key data from the DB (in all cases when the key was added, updated, or removed) and compares the data with the cache. It fires the callback only if data differ from the cache. Otherwise, the callback is ignored. 

If the `client.hgetall(key)` is called for the removed key it returns an empty dictionary (`{}`). This can be confused with the data of the key with no attributes. For example: `{"TABLE": {"KEY": {}}}`. 

So if preloaded data contains a key with no attributes and the listener method receives a notification about the removal of such key the callback is not called. The listener will simply remove the key from the cache without calling the callback. This leads to the situation when the removal of the key is not handled.

The solution is to get data for the added or updated keys, and for the removed keys use `None` instead. This will ensure that the comparison with the cache will work as expected.

**How I verified it**
Compile the package and run the unit test. Unit tests are extended to cover the expected behavior.
SviatoslavBoichuk pushed a commit to SviatoslavBoichuk/sonic-swss-common that referenced this pull request Sep 7, 2023
…#811)

**What I did**
Fix the issue of ignoring callback calls for removed keys.

**Why I did it**
ConfigDBConnector.listen method has a caching mechanism (added in sonic-net#587 PR) that preloads the DB state before starting. When the notification about the changed key is received the listen method gets key data from the DB (in all cases when the key was added, updated, or removed) and compares the data with the cache. It fires the callback only if data differ from the cache. Otherwise, the callback is ignored. 

If the `client.hgetall(key)` is called for the removed key it returns an empty dictionary (`{}`). This can be confused with the data of the key with no attributes. For example: `{"TABLE": {"KEY": {}}}`. 

So if preloaded data contains a key with no attributes and the listener method receives a notification about the removal of such key the callback is not called. The listener will simply remove the key from the cache without calling the callback. This leads to the situation when the removal of the key is not handled.

The solution is to get data for the added or updated keys, and for the removed keys use `None` instead. This will ensure that the comparison with the cache will work as expected.

**How I verified it**
Compile the package and run the unit test. Unit tests are extended to cover the expected behavior.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants