queuerPy 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,96 @@
1
+ """
2
+ Next interval function-related methods for the Python queuer implementation.
3
+ Mirrors Go's queuerNextInterval.go functionality.
4
+ """
5
+
6
+ import logging
7
+ from typing import Any, Callable
8
+
9
+ from queuer_global import QueuerGlobalMixin
10
+ from model.worker import Worker
11
+
12
+ logger = logging.getLogger(__name__)
13
+
14
+
15
+ class QueuerNextIntervalMixin(QueuerGlobalMixin):
16
+ """
17
+ Mixin class containing next interval function-related methods for the Queuer.
18
+ Mirrors Go's queuerNextInterval.go functionality.
19
+ """
20
+
21
+ def __init__(self):
22
+ super().__init__()
23
+
24
+ def add_next_interval_func(self, nif: Callable[..., Any]) -> Worker:
25
+ """
26
+ Add a NextIntervalFunc to the worker's available next interval functions.
27
+ Takes a NextIntervalFunc and adds it to the worker's available_next_interval_funcs.
28
+ The function name is derived from the function using helper.get_task_name_from_interface.
29
+
30
+ :param nif: The next interval function to add
31
+ :return: The updated worker after adding the function
32
+ :raises ValueError: If function is None
33
+ :raises RuntimeError: If function already exists or database update fails
34
+ """
35
+ from helper.task import get_task_name_from_interface
36
+
37
+ if nif is None:
38
+ raise ValueError("NextIntervalFunc cannot be None")
39
+
40
+ try:
41
+ nif_name = get_task_name_from_interface(nif)
42
+ except Exception as e:
43
+ raise RuntimeError(f"Error getting function name: {str(e)}")
44
+
45
+ if nif_name in self.worker.available_next_interval_funcs:
46
+ raise RuntimeError(f"NextIntervalFunc already exists: {nif_name}")
47
+
48
+ self.next_interval_funcs[nif_name] = nif
49
+ self.worker.available_next_interval_funcs.append(nif_name)
50
+
51
+ try:
52
+ worker = self.db_worker.update_worker(self.worker)
53
+ if not worker:
54
+ raise Exception("Worker could not be updated")
55
+
56
+ logger.info(f"NextInterval function added: {nif_name}")
57
+ return worker
58
+ except Exception as e:
59
+ raise RuntimeError(f"Error updating worker: {str(e)}")
60
+
61
+ def add_next_interval_func_with_name(
62
+ self, nif: Callable[..., Any], name: str
63
+ ) -> Worker:
64
+ """
65
+ Add a NextIntervalFunc to the worker's available next interval functions with a specific name.
66
+ Takes a NextIntervalFunc and a name, checks if the function is not None
67
+ and doesn't already exist in the worker's available next interval functions,
68
+ and adds it to the worker's available_next_interval_funcs.
69
+
70
+ This function is useful when you want to add a NextIntervalFunc
71
+ with a specific name that you control, rather than deriving it from the function itself.
72
+
73
+ :param nif: The next interval function to add
74
+ :param name: The specific name for the function
75
+ :return: The updated worker after adding the function with the specified name
76
+ :raises ValueError: If function is None
77
+ :raises RuntimeError: If function already exists or database update fails
78
+ """
79
+ if nif is None:
80
+ raise ValueError("NextIntervalFunc cannot be None")
81
+
82
+ if name in self.worker.available_next_interval_funcs:
83
+ raise RuntimeError(f"NextIntervalFunc with name already exists: {name}")
84
+
85
+ self.next_interval_funcs[name] = nif
86
+ self.worker.available_next_interval_funcs.append(name)
87
+
88
+ try:
89
+ worker = self.db_worker.update_worker(self.worker)
90
+ if not worker:
91
+ raise Exception("Worker could not be updated")
92
+
93
+ logger.info(f"NextInterval function added: {name}")
94
+ return worker
95
+ except Exception as e:
96
+ raise RuntimeError(f"Error updating worker: {str(e)}")
@@ -0,0 +1,89 @@
1
+ """
2
+ Task-related methods for the Python queuer implementation.
3
+ Mirrors Go's queuerTask.go functionality.
4
+ """
5
+
6
+ import logging
7
+ from typing import Any, Callable, Optional
8
+
9
+ from model.task import new_task, new_task_with_name
10
+ from model.task import Task
11
+ from queuer_global import QueuerGlobalMixin
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+
16
+ class QueuerTaskMixin(QueuerGlobalMixin):
17
+ """
18
+ Mixin class containing task-related methods for the Queuer.
19
+ Mirrors Go's queuerTask.go functionality.
20
+ """
21
+
22
+ def __init__(self):
23
+ super().__init__()
24
+
25
+ def add_task(self, task: Callable[..., Any]) -> Optional[Task]:
26
+ """
27
+ Add a new task to the queuer.
28
+ Creates a new task with the provided task function, adds it to the worker's available tasks,
29
+ and updates the worker in the database.
30
+ The task name is automatically generated based on the task's function name.
31
+
32
+ :param task: The task function to add
33
+ :return: The newly created task
34
+ :raises RuntimeError: If task creation fails or task already exists
35
+ """
36
+ task_name = task.__name__
37
+ if task_name in self.tasks:
38
+ raise RuntimeError(f"Task already exists: {task_name}")
39
+
40
+ try:
41
+ new_task_obj = new_task(task)
42
+ except Exception as e:
43
+ raise RuntimeError(f"Error creating new task: {str(e)}")
44
+
45
+ if new_task_obj.name in self.worker.available_tasks:
46
+ raise RuntimeError(f"Task already exists: {new_task_obj.name}")
47
+
48
+ self.tasks[new_task_obj.name] = new_task_obj
49
+ self.worker.available_tasks.append(new_task_obj.name)
50
+
51
+ # Update worker in DB
52
+ try:
53
+ self.db_worker.update_worker(self.worker)
54
+ except Exception as e:
55
+ raise RuntimeError(f"Error updating worker: {str(e)}")
56
+
57
+ logger.info(f"Task added: {new_task_obj.name}")
58
+ return new_task_obj
59
+
60
+ def add_task_with_name(self, task: Callable[..., Any], name: str) -> "Task":
61
+ """
62
+ Add a new task with a specific name to the queuer.
63
+ Creates a new task with the provided task function and name, adds it to the worker's available tasks,
64
+ and updates the worker in the database.
65
+
66
+ :param task: The task function to add
67
+ :param name: The specific name for the task
68
+ :return: The newly created task
69
+ :raises RuntimeError: If task creation fails or task already exists
70
+ """
71
+ try:
72
+ new_task_obj = new_task_with_name(task, name)
73
+ except Exception as e:
74
+ raise RuntimeError(f"Error creating new task: {str(e)}")
75
+
76
+ if name in self.worker.available_tasks:
77
+ raise RuntimeError(f"Task already exists: {name}")
78
+
79
+ self.tasks[new_task_obj.name] = new_task_obj
80
+ self.worker.available_tasks.append(new_task_obj.name)
81
+
82
+ # Update worker in DB
83
+ try:
84
+ self.db_worker.update_worker(self.worker)
85
+ except Exception as e:
86
+ raise RuntimeError(f"Error updating worker: {str(e)}")
87
+
88
+ logger.info(f"Task added: {new_task_obj.name}")
89
+ return new_task_obj
queuer_global.py ADDED
@@ -0,0 +1,56 @@
1
+ from typing import Any, Callable, Dict, Optional
2
+ from core.broadcaster import new_broadcaster
3
+ from core.listener import Listener
4
+ from database.db_job import JobDBHandler
5
+ from database.db_worker import WorkerDBHandler
6
+ from helper.database import Database, DatabaseConfiguration, new_database
7
+ from helper.logging import get_logger
8
+ from model.job import Job
9
+ from model.task import Task
10
+ from model.worker import Worker
11
+
12
+ logger = get_logger()
13
+
14
+
15
+ class QueuerGlobalMixin:
16
+ def __init__(self):
17
+ self.running: bool = False
18
+
19
+ # DB
20
+ self.db_job: JobDBHandler
21
+ self.db_worker: WorkerDBHandler
22
+
23
+ # Broadcaster
24
+ self.job_insert_broadcaster = new_broadcaster("job.INSERT")
25
+ self.job_update_broadcaster = new_broadcaster("job.UPDATE")
26
+ self.job_delete_broadcaster = new_broadcaster("job.DELETE")
27
+
28
+ # Listener
29
+ self.job_insert_listener = Listener[Job](self.job_insert_broadcaster)
30
+ self.job_update_listener = Listener[Job](self.job_update_broadcaster)
31
+ self.job_delete_listener = Listener[Job](self.job_delete_broadcaster)
32
+
33
+ # Ticker
34
+ self.heartbeat_ticker: Optional[Any] = None
35
+ self.poll_job_ticker: Optional[Any] = None
36
+
37
+ self.worker: Worker
38
+ self.tasks: Dict[str, Task] = {}
39
+ self.next_interval_funcs: Dict[str, Callable[..., Any]] = {}
40
+
41
+ def initialise(
42
+ self,
43
+ db_config: DatabaseConfiguration,
44
+ encryption_key: str = "",
45
+ ):
46
+ # Database connection
47
+ self.database: Database = new_database("queuer", db_config, logger)
48
+ self.DB = self.database.instance
49
+
50
+ # Database handlers
51
+ self.db_job: JobDBHandler = JobDBHandler(
52
+ self.database, db_config.with_table_drop, encryption_key
53
+ )
54
+ self.db_worker: WorkerDBHandler = WorkerDBHandler(
55
+ self.database, db_config.with_table_drop
56
+ )