Skip to content

Commit 9b3770a

Browse files
committed
feat: Upgrade event-routing-backends to v7.0.0
- Update xapi_events_all_parsed to parse the course id from new places due to changes in how multi-question problem_checks are handled.
1 parent 4466b09 commit 9b3770a

File tree

2 files changed

+122
-1
lines changed

2 files changed

+122
-1
lines changed

tutoraspects/plugin.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
"OPENEDX_EXTRA_PIP_REQUIREMENTS",
4242
[
4343
"openedx-event-sink-clickhouse==0.2.2",
44-
"edx-event-routing-backends==6.2.0",
44+
"edx-event-routing-backends==v7.0.0",
4545
],
4646
),
4747
("EVENT_SINK_CLICKHOUSE_MODELS", ["course_overviews", "user_profile"]),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
"""
2+
Update xapi_events_all_parsed_mv to parse the course id from
3+
new places due to changes in how multi-question problem_checks
4+
are handled.
5+
"""
6+
from alembic import op
7+
8+
revision = "0022"
9+
down_revision = "0021"
10+
branch_labels = None
11+
depends_on = None
12+
13+
DESTINATION_TABLE = "{{ ASPECTS_XAPI_DATABASE }}.{{ ASPECTS_XAPI_TABLE }}"
14+
TMP_TABLE_NEW = f"{DESTINATION_TABLE}_tmp_{revision}"
15+
TMP_TABLE_ORIG = f"{DESTINATION_TABLE}_tmp_mergetree_{revision}"
16+
on_cluster = " ON CLUSTER '{{CLICKHOUSE_CLUSTER_NAME}}' " if "{{CLICKHOUSE_CLUSTER_NAME}}" else ""
17+
old_engine = "ReplicatedMergeTree" if "{{CLICKHOUSE_CLUSTER_NAME}}" else "MergeTree"
18+
engine = "ReplicatedReplacingMergeTree" if "{{CLICKHOUSE_CLUSTER_NAME}}" else "ReplacingMergeTree"
19+
20+
21+
def upgrade():
22+
op.execute(
23+
"""
24+
SET allow_experimental_object_type=1;
25+
"""
26+
)
27+
op.execute(
28+
# There is not currently a "CREATE OR REPLACE MATERIALIZED VIEW..."
29+
f"""
30+
DROP VIEW IF EXISTS {{ ASPECTS_XAPI_DATABASE }}.{{ ASPECTS_XAPI_TRANSFORM_MV }}
31+
{on_cluster};
32+
"""
33+
)
34+
op.execute(
35+
f"""
36+
-- Materialized view that moves data from the raw table to processed table
37+
CREATE MATERIALIZED VIEW {{ ASPECTS_XAPI_DATABASE }}.{{ ASPECTS_XAPI_TRANSFORM_MV }}
38+
{on_cluster}
39+
TO {{ ASPECTS_XAPI_DATABASE }}.{{ ASPECTS_XAPI_TABLE }}
40+
AS
41+
SELECT
42+
event_id as event_id,
43+
JSON_VALUE(event_str, '$.verb.id') as verb_id,
44+
COALESCE(
45+
NULLIF(JSON_VALUE(event_str, '$.actor.account.name'), ''),
46+
NULLIF(JSON_VALUE(event_str, '$.actor.mbox'), ''),
47+
JSON_VALUE(event_str, '$.actor.mbox_sha1sum')
48+
) as actor_id,
49+
JSON_VALUE(event_str, '$.object.id') as object_id,
50+
-- If the contextActivities parent is a course, use that. It can be a "course"
51+
-- type, or a "cmi.interaction" type for multiple question problem submissions.
52+
-- Otherwise use the object id for the course id.
53+
multiIf(
54+
-- If the contextActivities parent is a course, use that
55+
JSON_VALUE(
56+
event_str,
57+
'$.context.contextActivities.parent[0].definition.type'
58+
) = 'http://adlnet.gov/expapi/activities/course',
59+
JSON_VALUE(event_str, '$.context.contextActivities.parent[0].id'),
60+
-- Else if the contextActivities parent is a GroupActivity, it's a multi
61+
-- question problem and we use the grouping id
62+
JSON_VALUE(
63+
event_str,
64+
'$.context.contextActivities.parent[0].objectType'
65+
) in ('Activity', 'GroupActivity'),
66+
JSON_VALUE(event_str, '$.context.contextActivities.grouping[0].id'),
67+
-- Otherwise use the object id
68+
JSON_VALUE(event_str, '$.object.id')
69+
) as course_id,
70+
get_org_from_course_url(course_id) as org,
71+
emission_time as emission_time,
72+
event_str as event_str
73+
FROM {{ ASPECTS_XAPI_DATABASE }}.{{ ASPECTS_RAW_XAPI_TABLE }};
74+
"""
75+
)
76+
77+
78+
def downgrade():
79+
op.execute(
80+
"""
81+
SET allow_experimental_object_type=1;
82+
"""
83+
)
84+
op.execute(
85+
# There is not currently a "CREATE OR REPLACE MATERIALIZED VIEW..."
86+
f"""
87+
DROP VIEW IF EXISTS {{ ASPECTS_XAPI_DATABASE }}.{{ ASPECTS_XAPI_TRANSFORM_MV }}
88+
{on_cluster};
89+
"""
90+
)
91+
op.execute(
92+
f"""
93+
-- Materialized view that moves data from the raw table to processed table
94+
CREATE MATERIALIZED VIEW {{ ASPECTS_XAPI_DATABASE }}.{{ ASPECTS_XAPI_TRANSFORM_MV }}
95+
{on_cluster}
96+
TO {{ ASPECTS_XAPI_DATABASE }}.{{ ASPECTS_XAPI_TABLE }}
97+
AS
98+
SELECT
99+
event_id as event_id,
100+
JSON_VALUE(event_str, '$.verb.id') as verb_id,
101+
COALESCE(
102+
NULLIF(JSON_VALUE(event_str, '$.actor.account.name'), ''),
103+
NULLIF(JSON_VALUE(event_str, '$.actor.mbox'), ''),
104+
JSON_VALUE(event_str, '$.actor.mbox_sha1sum')
105+
) as actor_id,
106+
JSON_VALUE(event_str, '$.object.id') as object_id,
107+
-- If the contextActivities parent is a course, use that. Otherwise use the object id for the course id
108+
if(
109+
JSON_VALUE(
110+
event_str,
111+
'$.context.contextActivities.parent[0].definition.type')
112+
= 'http://adlnet.gov/expapi/activities/course',
113+
JSON_VALUE(event_str, '$.context.contextActivities.parent[0].id'),
114+
JSON_VALUE(event_str, '$.object.id')
115+
) as course_id,
116+
get_org_from_course_url(course_id) as org,
117+
emission_time as emission_time,
118+
event_str as event_str
119+
FROM {{ ASPECTS_XAPI_DATABASE }}.{{ ASPECTS_RAW_XAPI_TABLE }};
120+
"""
121+
)

0 commit comments

Comments
 (0)