This project is an attempt at implementing a conformant IEEE Std 9274.1.1, IEEE Standard for Learning Technology— JavaScript Object Notation (JSON) Data Model Format and Representational State Transfer (RESTful) Web Service for Learner Experience Data Tracking and Access 2.0.0 LRS.
There are 3 main modules in this project that cover:
data
– the data structures involved,db
– their Data Access Objects for storing in, and fetching them from a database, and finallylrs
– a Web server to handle the LRS calls proper.
Changes are tracked in ChangeLog.
Users of this project, at this stage, are expected to be mostly developers or system administrators planning on setting up an LRS to integrate with an LMS (Learning Management System) or other learning experience related systems --see here for various examples and definitions. The jargon i'll use here then is for those user profiles.
The main software components required to make use of this project are:
-
Rust
The produced binaries (debug and release versions) can run directly on their own. However b/c this is a Web Server that stores users' data locally, produces logs, etc... deployment is not as straightforward as installing and using a command line utility. A good guide on how to do that I would suggest is Rocket Guide - Deploying.
In addition if you plan on contributing to the project, and locally testing changes etc... including passing conformance tests you'll need to install Rust.
-
PostgreSQL
As mentioned in the documentation, this project relies on an installed PostgreSQL database system. FWIW, as of the last edit date of this document, the version of PostgreSQL was 16.3.
You will need to configure a user w/ enough permissions to create databases and tables on the node where the RDBMS is running.
-
Node.js
To locally run the CTS you'll need to install Node.js and configure LaRS to be efficiently used for this use-case --see the Conformance Tests section later in this document.
-
nginx (or another HTTP Proxy server)
I developed and tested this project running it behind an
nginx
proxy in turn behind a firewall. This setup delegates the security, TLS handshakes + Certificates handling, and outside access to the nginx proxy server, which then allows running LaRS in HTTP mode securely.Of course other proxy servers can be used such as Apache
httpd
but nowadays,nginx
is my preferred goto for these use-cases.
You should copy the two .env.template
and Rocket.toml.template
files and rename them removing the .template
suffix.
These files are expected to contain sensitive information particular to your environment. They should be already included in the .gitignore
file but it's a good idea to double-check.
You should also carefully inspect and set the variables in those files to accurately reflect your setup + environment. Hopefully the comments in .env.template
should make this easy. The Rocket.toml
as its name implies is a Rocket specific configuration file. It is documented here.
When you run LaRS for the first time it will create two folders named static
and logs
under the project's home-dir —which in development is the CARGO_MANIFEST_DIR
.
The static
folder will contain files that store xAPI Attachments, Statements, and JWS Signatures received by way of PUT
and POST
HTTP Requests having multipart/mixed
content type.
The logs
folder will contain log files that capture the tracing output of the server.
This project passes the LRS Conformance Tests Suite (CTS) found here w/ caveats. Here's the output of the first time it did:
{
"name": "console",
"owner": null,
"flags": {
"endpoint": "http://localhost:9000"
},
"options": {},
"rollupRule": "mustPassAll",
"uuid": "101cae0f-785d-4cbe-9de0-30b29f973647",
"startTime": 1732158267726,
"endTime": 1732158306773,
"duration": 39047,
"state": "finished",
"summary": {
"total": 1442,
"passed": 1442,
"failed": 0,
"version": "2.0.0"
}
}
The CTS when run locally requires the following patch (to the helper.js
file) and adjustment to the server's configuration. The patch for the helper.js
eliminates the TIME_MARGIN
constraint.
The server configuration adjustments deal with modifying the .env
parameters to run the server locally. These modifications are:
DB_STATEMENTS_PAGE_LEN = 2
LRS_EXTERNAL_URL="http://localhost:9000/"
RUST_LOG="info,xapi_rs=debug"
The first limits the number of Statements to include in a StatementResult to only 2. Given that the tests rely on a setup preamble of one or two known Statements the limit of 2 for DB_STATEMENTS_PAGE_LEN
ensures that no more than 2 calls are made to LaRS before the test receives the expected result.
The second is used by LaRS for populating the more
property of a StatementResult which the test may invoke when an earlier response did not contain the expected Statement.
The last parameter ensures maximum verbosity in the logs which should help tracking what LaRS is emitting in response to CTS requests.
Finally to run the CTS, on LaRS side, open a command line console and enter:
$ sqlx db drop ↵
Drop database at <DB_SERVER_URL/DB_NAME>? (y/n): y ↵
$ sqlx db create ↵
$ cargo run --release ↵
And on the CTS side, enter:
$ node bin/console_runner.js -e <LRS_EXTERNAL_URL> -x 2.0.0 -z ↵
The DB_SERVER_URL
, DB_NAME
, and LRS_EXTERNAL_URL
should be the same as set in .env
.
In no particular order...
- Pass the conformance tests. Done 2024-11-21.
- Implement a Job scheduler to clean temporary database Views created when a GET request leads to more results that can fit into a page. Done 2024-12-04.
- Clean up temporary files created when generating multipart response. Done 2024-12-09.
[ ] Removespeedate
and re-write usingchrono
.
NOTE (rsn) 20241220 - I'm not sure anymore about this. The amount of work to correctly parse an ISO Duration, and the total space savings of 33KB from a binary that's around 46MB, is IMO not worth it.- If the JWS header (of a signed Statement) includes an X.509 certificate, we should validate the signature against that certificate as defined in JWS. We don't do that yet.
- Introduce a configuration option to allow setting either a time or size limits on assets stored in
static
. - Optimize Pg SQL queries --may be using CTEs.
- Minimize memory allocation by reducing the use of
String
types especially in custom deserializer implementations --e.g. consider usingDeserializeSeed
. - Add support for Authentication.
- Add support for Authorization.
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.