8000 Add implementation for clearing cache table by hjk1030 · Pull Request #177 · ddkang/aidb · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Add implementation for clearing cache table #177

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

Open
wants to merge 19 commits into
base: main
Choose a base branch
from

Conversation

hjk1030
Copy link
Contributor
@hjk1030 hjk1030 commented Apr 29, 2024

Added a function to delete all the data in the cache table. Trying to resolve issue #122.

@hjk1030
Copy link
Contributor Author
hjk1030 commented Apr 29, 2024

By the way, do I need to add tests for this?

@ttt-77
Copy link
Collaborator
ttt-77 commented Apr 29, 2024

By the way, do I need to add tests for this?

Yes.

@hjk1030
Copy link
Contributor Author
hjk1030 commented May 1, 2024

I modified an existing test to validate this since adding another test makes the existing test fail.

@hjk1030 hjk1030 marked this pull request as ready for review May 1, 2024 15:25
for service_binding in engine._config.inference_bindings:
if isinstance(service_binding, CachedBoundInferenceService):
async with service_binding._engine.begin() as conn:
stmt = delete(service_binding._cache_table)
Copy link
Collaborator

Choose 10000 a reason for hiding this comment

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

use meaningful variable names

await conn.execute(stmt)
tables = service_binding.get_tables(service_binding.binding.output_columns)
for table_name in tables:
stmt = delete(service_binding._tables[table_name]._table)
Copy link
Collaborator

Choose a reason for hiding this comment

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

If tables have dependencies, does deleting them in any arbitrary order cause issues?
(e.g. table B has a foreign key that refers to table A, does deleting table A first cause an issue?)

@@ -9,6 +9,8 @@
from tests.inference_service_utils.inference_service_setup import register_inference_services
from tests.inference_service_utils.http_inference_service_setup import run_server
from tests.utils import setup_gt_and_aidb_engine, setup_test_logger
from aidb.utils.asyncio import asyncio_run
from aidb_utilities.db_setup.clear_cache import clear_ML_cache
Copy link
Collaborator

Choose a reason for hiding this comment

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

isort

launch.py Outdated
@@ -8,7 +8,7 @@
from aidb_utilities.db_setup.blob_table import BaseTablesSetup
from aidb_utilities.db_setup.create_tables import create_output_tables
from aidb.utils.asyncio import asyncio_run

from aidb_utilities.db_setup.clear_cache import clear_ML_cache
Copy link
Collaborator

Choose a reason for hiding this comment

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

isort

aidb_res = aidb_engine.execute(aidb_query)
assert len(gt_res) == len(aidb_res)
# running the same query, so number of inference calls should remain same
# temporarily commenting this out because we no longer call infer_one
assert aidb_engine._config.inference_services["objects00"].infer_one.calls == calls[index]
assert aidb_engine._config.inference_services["objects00"].infer_one.calls == calls[index][0], f"Wrong query count: Expected {calls[index][0]}, Actual {aidb_engine._config.inference_services['objects00'].infer_one.calls}"
Copy link
Collaborator

Choose a reason for hiding this comment

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

This line is too long. Maximum line length is 80 characters.

@hjk1030
Copy link
Contributor Author
hjk1030 commented May 2, 2024

I modified the code style. Also changes the delete order to depend on foreign key references.

@hjk1030 hjk1030 requested a review from ttt-77 May 2, 2024 08:30
Clear the cache table at start if the ML model has changed.
Delete the cache table for each service.
'''
for inference_binding in engine._config.inference_bindings:
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you refactor the code?

  1. Collect all tables.
  2. Construct a Table Graph
  3. topological sort
  4. Delete tables.
    You can refer to
    def table_graph(self) -> Graph:
    and https://github.com/ddkang/aidb/blob/d8e78e488ac91b78e8cc002b06aa01dfa8f39dfd/aidb/config/config.py#L121C23-L121C39

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, modified that.

@hjk1030 hjk1030 requested a review from ttt-77 May 3, 2024 16:59
@hjk1030
Copy link
Contributor Author
hjk1030 commented May 6, 2024

@ttt-77 Could you please review this PR again?

@@ -1,13 +1,18 @@
from multiprocessing import Process
import os
Copy link
Collaborator

Choose a reason for hiding this comment

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

Have you added this test to Github Action?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes. The test is modified based on an original test and I verified it is executed.

@ttt-77
Copy link
Collaborator
ttt-77 commented May 8, 2024

Looks good to me. @ddkang



async def clear_ML_cache(engine: Engine):
'''
Copy link
Owner

Choose a reason for hiding this comment

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

Use standard naming conventions "clear_ml_cache"

Copy link
Owner

Choose a reason for hiding this comment

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

Also why is this in the DB setup and not the engine?

'''
Clear the cache table at start if the ML model has changed.
Delete the cache table for each service.
'''
Copy link
Owner

Choose a reason for hiding this comment

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

Describe the logic in the comment

* Move the clear cache function to engine
* Function name change
* Add code logic comment
@@ -47,24 +51,35 @@ async def test_num_infer_calls(self):
# no service calls before executing query
Copy link
Owner

Choose a reason for hiding this comment

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

We should have a separate test that tests that other ML models don't get removed when one is removed

hjk1030 added 6 commits May 9, 2024 23:25
* Add deletion for services seperately
* Fix launch.py
* Add test to check whether only cache for one service is deleted
* Change function param declaration to be compatible with python 3.8
* Change call count logic since all the inference service use the same counter
* Add join() function to terminate the test server completely
* Clear cache before test run
* Set count target corresponding to initial call count
* run cache clearing using asyncio
* Add join() and sleep to make sure the server terminates
@hjk1030
Copy link
Contributor Author
hjk1030 commented May 10, 2024

@ddkang Could you please review this?

@@ -84,6 +84,8 @@ async def test_num_infer_calls(self):
del gt_engine
del aidb_engine
p.terminate()
p.join()
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Also, I cannot terminate the test server completely without this. I'm not sure whether it's a bug or I'm not using the correct way to write multiple tests.

Copy link
Owner

Choose a reason for hiding this comment

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

Please check this in depth

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I believe the test server wasn't properly closed before. The server will still occupy the port if only the terminate() function is called. However most test classes only have one unit test or the service is not called, so it did not cause any problems.

@@ -42,3 +49,53 @@ def execute(self, query: str, **kwargs):
raise e
finally:
self.__del__()

async def clear_ml_cache(self, service_name_list = None):
Copy link
Owner

Choose a reason for hiding this comment

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

Is there a reason this function is so complicated?

Copy link
Contributor Author
@hjk1030 hjk1030 May 10, 2024

Choose a reason for hiding this comment

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

Most of this function is building the foreign key relationship graph since deleting the data referenced by another output table will cause error. I believe this is necessary unless there exists such a graph already.

Copy link
Owner

Choose a reason for hiding this comment

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

Are there other functions that build the fk relationship graph? If so, that should be refactored

Copy link
Owner

Choose a reason for hiding this comment

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

* Use the existing inference topological order as delete order
@hjk1030
Copy link
Contributor Author
hjk1030 commented May 14, 2024

I refactored the function using the topological order of inference services.

@ddkang
Copy link
Owner
ddkang commented May 15, 2024

@ttt-77 please check

if isinstance(bounded_service, CachedBoundInferenceService):
if bounded_service.service.name in service_name_list:
for input_column in bounded_service.binding.input_columns:
service_name_list.add(input_column.split('.')[0])
Copy link
Collaborator

Choose a reason for hiding this comment

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

why do you add table name into service_name_list?

service_name_list.add(input_column.split('.')[0])
asyncio_run(conn.execute(delete(bounded_service._cache_table)))
for output_column in bounded_service.binding.output_columns:
asyncio_run(conn.execute(delete(bounded_service._tables[output_column.split('.')[0]]._table)))
Copy link
Collaborator

Choose a reason for hiding this comment

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

The output tables may be same. Can you add them into a set and then delete them?

for index, (query_type, aidb_query, exact_query) in enumerate(queries):
# Run the query on the aidb database
logger.info(f'Running query {exact_query} in ground truth database')
# Run the query on the ground truth database
Copy link
Collaborator

Choose a reason for hiding this comment

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

Write comments in the correct locations.

del aidb_engine
p.terminate()
p.join()
time.sleep(1)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this necessary?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I believe the join() is necessary or the server startup for the second test has some problems: https://github.com/ddkang/aidb/actions/runs/9025134318/job/24800303051. The sleep() is redundant and I have removed that.

hjk1030 added 3 commits May 15, 2024 23:41
* Fix how the service to clear cache are collected
* Reduce redundant table deletion
* Comment Fix
* Remove redundant sleep
* Use the correct graph to collect service
@hjk1030
Copy link
Contributor Author
hjk1030 commented May 15, 2024

@ttt-77 Could you please review this?


asyncio_run(aidb_engine.clear_ml_cache(["lights01"]))

for index, (query_type, aidb_query, exact_query) in enumerate(queries):
Copy link
Collaborator

Choose a reason for hiding this comment

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

Refactor the code. Could this loop be merged into previous one?

service_name_list = set(service_name_list)

# Get all the services that need to be cleared because of foreign key constraints
inference_graph = self._config.inference_graph
Copy link
Collaborator

Choose a reason for hiding this comment

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

The edge in inference_graph doesn't represent two nodes have foreign key constraints

@hjk1030
Copy link
Contributor Author
hjk1030 commented May 18, 2024

I've reconsidered the clearing logic. Now I'm planning to use the following procedure:

  1. Collect the output tables directly related to the selected services.
  2. Collect the output tables that need to be cleared considering the fk constraints and service constraints (if one of the output tables in a service needs to be cleared, all the tables belonging to the service have to be cleared as well). This will use the table_graph in the config, and I'll create a new map at the beginning to get all the services related to a table(I didn't find an existing map for this).
  3. Delete the cache tables. No fk refers to the cache table so this should not cause a problem.
  4. Delete the output tables in the reversed topological order of table_graph.

Are there any problems with this procedure? Or can it be simplified in some way?

@ttt-77
Copy link
Collaborator
ttt-77 commented May 18, 2024

Looks good.

* Merge the two stage of testing using a loop

* Refactor the cache clearing using the table graph
@hjk1030
Copy link
Contributor Author
hjk1030 commented May 19, 2024

@ttt-77 Could you please check this? The clearing steps are more complicated than I thought but I think all the steps are necessary.

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.

3 participants
0