Sessions are central state holders and one of the most important classes in PlainBox. Since they are all named alike it’s a bit hard to find what the actual responsibilities are. Here’s a small shortcut, do read the description of each module and class for additional details though.
This a class that holds all of the state and program logic. It SessionManager is a class that couples SessionState and SessionStorage. It has the methods required to alter the state by introducing additional jobs or results. It’s main responsibility is to keep track of all of the jobs, their results, if they are runnable or not (technically what is preventing them from being runnable) and to compute the order of execution that can satisfy all of the dependencies.
It holds a number of references to other pieces of PlainBox (jobs, resources and other things) but one thing stands out. This class holds references to a number of JobState objects that couple a JobResult and JobDefinition together.
This class is a subclass of SessionState with additional methods for suspend and resume. It should not be used in new applications and it will be removed eventually, once the new manager-based API settles in. There are two classes that actually implement this API, one based on the original implementation and another one based on the new implementation. The data they create is not compatible with each other. Currently the original implementation is used. This will change very soon.
A coupling class between JobDefinition and JobResult. This class also knows why a job cannot be started in a particular session, by maintaining a set of “inhibitors” that prevent it from being runnable. The actual inhibitors are managed by SessionState.
This class knows how properly to save and load bytes and manages a directory for all the filesystem entries associated with a particular session. It holds no references to a session though. Typically the class is not instantiated directly but instead comes from helper methods of SessionStorageRepository.
This class knows how to enumerate possible instances of SessionStorage from a given location in the filesystem. It also knows how to obtain a default location using XDG standards.
Class representing the cause of a job not being ready to execute.
It is intended to be consumed by UI layers and to provide them with enough information to render informative error messages or other visual feedback that will aid the user in understanding why a job cannot be started.
There are four possible not ready causes:
- UNDESIRED:
- This job was not selected to run in this session
- PENDING_DEP:
- This job depends on another job which was not started yet
- FAILED_DEP:
- This job depends on another job which was started and failed
- PENDING_RESOURCE:
- This job has a resource requirement expression that uses a resource produced by another job which was not started yet
- FAILED_RESOURCE:
- This job has a resource requirement that evaluated to a false value
All causes apart from UNDESIRED use the related_job property to encode a job that is related to the problem. The PENDING_RESOURCE and FAILED_RESOURCE causes also store related_expression that describes the relevant requirement expression.
There are three attributes that can be accessed:
- cause:
- Encodes the reason why a job is not ready, see above.
- related_job:
- Provides additional context for the problem. This is not the job that is affected, rather, the job that is causing the problem.
- related_expression:
- Provides additional context for the problem caused by a failing resource expression.
Class representing the state of a job in a session.
Contains two basic properties of each job:
- the readiness_inhibitor_list that prevent the job form starting
- the result (outcome) of the run (IJobResult)
For convenience (to SessionState implementation) it also has a reference to the job itself. This class is a pure state holder an will typically collaborate with the SessionState class and the UI layer.
Quickly check if the associated job can run right now.
Create a JobState instance from JSON record
Get a human readable description of the current readiness state
the job associated with this state
Event fired when the result associated with this job state changes
the list of readiness inhibitors of the associated job
the result of running the associated job
Manager class for coupling SessionStorage with SessionState.
This class allows application code to manage disk state of sessions. Using the checkpoint() method applications can create persistent snapshots of the SessionState associated with each SessionManager.
Create a checkpoint of the session.
After calling this method you can later reopen the same session with SessionManager.open_session().
Create a session manager with a fresh session.
This method populates the session storage with all of the well known directories (using WellKnownDirsHelper.populate())
Parameters: |
|
---|---|
Ptype job_list: | list of IJobDefinition. |
Ptype repo: | |
Ptype legacy_mode: | |
bool |
|
Returns: | fresh SessionManager instance |
Load a previously checkpointed session.
This method allows one to re-open a session that was previously created by SessionManager.checkpoint()
Parameters: |
|
---|---|
Ptype storage: | |
Raises: | Anything that can be raised by load_checkpoint() and resume() |
Returns: | Fresh instance of SessionManager |
SessionState associated with this manager
SessionStorage associated with this manager
Class representing all state needed during a single program session.
This is the central glue/entry-point for applications. It connects user intents to the rest of the system / plumbing and keeps all of the state in one place.
The set of utility methods and properties allow applications to easily handle the lower levels of dependencies, resources and ready states.
SessionState has the following instance variables, all of which are currently exposed as properties.
Variables: |
|
---|
Add a new job to the session
Parameters: |
|
---|---|
Returns: | The job that was actually added or an existing, identical job if a perfect clash was silently ignored. |
Raises DependencyDuplicateError: | |
if a duplicate, clashing job definition is detected |
The new_job gets added to all the state tracking objects of the session. The job is initially not selected to run (it is not in the desired_job_list and has the undesired inhibitor).
The new_job may clash with an existing job with the same name. Unless both jobs are identical this will cause DependencyDuplicateError to be raised. Identical jobs are silently discarded.
Note
This method recomputes job readiness for all jobs
List of jobs that are on the “desired to run” list
This is a list, not a set, because the dependency solver algorithm retains as much of the original ordering as possible. Having said that, the actual order can differ widely (for instance, be reversed)
Provide the estimated duration of the jobs that have been selected to run in this session (maintained by calling update_desired_job_list).
Manual jobs have an arbitrary figure added to their runtime to allow for execution of the test steps and verification of the result.
Returns: | (estimate_automated, estimate_manual) |
---|
where estimate_automated is the value for automated jobs only and estimate_manual is the value for manual jobs only. These can be easily combined. Either value can be None if the value could not be calculated due to any job lacking the required estimated_duration field.
List of all known jobs.
Not necessarily all jobs from this list can be, or are desired to run. For API simplicity this variable is read-only, if you wish to alter the list of all jobs re-instantiate this class please.
Map from job name to JobState that encodes the state of each job.
metadata object associated with this session state.
Signal sent whenever a job is added to the session.
This signal is fired after on_job_state_map_changed()
Signal sent whenever a job is removed from the session.
This signal is fired after on_job_state_map_changed()
Signal fired after a job get changed (set)
This signal is fired each time a result is presented to the session.
This signal is fired after on_job_state_map_changed()
Signal fired after job_state_map is changed in any way.
This signal is always fired before any more specialized signals such as on_job_result_changed() and on_job_added().
This signal is fired pretty often, each time a job result is presented to the session and each time a job is added. When both of those events happen at the same time only one notification is sent. The actual state is not sent as it is quite extensive and can be easily looked at by the application.
Map from resource name to a list of resource records
List of jobs that were intended to run, in the proper order
The order is a result of topological sorting of the desired_job_list. This value is recomputed when change_desired_run_list() is called. It may be shorter than desired_run_list due to dependency errors.
Add or change a resource with the given name.
Resources silently overwrite any old resources with the same name.
Discard jobs that are selected by the given qualifier.
Parameters: | qualifier – A qualifier that selects jobs to be removed |
---|---|
Ptype qualifier: | |
IJobQualifier | |
Raises ValueError: | |
If any of the jobs selected by the qualifier is on the desired job list (or the run list) |
This function correctly and safely discards certain jobs from the job list. It also removes the associated job state (and referenced job result) and results (for jobs that were resource jobs)
Update the set of desired jobs (that ought to run)
This method can be used by the UI to recompute the dependency graph. The argument ‘desired_job_list’ is a list of jobs that should run. Those jobs must be a sub-collection of the job_list argument that was passed to the constructor.
It never fails although it may reduce the actual permitted desired_job_list to an empty list. It returns a list of problems (all instances of DependencyError class), one for each job that had to be removed.
Notice the specified test result and update readiness state.
This function updates the internal result collection with the data from the specified test result. Results can safely override older results. Results also change the ready map (jobs that can run) because of dependency relations.
Some results have deeper meaning, those are results for local and resource jobs. They are discussed in detail below:
Resource jobs produce resource records which are used as data to run requirement expressions against. Each time a result for a resource job is presented to the session it will be parsed as a collection of RFC822 records. A new entry is created in the resource map (entirely replacing any old entries), with a list of the resources that were parsed from the IO log.
Local jobs produce more jobs. Like with resource jobs, their IO log is parsed and interpreted as additional jobs. Unlike in resource jobs local jobs don’t replace anything. They cannot replace an existing job with the same name.
alias of SessionStateLegacyAPICompatImpl
Abstraction for storage area that is used by SessionState to keep some persistent and volatile data.
This class implements functions performing input/output operations on session checkpoint data. The location property can be used for keeping any additional files or directories but keep in mind that they will be removed by SessionStorage.remove()
This class indirectly collaborates with SessionSuspendHelper and SessionResumeHelper.
Forcibly unlock the storage by removing a file created during atomic filesystem operations of save_checkpoint().
This method might be useful if save_checkpoint() raises LockedStorageError. It removes the “next” file that is used for atomic rename.
Create a new SessionStorage in a random subdirectory of the specified base directory. The base directory is also created if necessary.
Parameters: |
|
---|
Note
Legacy mode is where applications using PlainBox API can only handle one session. Creating another session replaces whatever was stored before. In non-legacy mode applications can enumerate sessions, create arbitrary number of sessions at the same time and remove sessions once they are no longer necessary.
Legacy mode is implemented with a symbolic link called ‘last-session’ that keeps track of the last session created using legacy_mode=True. When a new legacy-mode session is created the target of that symlink is read and recursively removed.
Load checkpoint data from the filesystem
Returns: | data from the most recent checkpoint |
---|---|
Return type: | bytes |
Raises: |
|
location of the session storage
Remove all filesystem entries associated with this instance.
Save checkpoint data to the filesystem.
The directory associated with this SessionStorage must already exist. Typically the instance should be obtained by calling SessionStorage.create() which will ensure that this is already the case.
Raises: |
|
---|
pathname of the session state file
Helper class to enumerate filesystem artefacts of current or past Sessions
This class collaborates with SessionStorage. The basic use-case is to open a well-known location and enumerate all the sessions that are stored there. This allows to create SessionStorage instances to further manage each session (such as remove them by calling :meth:SessionStorage.remove()`)
Compute the default location of the session state repository
Returns: | ${XDG_CACHE_HOME:-$HOME/.cache}/plainbox/sessions |
---|
Find the last session storage object created in this repository.
Returns: | SessionStorage object associated with the last session created in this repository using legacy mode. |
---|
Note
This will only return storage objects that were created using legacy mode. Nonlegacy storage objects will not be returned this way.
Enumerate stored sessions in the repository.
If the repository directory is not present then an empty list is returned.
Returns: | list of SessionStorage representing discovered sessions |
---|
pathname of the repository