-
Notifications
You must be signed in to change notification settings - Fork 4
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
Feature TaskManager Scheduler and Queue and Context Decorators for Timed and Cancellable #438
Conversation
👇 Click on the image for a new way to code review
Legend |
873f8d4
to
213fdfd
Compare
d1f2217
to
5b0bc2e
Compare
c8c94be
to
ca44318
Compare
5b0bc2e
to
d8cf498
Compare
Now that the At this I was thinking that this means In such a situation the |
d924aa3
to
0646286
Compare
ee7bf01
to
c715cf3
Compare
The However users input an This allows us to set a base low priority or base high priority. The |
So in attempting to work out the This led me to flesh out At this I was attempting to extend But I hit some problems with this... namely extending classes also inherits static methods, and
Not sure what this is about. At any case, I swapped to working with a promise property instead and creating a deconstructed promise inside the Now it is possible to create TypeScript does have a special type for "thenable" things. They are This means, we can say that I find that if we were to say that it implements the There was a problem with the constructor types. I want the default type parameter of Unfortunately constructor overloading doesn't support generic parameters: microsoft/TypeScript#35387, so it doesn't actually enforce the handler return type atm. There are some solutions that involve some type hackery by separating the constructor type from the instance type, like imagine having a Furthermore, there's also a new |
It works:
I wonder if we use only |
The We can do it in 2 ways:
I'm wondering if This means using |
5b9c914
to
331c732
Compare
32ecc60
to
1b109d9
Compare
f629f67
to
c6b3c0c
Compare
Ok all changes relating to the
The |
I've updated the base branch to be |
Ah, I was about to update that. This has been squashed and rebased on staging now. |
I'm doing the |
Remove |
There would be 3 domains being prototyped here:
Right now |
Both the We could also just implement the |
I suggest start designing this assuming |
All the tests are fixed now. Just need to remove the timer domain and use the new library. |
This is intentional. If the domains need to do something else, they should then do whatever fancy work they need by scheduling new tasks. Plus the order in the PK agent should be:
So during the stopping of the domains and tasks, it's possible to interact with the task manager by scheduling new tasks. If in the future we have a need to have a way of requeuing a task while also settling the task promise... then a different exception is needed for this, as it also has to decide whether the task promise fulfils or rejects. And this decision should be decided later. The |
Yes, the library is released as |
Looks like everything has been addressed now. Just need any final changes, clean up and squash the new commits. Then we should be good to merge. I think you're still working on some contexts stuff @CMCDragonkai ? There are still some tasks un-ticked for tests. They are low priority and will be addressed in a separate issue? In the mean time I'll be working on #445 . |
eaf0281
to
4375f9e
Compare
The |
…uld do nothing There are 3 properties for the `timed` wrapper: A. If timer times out, signal is aborted B. If signal is aborted, timer is cancelled C. If timer is owned by the wrapper, then it must be cancelled when the target finishes There are 4 cases where the wrapper is used and where the properties are applied: 1. Nothing is inherited - A B C 2. Signal is inherited - A B C 3. Timer is inherited - A 4. Both signal and timer are inherited - A* B and C are only applied to case 1 and 2, because that's when the `Timer` is owned by the wrapper. *Case 4 is a special case, because the timer and signal are inherited, so it is assumed that the handlers are already setup betwen the timer and signal.
…factored out common functionality in contexts domain
4375f9e
to
eb4e287
Compare
Ok I see there's still some stuff to clean up in the tests. This is in the latest WIP commit. Will review the tasks tests tomorrow in case anything else needs change. @tegefaulkes in the mean time, can you make sure that the CI/CD is passing for this branch right now, so it is ready for merge to staging? |
8109199
to
5647b39
Compare
Cleaned up |
All tests are passing except for a single timeout in
I've re-triggered it but since it's not the scope of this PR I think we can merge. |
Merged! |
Description
At the same time, we may apply the DB to new a generic queuing system. Automatic indexing still isn't available yet, and we may only provide that after transparent encryption/decryption is implemented in the DB. So for now any DB usage has to continue using its own indexes. However SI transactions will help realise this, since we can now be user that any reads and writes are all consistent within the transaction body.
Queue does not use
WorkerManager
, it doesn't know about the nature of the task, instead it executes tasks according to a user-specified concurrency limit, task handlers can decide on their own accord to execute tasks by passing it to theWorkerManager
for parallel processing, this allows tasks to be IO-bound to be sent into the scheduler/queue without worrying about it being inefficiently sent to the worker managerIssues Fixed
Tasks
Asynchronous Promise Cancellation and Timer:
Timer
class with integration intoPromiseCancellable
Timer
@timed
decorator usingTimer
andAbortSignal
timed
decorator testingSignal
andAbortController
timed
error stack provides information on where the decorated function is calledtimed
HOF variant to allow function composition@cancellable
decorator usingAbortSignal
andPromiseCancellable
cancellable
decoratorcancellable
HOF variant[ ] 8.- not doing due to Feature TaskManager Scheduler and Queue and Context Decorators for Timed and Cancellable #438 (comment)@transactional
decorator usingDBTransaction
[ ] 9. tests for@transactional
[ ] 10.transactional
HOF varianttimedCancellable
as he combination of timed and cancellableTasks System:
Lock
fromasync-locks
setTimeout
where the delay is set to the "next" task to be scheduledawait
, but take care not to wait for the task to completeDate.now()
always usingperformance.now()
when comparing task schedule timeTaskPath
to represent the arbitrary label for tasks, so this allows domain to look up multiple tasks based on a specific path. Note that when returning the task data, you will need to return tuples of[KeyPath, Task]
... or just yieldTask
where thepath: TaskPath
allows users to know what the true path of the task is. TheTaskPath
should be an alias ofLevelPath
. Note that this means you can useArray<string | Buffer>
to query or schedule new tasks, but the returnedTaskPath
would always need to beArray<Buffer>
.NodeGraph
.TaskDeadline
to set the deadline of how long the task is allowed to run for. This will be used by thetimed
HOF to ensure that background tasks are given a specific deadline. Default it toInfinity
to allow infinite time.task.promise.cancel()
.[ ] At the end of- this will be done in Integrate TaskManager into NodeGraph and Discovery #445PolykeyAgent.start
you need to doscheduler.startProcessing()
, it should be a lazy creation and lazy start from the beginning to allow handlers to be registered. This is whyPolykeyAgent
would be creating a lazy scheduler so it doesn't start the processing loop.getTaskData
calls, replace withgetTask
andgetTasks
. Furthermore when scheduler and queue has been separated, you'll havescheduler.getTask
andqueue.getTask
, it may just be wrapping thequeue.getTask
method. The schedulergetTask
can get all tasks, butQueue
can get only the active and inactive tasks (the queued tasks).new EventTarget
, where you can emit events and listen for events, these events, are going to be about the task fulfillment or rejection.then
operator.Scheduler
andQueue
. It's important to distinguish inactive vs active tasks, where active tasks are live in-memory executing tasks.Priority
. Have a sublevel likeQueue/tasks/PriorityIndex/ScheduleTime/TaskId
. This is a static priority index.(e, result)
. Then check ifif (e != null)
. Then you canresolve
.Task
should be a POJO record, not a class, in order to communicate that it is a value-level object, not some sort of special domain object. It's not live. It's just data. The original reason forTask
to be a class was to make it a promise. But we can't do this due toawait s.scheduleTask()
awaiting both the scheduling and the processing. Now that we have gone to using apromise
property, the original reason is no longer valid, so we can go back to using a record forTask
so that is clear that this is a POJO data, and not some code.TaskData
, that's encapsulated within theTask
POJO recordpromise
property is a special property, that when thethen
is called, that's when the event listeners are assigned in the queue. This can be forced if the scheduling of the task is not lazy. Thelazy
boolean has to be false by default, meaning eager scheduling is the default..promise
should be aPromiseCancellable
enabling one to dotask.promise.cancel()
. Doing this is independent of whether the event listeners are attached or not. It needs to be capable of cancelling a task that is only scheduled, or a task that is queued and inactive, or queued and active. The cancellability of the background task is always "lazy". The task is never early rejected.TaskId
encoded as string should bebase32hex
. You need put this as an encoding function into theutils
.TaskIdEncoded
. This is used when emitting events as the event name must be a string or symbol, can't pass a buffer into it. This will maintain the sortability of the task id.[ ] Start using timer mocks to mock the- do not use mocking here, it is too complicated, instead prefer using minimal timeouts between 25 to 1000 millisecond timeoutsperformance.now()
activeLimit
called exactly 4 times
, rename and usefastCheck
to use a random set of tasks.can await a task promise resolve/reject
, use fast check to randomize tasks and check them, make a 3rd test combining the two.task promise for invalid task should throw
should check for a task to fail if no handler exists, should check both no handler existed, or handler was de-registered.Tasks.getTaskPromise
.getTaskPromise
are the same for the same task.Final checklist