-
-
Notifications
You must be signed in to change notification settings - Fork 1
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
Implement an Asynchronous Task system using OOP principles (ported from PygameCommunityBot) #9
Comments
Is your feature request related to a problem? Please describe. Describe the solution you'd like Describe alternatives you've considered |
ImplementationIn order to implement this module, we will need these things:
|
1. Job SubmoduleThis module defines the basis for all jobs. The pattern of inheritance for jobs is as follows:
There are multiple utility jobs based upon these base job classes to ease things like Discord messaging, scheduling a method call, and more. Various methods inherited from Every job object can use its
|
2. Job Manager SubmoduleThis module defines the job manager.
Job objects are unable to run properly if they are not added to a Jobs can use their job manager proxy to access permission-restricted functions, which allow them to interact with other jobs in a controlled manner. With the help of their manager proxy, jobs can find, schedule, start, stop, restart, guard (to prevent unintended state modifications from other jobs), unguard, or kill other jobs, assuming that they have been given the permissions to do so. Without the required permissions, these operations will be blocked with a An enum class is used to implement and document the different job permission levels that exist. These must be set on a class level prior to runtime and cannot be modified. Permission Levels LOWEST = 1
"""The lowest permission level.
An Isolated job which has no information about other jobs being executed.
Permissions:
- Can manage its own execution at will.
"""
LOW = 1 << 1
"""A low permission level.
Permissions:
- Can manage its own execution at will.
- Can discover and view all alive jobs, and request data from them.
"""
MEDIUM = 1 << 2
"""The default permission level, with simple job management permissions.
Permissions:
- Can manage its own execution at will.
- Can discover and view all alive jobs, and request data from them.
- Can instantiate, register, start and schedule jobs of a lower permission level.
- Can stop, restart, or kill jobs instantiated by itself or unschedule its scheduled jobs.
- Can unschedule jobs that don't have an alive job as a scheduler.
"""
HIGH = 1 << 3
"""An elevated permission level, with additional control over jobs
of a lower permission level.
Permissions:
- Can manage its own execution at will.
- Can discover and view all alive jobs, and request data from them.
- Can instantiate, register, start and schedule jobs of a lower permission level.
- Can stop, restart, or kill jobs instantiated by itself or unschedule its scheduled jobs.
- Can unschedule jobs that don't have an alive job as a scheduler.
- Can stop, restart, kill or unschedule any job of a lower permission level.
- Can guard and unguard jobs of a lower permission level instantiated by itself.
- Can dispatch custom events to other jobs (`CustomEvent` subclasses).
"""
HIGHEST = 1 << 4
"""The highest usable permission level, with additional control over jobs
of a lower permission level. Lower permissions additionally apply to this level.
Permissions:
- Can manage its own execution at will.
- Can discover and view all alive jobs, and request data from them.
- Can instantiate, register, start and schedule jobs of a lower permission level.
- Can stop, restart, or kill jobs instantiated by itself or unschedule its scheduled jobs.
- Can unschedule jobs that don't have an alive job as a scheduler.
- Can stop, restart, kill or unschedule any job of a lower permission level.
- Can guard and unguard jobs of a lower permission level instantiated by itself.
- Can guard and unguard jobs of the same permission level instantiated by itself.
- Can dispatch custom events to other jobs (`CustomEvent` subclasses).
- Can dispatch any event to other jobs (`BaseEvent` subclasses).
- Can instantiate, register, start and schedule jobs of the same permission level.
- Can stop, restart, kill or unschedule any job of the same permission level.
"""
SYSTEM = 1 << 5
"""The highest possible permission level reserved for system-level jobs. Cannot be used directly.
Lower permissions additionally apply to this level.
Permissions:
- Can manage its own execution at will.
- Can discover and view all alive jobs, and request data from them.
- Can instantiate, register, start and schedule jobs of a lower permission level.
- Can stop, restart, or kill jobs instantiated by itself or unschedule its scheduled jobs.
- Can unschedule jobs that don't have an alive job as a scheduler.
- Can stop, restart, kill or unschedule any job of a lower permission level.
- Can guard and unguard jobs of a lower permission level instantiated by itself.
- Can dispatch custom events to other jobs (`CustomEvent` subclasses).
- Can dispatch any event to other jobs (`BaseEvent` subclasses).
- Can instantiate, register, start and schedule jobs of the same permission level.
- Can stop, restart, kill or unschedule any job of the same permission level.
- Can guard or unguard any job.
""" |
Job SchedulingJob scheduling works by scheduling the instantiation of a specific job class with a timestamp. For this to work, each job class must be given a permanent and unique identifier to recognize it after it was scheduled with. All arguments to pass to the job constructor must additionally be serializable using |
3 & 4. Event Classes SubmoduleThese modules define base classes for event objects, which are used to propagate event occurences to all jobs that are listening for them. They can also store data in attributes to pass on to listening jobs.
|
ExamplesThis sample code shows how the main file for job-class-based program is meant to be structured. Here, the
class GreetingTest(core.ClientEventJobBase, permission_level=JobPermissionLevels.MEDIUM): # MEDIUM is the default
"""
A job that waits for a user to type a message starting with 'hi', before responding with 'Hi, what's your name?'.
This job will then wait until it receives another `OnMessage` event, before saying 'Hi, {event_content}'
"""
EVENT_TYPES = (events.OnMessage,)
def __init__(self, target_channel: Optional[discord.TextChannel] = None):
super().__init__() # very important
self.data.target_channel = target_channel
async def on_init(self):
if self.data.target_channel is None:
self.data.target_channel = common.guild.get_channel(822650791303053342)
def check_event(self, event: events.OnMessage): # additionally validate any dispatched events
return event.message.channel.id == self.data.target_channel.id
async def on_run(self, event: events.OnMessage):
if event.message.content.lower().startswith("hi"):
with self.queue_blocker(): # block the event queue of this job while talking to a user, so that other events are ignored if intended
await self.data.target_channel.send("Hi, what's your name?")
author = event.message.author
check = (
lambda x: x.message.author == author
and x.message.channel == self.data.target_channel
and x.message.content
)
name_event = await self.wait_for(self.manager.wait_for_event( # self.wait_for signals that the job is awaiting something to other jobs and the job manager
events.OnMessage, check=check
))
user_name = name_event.message.content
await self.data.target_channel.send(f"Hi, {user_name}")
class Main(core.SingleRunJob, permission_level=JobPermissionLevel.HIGHEST): # prevent most jobs from killing the `Main` job
"""The main job class that serves as an entry into a program that uses jobs.
"""
async def on_run(self):
await self.manager.create_and_register_job(GreetingTest)
__all__ = [
"Main",
] |
This has now been successfully implemented. |
This is a port of an issue from the PygameCommunityBot project.
The text was updated successfully, but these errors were encountered: