Open nvallinoto opened 1 year ago
Hi @nvallinoto ,
I think this is a new funcionality that can be really nice.
Things to consider:
from: email, bla@bla.com, to: username: 12345678
. This web service will end instantly.from: email, bla@bla.com, to: username: 12345678
. So, this would answer something like: not processed, yet; in progress; concluded: with success|error, and attaching the logs.Web services as such would be easy to implement. The key issue is to adapt the plugin to support them.
Hi @jpahullo, thanks for your suggestions. I could try to implement it although this is my first time writing a web service for moodle. If you can drive me I can try. The problem as I can see is that the plugin doesn't have a queue system but executes immediately the users' merging. So we need to modify quite heavily the plugin adding new functions to enable the asynchronous processing you proposed .. don't know if I'm able to arrive to the end.
Hi @nvallinoto !
No worries. We agree: The big issue is changing from synchronous to async merging users.
It is also interesting for our institution, so sooner or later, queueing merging request will land over here.
Thanks for your comments and suggestions.
Hi @jpahullo, if we are going in the direction to create a web service (sooner or later) following your suggestion to enable asynchronous processing I think could be useful to indicate a road map with the main functions (with input and output) to be write in order to abilitate the plugin to work in a such way. Could you start to write a draft document with these steps/pieces of software needed (I imagine that some of the existing code could be reused) ? In this way me or some else interested in this new functionality can start to work on it. What do you think ?
It is a good idea, @nvallinoto. Thanks for the proposal. When I was able to write it, I'll do. I think it would be something like a list of tasks posted here.
Finally, the action to merge two users is done by a specific function call. So, all the new parts would be new code, and then the adhoc task would be calling this function. Mainly.
Thanks a lot for the idea!
Hi @jpahullo, if and when you will have time could be the best way to proceed because you are the one who knows better the merge user accounts plugin.
The working path to implement a new webservice for merging users could be as follows:
Previous considerations:
from: email, bla@bla.com, to: username: 12345678
. This web service will end instantly. It could return an id
for the merging request, which could be used afterwards for its status. Otherwise, any error would be exposed. We could name it as merging request id
. Thinking about it, better to return an id
, given that we could queue several request with the same data fields.merging request id
. So, this would answer something like: not processed, yet; in progress; concluded: with success|error, and attaching the logs.So, for the part of web services on its own:
queue_merging_request
:
username
, id
, idnumber
or any other value currently supported.get_status_for_merging_request
:
queue_merging_request
We could think about this statuses (the seen number from the ordered list could be the status id):
To just implement those web services, you could even not interact with a real merging request, just return a predefined skeleton. For instance:
queue_merging_request
return always id 1.get_status_for_merging_request
you could return a predefined structure (like if it was sucessful, for instance) only when asking for id 1. Any other id would return the message with missing merging request id.For how to implement web services on Moodle in any plugin, please follow the official documentation from Moodle, and check existing web services implementation.
About users and tokens: This functionality is very sensitive, so we should add a comment on the README.md for asking Moodle administrator to build a new token for this web service manually via web. That generated token should be pass with a full URL to both web services to the client side, so that they can ask for merge users. We can also add a note that IT service to firewall those calls allowing them only from the specific client side and to the Moodle URL.
This would be a great effort for having those web services implemented.
For a real merging request implementation (queue, scheduled tasks and so on), we would only need to replace the code that generates the predefined code dealing with a real data model (new tables on databases and so on).
Missing drafts are:
Hi @nvallinoto,
I've done some kind of drafts as comments on this issue. I think the one about web services would be sufficient to start with.
Thanks!
Hi @jpahullo, impressive list of things to do. Are there any activities concerning the database too or the queue of merging requests is managed by existing tables?
ehehehe, if you read it with calm, you can see that there must be changes on the tables related to this plugin. Mainly the one is related to the queue of merging requests, that I think should be the combination of the data fields related for a merging request and the current information existing on the merging logs (see my last comment about it).
But to just get working web services, without login in the background, you can implement it without touching anything of the plugin itself.
Thanks to you @nvallinoto !
ehehehe, if you read it with calm, you can see that there must be changes on the tables related to this plugin. Mainly the one is related to the queue of merging requests, that I think should be the combination of the data fields related for a merging request and the current information existing on the merging logs (see my last comment about it).
you are right .. in the final point of the missing draft.
dear all,
I would like to start developing the new web services with the proposals made by Jordi. Before starting I'll share in this thread a diagram summarizing the contents of this possible improvement of the plugin in order to collect any further suggestions.
Nicola
20230216_EN_WebServices_MergeUserAccounts.pdf
This is the diagram of the proposed web services for Merge user accounts plugin.
Please have a look and react with your critics and improvements.
@jpahullo I followed your suggestions.
Hi!
thanks for sharing your thoughts and proposal.
Regarding the pdf schema: it’s very good in the overall.
There are a couple of things I’d suugest or ask though:
As I said, all is pretty pretty good. Good job!
Hi, thank you very much for your suggestions. The point 1) is ok for me. Regarding the point 2) what is the content of the log field? I will update the diagrams. Nicola
The column logs
contain information related to time started and end of the merging operation, as well as all those SQL sentences executed. It is a column of type text field and its content is a JSON, with an array of strings, one array position per every log operation during the execution of the merging operation. For the purpose of the diagram, it will be sufficient to add the column logs
, as the rest of the fields.
Thanks!
Hi @jpahullo, in attachment you will find the updated diagram of the new web services with your last replies. 20230222_EN_WebServices_MergeUserAccounts.pdf If no other suggestions is arriving I would like to start to write some code. Which is your suggestions to start (just to fork the last version and starting to develop at local server )? Nicola
Hi @nvallinoto,
I think it is better now.
Today I realized that two web services were somehow overlapping each other: the two get_…
I think we can just keep the last one, more versatile, and the one really necessary. With that one, we can still ask for an id, and it will return an empty list or just a list with one item.
That’s my opinion.
You can start developing as you say. That’s perfect.
Work first on the web services part as I suggested. Leave the conversion of current merging into scheduled and adhoc tasks for the last.
Let’s go!!
you are right the second web service is included in the third one. I removed the second one 20230224_EN_WebServices_MergeUserAccounts.pdf . Here the new updated diagram.
Let’s go!!!!
Hi @jpahullo, I wrote the interface of the two API: queue_merging_request and get_queue_list_merging_request Now I see them in the API documentation moodle page. / Next step is the creation of Moodle table to manage the queue of the merging requests. I have a question: how to add a sequence in file install.xml inside db folder ? In attachment mergeusers_api_table.txt you will find the possible content of the update.xml file. Thanks, Nicola
Hi @nvallinoto ,
Thanks for working on it. Thanks a lot.
I revisited your xmldb file. In general, it seems pretty good. the indexes for both values will help a lot if we allow admins to search requests through the queue.
I also need to make some comments:
removeuservalue
and keepuservalue
are arbitrarily of varchar(30)
. Why? I can see that user.idnumber
is a varchar(255)
. So we have to update them to that maximum.removeuserid
and keepuserid
: these two fields has the whole sense when an admin is using the current plugin web for searching and defining the couple of users to merge. So, when using the current plugin web all 6 fields will be populated by the web form. This is not something you have to do, but we need to consider right now. In other case, both fields can be perfectly null
. When merging the users, the process could also update these fields to set them up with the proper user.id
too.retries
as stated in the above comment. It is necessary since the adhoc task that will process the request, need to account how many retries exist for this request. Moodle retry any failing adhoc task since it finishes with success. We will need to adjust this default behaviour by managing the number of retries internally.statusdescription
as a storage of a key from a internationalized string. However, we can build that string using the status
code, and having internationalized string like $string['status_1_description'] = "Request queued";
for a $status = 1
, and so on. Then, we can safely remove the field statusdescription
. Just as an additional comment:
For web services and CLI processes may be able to have certain search criteria, I mean, a certain value pair {removeuserfield + removeuservalue} and/or {keepuserfield + keepuservalue} that may return more than a user record. In those cases, the request cannot continue and have to abort, without any retry. Just abort. This is a new state that we have to consider for the field status
.
Consider only those details that affect to your development. I provides a lot of details and "why"s, to help you understand what we are looking for behind any decision.
Thanks again,
Jordi
Hi @jpahullo,
thanks a lot for your very useful comments. I introduced all of your suggestions in database schema.
You will find it in attachment.
20230320_mergeusers_api_table.txt
In my previous comment I asked how (if it is possible) add a sequence in the schema.
The field id has a related sequence
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true" NEXT="removeuserfield"/>
The question is where and how to define the sequence in order to be created when you'll install or update the plugin ?
You need to create it manually in the database ?
I have seen other examples of install.xml in Moodle code but the sequence are not present.
Nicola
Hi @jpahullo,
I have updated the diagram 20230317_Moodle_MergeUserAccounts_API.pdf with the two web services following the last suggestions regarding the columns definition of the new Moodle table.
I have seen your request on Telegram channel (https://t.me/moodledev/122358).
I wrote the name of the web service functions in admin/tool/mergerusers/db/services.php
and the related methods in admin/tool/mergerusers/classes/external.php
I don't know if the way I just described is the component_class_callback (IIRC) or the subplugin mode to do it.
After that I wrote a new table to be added to the file
admin/tool/mergerusers/db/install.xml for a fresh install of the plugin and to the admin/tool/mergerusers/db/upgrade.php
for a plugin's update. I already tried to update the Moodle database using the upgrade.xml file but after adding +1 to $plugin->version in version.php the new table hasn't created.
Nicola
Hi @nvallinoto ,
Thanks for the work. The table schema seems ok for me.
The XML file should be db/install.xml, produced by the XMLDB Editor, as you did.
The upgrade file should be db/upgrade.php. See this plugin or other plugins on how to perform that. Also, XMLDB Editor helps you producing the PHP code for the upgrade.php.
However, you have to think on this: any Moodle instance that is having this plugin already installed, db/upgrade.php must produce the specific new table schema, and all existing data migrated. So, you have to think on a process for the db/upgrade.php to pass the table and any existing data from the table named tool_mergeusers
to the tool_mergeusers_queue
, so that no data is lost.
This change is a big change, so take care on producing the db/upgrade.php. Also, the table schema is not the same, so there would be empty/null fields, like for the removeuserfield and removeuservalue and the equivalent for the keepuserfield and keepuservalue. timecreated and timemodified would be the same. success field would be encoded as the corresponding status code. And the log field will be kept. You can imagine a process of producing a new fresh table and migrating the whole data or renaming the existing table and producing the changes column by column.
In the end, we have to consider the observers too, so that the success and failing merging operations trigger the corresponding events.
All this is a lot of work. But I think you'd better build your part for the queue table, necessary for your webservices, produce tests, and then go on for the rest of the changes, if you are able to.
Any little contribution will be very welcome.
Last, but not least: your questions:
Thanks again,
Jordi
at the moment I will continue to develop without thinking to the data to be exported from the actual table to the new one. I have one more detailed question concerning the sequence. After the table is created a sequence is created automatically with the definition "sequence = true" or I need to create manually ? I had a look to the database and there are as many sequences (in folder sequences) as tables with a sequence. All tables have sequence.
No no, as I said, the id
column is per se an auto-increment index. You have to do nothing, but install/generate that table. As simple as that.
Thanks
I created the table _tool_mergeusersqueue using upgrade.php and I have seen that magically the sequence tool_mergeusers_queue_id_seq was created too. Well. Let's go on.
the first web service tool_mergeusers_enqueue_merging_request is working well. I added the values of the two fields removeuserid and keepuserid too.
Congrats! Go, go go!
refining the web service perhaps could be better to handle errors as written in this documentation page https://docs.moodle.org/dev/Errors_handling_in_web_services ? Do you have a simple example of it ?
What do you mean by "refining web services... to handle errors"?
In general, if some error occurs during the execution of the web service, it must behave as nothing happened and returning the error back to the client.
As the documentation states, if during the execution of the web service, an exception is through (anything being or extending moodle_exception()) will automatically fill the error fields and details back to the client.
So, in your web service implementation, you only need to through a new moodle_exception whenever necessary. The rest is managed by Moodle for you.
So, for instance, queueing a new merge request should happen always. Always i always. It's only adding a record into the table. That's it. Nothing else. So, it will happen always EXCEPT the moodle database is unaccessible or the table does not exist (for any reason). In that case I think Moodle would throw an exception automatically, so you should not have to take care of it.
For the other web service, asking the status of a given merge request should behave similarly as before. This web service only asks for the status of a given record or records.
Thanks for the work,
Jordi
Thank you for your comment about the way moodle works to raise exception from server to the client. Concerning the other web service we decided to include the second in the last one (more inclusive and just not to have two web services with same results in part). So the other web service will return an object that is a list. Have a look to the last diagram https://github.com/ndunand/moodle-tool_mergeusers/files/11019158/20230317_Moodle_MergeUserAccounts_API.pdf and let me know if it's ok for you.
Yes @nvallinoto , all is ok.
My words were thinking on this lasr change: in total we have 2 web services.
The second one returns always a list. But we know that if we asked for a request id, the list eill be empty or just one item. Instead, if we asked by a given username, the list could be empty, containing one or more elements in the list.
Thanks!!!
Hi Jordi, I terminated the second web service. I need only to validate the array with the parameters but the rest is working well and I added as optional parameters the removeuserid and keepuserid too! Next week I'll start the task process.
Good to know!
Before going on the task part, consider, please, adding some tests for the web services logic.
New code should be accompanied with tests.
Thanks for the work @nvallinoto
Hi, I did some tests using postman. Or you mean other type of test ? in the case how to add them to plugin ? Nicola
Yeah, postman, curl, etc are good at manual testing. And they are good!
What I mean is adding phpunit or behat tests. There are some added already to the plugin (see directory tests/). How to pass/execute them? You need to look for it on the moodledev docs site.
These tests are also code delivered within the plugin, that says what is expected to happen.
In your case, for this part of web services, you do not need to test the whole web service invocation, but only test the logic of inserting the record in the table and the one getting some records from the queue table, respectively.
If you link me here the branch in your repo, I could help you a bit more with my explanations.
Again, thanks!!!!
Jordi
ok I will have a look to directory /test to understand how to add phpunit or behat tests for a plugin. As soon as I copy the plugin code in my repo I will let you know.
Hi Jordi, you will find the file added or modified here https://github.com/nvallinoto/moodle-tool_mergeusers (version.php, CHANGES.md, db/services.php, db/upgrade.php, classes/external.php) Nicola
Updated diagram (28.03.23) of API Moodle interface to extend the plugin Merge user account
Hi Jordi,
following the diagram (https://github.com/ndunand/moodle-tool_mergeusers/files/11088703/20230328_Moodle_MergeUserAccounts_API.pdf) I wrote the _get_queue_mergingrequest task and now I need your help to define the adhoc task _merge_useraccounts
class merge_user_accounts extends \core\task\adhoc_task {
/**
* Execute the task.
*/
public function execute($usertokeep, $usertoremove) {
// do the real merge user accounts
}
}
Hi @nvallinoto ,
If you have implemented the web services, this would conclude in a PR to solve this issue.
Prior resolving this issue, we should do an upgrade process of any existing log into the new table of merge requests.
This wouldn't be integrated into master, but into another different branch (this will be my job), since it will be a work-in-progress branch to include all changes from web services + tasks, to adapt completely the current behaviour into merge requests and tasks.
Then, the part of scheduled tasks + adhoc tasks comes on #207. So, comments on scheduled tasks will be on #207 now on.
Thanks a lot,
Jordi
Regarding the webservices the right conclusion needs the test part to be included. Any help is welcome because it's my first attempt to do it. Any suggestion is welcome. Concerning the update process (moving the log to the new table) can you describe it better ? Thanks for all.
You're right about tests. I let you know @nvallinoto about your doubts. I have to go now.
Thanks a lot,
Jordi
Hi @jpahullo in order to implement the web service in the correct way you wrote that "we should do an upgrade process of any existing log into the new table of merge requests." (https://github.com/ndunand/moodle-tool_mergeusers/issues/218#issuecomment-1491811363) Are correct the following links between the table "tool_mergeusers" fields and the new one ?
Hi @jpahullo, I've updated the diagram which summarizes graphically the way I've followed in writing the code. 20230403_Moodle_MergeUserAccounts_API.pdf Please let me know if it makes sense for you. Nicola
Hi @nvallinoto,
Regarding to the migration process:
completedtime
in your new schema.Thanks a lot,
Jordi
Hi all, I'm working on moodle development through an external application using web services to add new user (core_user_create_users), to enrol users (enrol_manual_enrol_users), to get users' grades (gradereport_overview_get_course_grades) and so on. All is working well. Now I need to use merge user accounts plugin not only via admin interface but also through the external application. According to your experience is it possible to create a web service for Merge user accounts plugin ? Which are the possible critical issues ? Thanks.