I'm using FASTApi and trying to implement an endpoint, which starts a job. Once the job is started, the endpoint shall be "locked" until the previous job finished. So far its implemented like this:
myapp.lock = threading.Lock()
@myapp.get("/jobs")
def start_job(some_args):
if myapp.lock.acquire(False):
th = threading.Thread(target=job,kwargs=some_args)
th.start()
return "Job started"
else:
raise HTTPException(status_code=400,detail="Job already running.")
So, when the job gets started, a thread will be created using the method job:
def job(some_args):
try:
#doing some stuff, creating objects and writing to files
finally:
myapp.lock.release()
So far so good, the endpoint is working, starts a job and locks as long as the job is running. But my problem is that the thread is still alive although the job "finished" and released the lock. I was hoping that the thread would close itself after execution. Maybe the problem is that myapp is keeping it alive? How can I stop it?
I figured out this kind of solution:
myapp.lock = False
@myapp.get("/jobs")
async def start_job(some_args, background_tasks: BackgroundTasks):
if not myapp.lock:
background_tasks.add_task(job, some_args)
return "Job started"
else:
raise HTTPException(status_code=400,detail="Job already running.")
def job(some_args):
try:
myapp.lock = True
#doing some stuff, creating objects and writing to files
finally:
myapp.lock = False
I have faced the similar issue. I would like to block the request that want to change the state of a specific object (an object is a simulation in my case). I use PostgreSQL and have created the following
create table simulation_lock (simulation_id INTEGER PRIMARY KEY, is_locked BOOLEAN DEFAULT False);
from starlette.exceptions import HTTPException
from fmr.database import SessionContext
class SimulationLock:
def __init__(self, simulation_id: int):
self._simulation_id = simulation_id
self._was_acquired = False
def __enter__(self):
with SessionContext() as session:
query = f"update simulation_lock set is_locked = true where " \
f"simulation_id = {self._simulation_id} " \
f"and is_locked = false returning is_locked;"
result = session.execute(query).first()
session.commit()
if result is not None and result[0] is True:
self._was_acquired = True
else:
raise HTTPException(
status_code=500, detail="Already some operations on the "
"simulation are performed.")
def __exit__(self, exc_type, exc_val, exc_tb):
if self._was_acquired:
with SessionContext() as session:
query = f"update simulation_lock set is_locked = false " \
f"where simulation_id = {self._simulation_id};"
session.execute(query)
session.commit()
@scenario_router.post(
"/run"
)
async def run(
run_scenario_request: RunScenarioRequest,
):
with SimulationLock(run_scenario_request.scenario_id):
run_scenario(run_scenario_request)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.