Skip to content

Commit 8e5d2a0

Browse files
authored
xAPI 2.0 Support (#477)
1 parent 7472d41 commit 8e5d2a0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+870
-457
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
# Version of LRS Admin UI to use
44

5-
LRS_ADMIN_UI_VERSION ?= v0.2.5
5+
LRS_ADMIN_UI_VERSION ?= v0.2.6
66
LRS_ADMIN_UI_LOCATION ?= https://github.com/yetanalytics/lrs-admin-ui/releases/download/${LRS_ADMIN_UI_VERSION}/lrs-admin-ui.zip
77
LRS_ADMIN_ZIPFILE ?= lrs-admin-ui-${LRS_ADMIN_UI_VERSION}.zip
88

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ For releases and release notes, see the [Releases](https://github.com/yetanalyti
5252
- [Reactions](doc/reactions.md)
5353
- [JSON Spec](doc/reactions/spec.md)
5454
- [Sending xAPI statement(s) with Postman](doc/postman.md)
55+
- [xAPI Versioning](doc/xapi_versioning.md)
5556

5657
### Demos
5758

deps.edn

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,12 @@
5353
xyz.capybara/clamav-client {:mvn/version "2.1.2"}
5454
;; Yet Analytics deps
5555
com.yetanalytics/lrs
56-
{:mvn/version "1.3.1"
56+
{:mvn/version "1.4.0"
5757
:exclusions [org.clojure/clojure
5858
org.clojure/clojurescript
5959
com.yetanalytics/xapi-schema]}
6060
com.yetanalytics/xapi-schema
61-
{:mvn/version "1.4.0"
61+
{:mvn/version "1.4.1"
6262
:exclusions [org.clojure/clojure
6363
org.clojure/clojurescript]}
6464
com.yetanalytics/colossal-squuid
@@ -72,7 +72,7 @@
7272
:exclusions [org.clojure/clojure
7373
buddy/buddy-sign]}
7474
com.yetanalytics/lrs-reactions
75-
{:mvn/version "0.0.1"
75+
{:mvn/version "0.0.3"
7676
:exclusions [org.clojure/clojure]}
7777
com.yetanalytics/gen-openapi
7878
{:mvn/version "0.0.4"
@@ -136,7 +136,7 @@
136136
:git/sha "3f288f1f16d167723ad87cc35b1dfee3c1681e10"}
137137
com.yetanalytics.lrs/test-runner
138138
{:git/url "https://github.com/yetanalytics/lrs-test-runner.git"
139-
:git/sha "8bd5be7816288e85f5c07fc11bf8cf53667e72da"
139+
:git/sha "1891bb5c8802a397ffaee86d336ee95d71cc1a4d"
140140
:exclusions [org.clojure/data.json]}
141141
com.yetanalytics/datasim
142142
{:mvn/version "0.4.4"

doc/env_vars.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@ The following options are used for advanced database performance tuning and may
110110
| `LRSQL_STMT_RETRY_BUDGET` | `stmtRetryBudget` | The max amount of time allowed for statement POST transaction retries before failing (ms). | `1000` |
111111
| `LRSQL_ENABLE_REACTIONS` | `enableReactions` | Whether or not to enable statement reactions. | `false` |
112112
| `LRSQL_REACTION_BUFFER_SIZE` | `reactionBufferSize` | Number of pending reactions to allow. Additional reactions will be dropped with a warning message. | `10000` |
113+
| `LRSQL_REACTION_VERSION` | `reactionVersion` | The xAPI version used when the reactor emits statements. Must be either `1.0.3` or `2.0.0`. | `1.0.3` |
114+
| `LRSQL_SUPPORTED_VERSIONS` | `supportedVersions` | A comma-separated list of supported xAPI versions. This is used to validate incoming requests and ensure compatibility. | `1.0.3,2.0.0` |
115+
| `LRSQL_ENABLE_STRICT_VERSION` | `enableStrictVersion` | Whether or not to enable strict versioning. When enabled, GET requests for statements using a 1.0.3 header will convert 2.0.0 statements by removing or normalizing fields. | `false` |
113116

114117
_NOTE:_ `LRSQL_STMT_RETRY_LIMIT` and `LRSQL_STMT_RETRY_BUDGET` are used to mitigate a rare scenario where specific Actors or Activities are updated many times in large concurrent batches. In this situation the DBMS can encounter locking and these settings are used to allow retries that eventually write all the conflicting transactions, but may incur performance degradation. If you are experiencing this situation the first step would be to look at why your data needs to rewrite specific Actors or Activities rapidly with different values, which could potentially solve it at the source. If the issue cannot be avoided by data design alone, another possible solution is reducing batch sizes to decrease or eliminate locks. As a last resort, increasing these settings will at least ensure the statements get written but as mentioned may incur a slowdown in concurrent throughput.
115118

doc/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
- [Example AWS Deployment](aws.md)
3333
- [Reactions](reactions.md)
3434
- [Sending xAPI statement(s) with Postman](postman.md)
35+
- [xAPI Versioning](xapi_versioning.md)
3536

3637
### Demos
3738

doc/xapi_versioning.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
[<- Back to Index](index.md)
2+
3+
# xAPI Versioning
4+
5+
SQL LRS supports xAPI versions 1.0.3 and 2.0.0. The version used is determined by the `X-Experience-API-Version` header in the request. Use the LRSQL_SUPPORTED_VERSIONS environment variable or the `supportedVersions` LRS configuration property to set which versions are supported. By default, both versions are supported. For more information see [the configuration documentation](env_vars.md).
6+
7+
## Strict Versioning
8+
9+
Note that by default, responses to requests with an `X-Experience-API-Version` header set to `1.0.3` may contain statements in `2.0.0` format. To ensure that `2.0.0` statements are downgraded to `1.0.3` format use the `LRSQL_ENABLE_STRICT_VERSION` environment variable or the `enableStrictVersion` LRS configuration property. For more information see [the configuration documentation](env_vars.md).
10+
11+
## Reaction Versioning
12+
13+
Reactions generate version `1.0.3` statements by default but you can configure this by setting the `LRSQL_REACTION_VERSION` environment variable or the `reactionVersion` LRS configuration property. For more information see [the configuration documentation](env_vars.md). Note that creating reactions under `2.0.0` and then restricting the LRS to version `1.0.3` only will lead to errors in the LRS Admin UI frontend. To recover from this situation reenable `2.0.0` support and delete any incompatible reactions before returning to `1.0.3` only.
14+
15+
[<- Back to Index](index.md)

resources/lrsql/config/prod/default/lrs.edn

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,7 @@
1313
:stmt-retry-limit #or [#env LRSQL_STMT_RETRY_LIMIT 10]
1414
:stmt-retry-budget #or [#env LRSQL_STMT_RETRY_BUDGET 1000]
1515
:enable-reactions #boolean #or [#env LRSQL_ENABLE_REACTIONS false]
16-
:reaction-buffer-size #long #or [#env LRSQL_REACTION_BUFFER_SIZE 10000]}
16+
:reaction-buffer-size #long #or [#env LRSQL_REACTION_BUFFER_SIZE 10000]
17+
:reaction-version #or [#env LRSQL_REACTION_VERSION "1.0.3"]
18+
:supported-versions #or [#env LRSQL_SUPPORTED_VERSIONS "1.0.3,2.0.0"]
19+
:enable-strict-version #boolean #or [#env LRSQL_ENABLE_STRICT_VERSION false]}

resources/lrsql/config/test/default/lrs.edn

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,7 @@
1313
:stmt-retry-limit 20
1414
:stmt-retry-budget 10000
1515
:enable-reactions true
16-
:reaction-buffer-size 10000}
16+
:reaction-buffer-size 10000
17+
:reaction-version "1.0.3"
18+
:supported-versions "1.0.3,2.0.0"
19+
:enable-strict-version false}

src/db/mariadb/lrsql/mariadb/record.clj

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,10 @@
6868
(create-credential-table! tx)
6969
(create-credential-to-scope-table! tx)
7070
(create-blocked-jwt-table! tx))
71-
(-update-all! [_ _tx]
72-
; MariaDB is the latest database to get a SQl-LRS implementation, so no migrations are needed.
73-
; In the future migrations will go here.
74-
)
75-
71+
(-update-all! [_ tx]
72+
(when-not (= 1 (:has_context_agent (query-statement-to-actor-usage-enum-has-context-actors tx)))
73+
(alter-statement-to-actor-usage-enum-add-context-actors! tx)))
74+
7675
bp/BackendUtil
7776
(-txn-retry? [_ ex]
7877
(and (instance? java.sql.SQLException ex)
@@ -201,7 +200,7 @@
201200
;;;; So we don't actually store the JWT; we just store a (shorter) hash of it.
202201
;;;; Operations that don't interact with the jwt obviously don't need to hash it.
203202
;;;;
204-
203+
205204
bp/JWTBlocklistBackend
206205
(-insert-blocked-jwt! [_ tx input]
207206
(insert-blocked-jwt! tx (update input :jwt md/sha256-base64)))

src/db/mariadb/lrsql/mariadb/sql/ddl.sql

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,3 +273,34 @@ CREATE TABLE IF NOT EXISTS blocked_jwt (
273273
one_time_id CHAR(36) UNIQUE,
274274
KEY blocked_jwt_evict_time_idx (evict_time)
275275
);
276+
277+
/* Migration 2025-09-26 - Add ContextAgent, ContextGroup, SubContextAgent, SubContextGroup to statement_to_actor usage enum */
278+
279+
-- :name query-statement-to-actor-usage-enum-has-context-actors
280+
-- :command :query
281+
-- :result :one
282+
-- :doc Query to see if the `statement_to_actor.usage` column has ContextAgent in its enum.
283+
SELECT EXISTS (
284+
SELECT 1
285+
FROM INFORMATION_SCHEMA.COLUMNS
286+
WHERE TABLE_NAME = 'statement_to_actor'
287+
AND COLUMN_NAME = 'usage'
288+
AND FIND_IN_SET('ContextAgent', REPLACE(REPLACE(COLUMN_TYPE, 'enum(', ''), ')', '')) > 0
289+
) AS has_context_agent;
290+
291+
-- :name alter-statement-to-actor-usage-enum-add-context-actors!
292+
-- :command :execute
293+
-- :doc Change the enum datatype of the `statement_to_actor.usage` column to add ContextAgent, ContextGroup, SubContextAgent, and SubContextGroup.
294+
ALTER TABLE statement_to_actor MODIFY COLUMN `usage` ENUM ('Actor',
295+
'Object',
296+
'Authority',
297+
'Instructor',
298+
'Team',
299+
'SubActor',
300+
'SubObject',
301+
'SubInstructor',
302+
'SubTeam',
303+
'ContextAgent',
304+
'ContextGroup',
305+
'SubContextAgent',
306+
'SubContextGroup') NOT NULL;

0 commit comments

Comments
 (0)