I'm currently facing a problem where I am giving a thread a reference to a set and I want to be able to replace the set with a mocked database call. I have so far done
import logging
import threading
import time
from typing import Callable
from loguru import logger
class MonitorProduct:
def __init__(self, term: str, is_alive: Callable[[str], bool]) -> None:
self.is_alive = is_alive
self.term = term
def do_request(self) -> None:
time.sleep(.1)
while True:
logger.info(f'Checking {self.term}')
if not self.is_alive(self.term):
logger.info(f'Deleting term from monitoring: "{self.term}"')
return
time.sleep(5)
# mocked database
def database_terms() -> set[str]:
return {
'hello world',
'python 3',
'world',
'wth',
}
def database_terms_2() -> set[str]:
return {
'what am I doing wrong',
}
def main() -> None:
terms: set[str] = set()
while True:
db_terms = database_terms()
diff = db_terms - terms
terms.symmetric_difference_update(db_terms)
for url in diff:
logger.info(f'Starting URL: {url}')
threading.Thread(
target=MonitorProduct(url, terms.__contains__).do_request
).start()
time.sleep(2)
# ----------------------------------------------- #
db_terms = database_terms_2()
diff = db_terms - terms
terms.symmetric_difference_update(db_terms) # <--- terms should only now contain `what am I doing wrong`
# Start the new URLS
for url in diff:
logger.info(f'Starting URL 2: {url}')
threading.Thread(
target=MonitorProduct(url, terms.__contains__).do_request
).start()
time.sleep(10)
if __name__ == '__main__':
main()
The problem I am now having is that when we do our first db call, it should start threads for each of terms:
{
'hello world',
'python 3',
'world',
'wth',
}
and as you can see we also send in a terms.__contains__ for each thread.
When we do the second call of db - that set should replace the terms to
{
'what am I doing wrong',
}
which should end up exiting the four running threads due to:
def do_request(self) -> None:
time.sleep(.1)
while True:
logger.info(f'Checking {self.term}')
if not self.is_alive(self.term):
logger.info(f'Deleting term from monitoring: "{self.term}"')
return
time.sleep(5)
however the problem is that we cannot replace terms by doing
terms = ... because we are creating a new set and then bidning that set to the variable terms while the thread still has a reference to the old set.
My question is, how can I replace the old terms with updating to the newest set without binding a new set?
myset.clear(); myset.update(new_values)if not self.is_alive(self.term):in the same timing which is not what I would like to do because then there is threads that were supposed to run - be exited instead and then starting a new spawn again due to that.