-
Improvement
-
Resolution: Fixed
-
Minor
-
2.8.11, 2.9.5, 3.0.3
-
None
-
MOODLE_28_STABLE, MOODLE_29_STABLE, MOODLE_30_STABLE
-
MOODLE_28_STABLE, MOODLE_29_STABLE, MOODLE_30_STABLE
5.1 WHY WE NEED IN PLUGIN
Locking is required whenever we need to prevent 2 processes from accessing the same resource at the same time. The prime candidate for locking in the mhaairs plugin is grade category create/update via the grade update web service calls during grade sync.
For each grade item the sync sends one grade item update request and then a grade update request for each student. The grade updates are synchronous. Parallelism comes into play when we have multiple grade items in the same sync. We may get a conflict issue when sending two (or more) assignments from Connect in the same sync bulk, all having the same category which does not yet exist in Moodle. MH Campus has multiple servers, so the grade item updates get processed in parallel. They get to Moodle at the same time, and get processed in Moodle in parallel as well. We get race condition when two processes try to create the same category at the same time.
5.2 PLUGIN SUPPORT
A locking component is incorporated in the plugin. It includes file locking and redis locking, configurable in the plugin site settings. It also includes cli for resetting locks.
5.3 MOODLE LOCK API FROM 2.7
Moodle 2.7 introduces a locking api (https://docs.moodle.org/dev/Lock_API) for critical tasks (e.g. cron). The default locking system to use is DB locking for Postgres, and file locking for MySQL, Oracle and SQLServer. If $CFG->preventfilelocking is set, then the default will always be DB locking. It can be manually set to one of the lock factory classes listed below, or one of your own custom classes implementing the \core\lock\lock_factory interface.
// $CFG->lock_factory = "auto";
The list of available lock factories is:
• “\\core\\lock
file_lock_factory" - File locking. Uses lock files stored by default in the dataroot. Whether this works on clusters depends on the file system used for the dataroot.
• "\\core\\lock
db_record_lock_factory" - DB locking based on table rows.
• "\\core\\lock
postgres_lock_factory" - DB locking based on postgres advisory locks.
See config-dist.php for details on settings used by the lock factories and customization of the list of supported file types.
5.4 TRANSITION TO MOODLE’S LOCK API
The transition to Moodle’s lock API consists of the following:
• Removal of the lib/lock folder which contains the plugin’s local lock classes.
• Removal of the cli folder which contains the cli script for resetting locks.
• Removal of the settings ui for selecting the lock type and its lang strings.
• Adding adhoc task for adding the category and updating the grade item in the background.
• Adjusting the plugin’s gradebook service to execute the task when the requested category doesn’t exist.
• Plugin upgrade to remove config setting block_mhaairs_locktype.
• Unit testing.
• Acceptance testing.
For using redis locking after transition (requires Moodle 2.9 or higher) see moodle-local_redislock/README.md.
5.5 UNIT TESTING
5.5.1 test_update_item_new_category
Tests the gradebookservice update grade function for adding an item in a new category. The test creates two grade items which are assigned to the same new category. The category is created during the first update.
5.5.2 test_update_item_multiple_categories
Tests the gradebookservice update grade function for adding an item in a category, where multiple categories with the same name already exist. The item should be assigned to the oldest category. When moved to a category with a different name, the item should be assigned to the new category. No tasks should be created and no locking should be triggered.
5.6 ACCEPTANCE TESTING
5.6.1 The configuration settings for lock type does not exist.
5.7 NOT TESTED
1. We don't test lock activated.
2. We do not need to test lock release specifically because if a lock fails to release it will throw coding exception in unit testing.