Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: rewrite forum payload to be sent to the event bus #447

Draft
wants to merge 21 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
7825196
feat: add support for Avro dict
Ian2012 Jun 7, 2023
9aaa04e
refactor: add support for dicts as avro maps instead of record
mariajgrimaldi Dec 12, 2024
743bcc4
test: add more test cases for serializing dicts
mariajgrimaldi Dec 13, 2024
f4aa824
refactor: address quality issues from latest commits
mariajgrimaldi Dec 13, 2024
f7beb63
refactor: address PR reviews
mariajgrimaldi Dec 16, 2024
482c8d9
fix: address quality issues
mariajgrimaldi Dec 16, 2024
7d9b8b8
test: add deserializer tests for dicts
mariajgrimaldi Dec 16, 2024
c76b3d1
test: add tests for deserialization errors
mariajgrimaldi Dec 16, 2024
ec1fdec
test: add test cases for schema generation with dict types
mariajgrimaldi Dec 16, 2024
2d225b9
fix: address quality issues
mariajgrimaldi Dec 16, 2024
2839ae7
refactor: rewrite comment with suggestion
mariajgrimaldi Jan 8, 2025
4389cfb
refactor: include map type instead of replacing record
mariajgrimaldi Jan 8, 2025
8f67ea2
refactor: drop changes in forum events
mariajgrimaldi Jan 8, 2025
9ee35f2
refactor: drop changes in forum events
mariajgrimaldi Jan 8, 2025
a32ac76
refactor: address PR reviews
mariajgrimaldi Jan 10, 2025
2980a93
test: add missing test for de-serializing complex types
mariajgrimaldi Jan 10, 2025
7eabdaa
refactor: check for keys and values simple types while de-serializing
mariajgrimaldi Jan 10, 2025
72445ff
chore: generate avro schema for each forum event
mariajgrimaldi Dec 12, 2024
880b835
refactor: rewrite forum payload to be sent to the event bus
mariajgrimaldi Dec 13, 2024
ff3ada4
refactor: regenerate avro schemas for latest forum payload
mariajgrimaldi Dec 13, 2024
f28f4a8
refactor: drop forum events from unserializable list
mariajgrimaldi Jan 8, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions openedx_events/event_bus/avro/deserializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,27 @@ def _deserialized_avro_record_dict_to_object(data: dict, data_type, deserializer
elif data_type in PYTHON_TYPE_TO_AVRO_MAPPING:
return data
elif data_type_origin == list:
# returns types of list contents
# if data_type == List[int], arg_data_type = (int,)
# Returns types of list contents.
# Example: if data_type == List[int], arg_data_type = (int,)
arg_data_type = get_args(data_type)
if not arg_data_type:
raise TypeError(
"List without annotation type is not supported. The argument should be a type, for eg., List[int]"
)
# check whether list items type is in basic types.
# Check whether list items type is in basic types.
if arg_data_type[0] in SIMPLE_PYTHON_TYPE_TO_AVRO_MAPPING:
return data
elif data_type_origin == dict:
# Returns types of dict contents.
# Example: if data_type == Dict[str, int], arg_data_type = (str, int)
arg_data_type = get_args(data_type)
if not arg_data_type:
raise TypeError(
"Dict without annotation type is not supported. The argument should be a type, for eg., Dict[str, int]"
)
# Check whether dict items type is in basic types.
if all(arg in SIMPLE_PYTHON_TYPE_TO_AVRO_MAPPING for arg in arg_data_type):
return data
elif hasattr(data_type, "__attrs_attrs__"):
transformed = {}
for attribute in data_type.__attrs_attrs__:
Expand Down
21 changes: 18 additions & 3 deletions openedx_events/event_bus/avro/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,14 @@ def _create_avro_field_definition(data_key, data_type, previously_seen_types,
field["type"] = field_type
# Case 2: data_type is a simple type that can be converted directly to an Avro type
elif data_type in PYTHON_TYPE_TO_AVRO_MAPPING:
if PYTHON_TYPE_TO_AVRO_MAPPING[data_type] in ["record", "array"]:
if PYTHON_TYPE_TO_AVRO_MAPPING[data_type] in ["map", "array"]:
# pylint: disable-next=broad-exception-raised
raise Exception("Unable to generate Avro schema for dict or array fields without annotation types.")
avro_type = PYTHON_TYPE_TO_AVRO_MAPPING[data_type]
field["type"] = avro_type
elif data_type_origin == list:
# returns types of list contents
# if data_type == List[int], arg_data_type = (int,)
# Returns types of list contents.
# Example: if data_type == List[int], arg_data_type = (int,)
arg_data_type = get_args(data_type)
if not arg_data_type:
raise TypeError(
Expand All @@ -83,6 +83,21 @@ def _create_avro_field_definition(data_key, data_type, previously_seen_types,
f" {set(SIMPLE_PYTHON_TYPE_TO_AVRO_MAPPING.keys())}"
)
field["type"] = {"type": PYTHON_TYPE_TO_AVRO_MAPPING[data_type_origin], "items": avro_type}
elif data_type_origin == dict:
# Returns types of dict contents.
# Example: if data_type == Dict[str, int], arg_data_type = (str, int)
arg_data_type = get_args(data_type)
if not arg_data_type:
raise TypeError(
"Dict without annotation type is not supported. The argument should be a type, for eg., Dict[str, int]"
)
avro_type = SIMPLE_PYTHON_TYPE_TO_AVRO_MAPPING.get(arg_data_type[1])
if avro_type is None:
raise TypeError(
"Only following types are supported for dict arguments:"
f" {set(SIMPLE_PYTHON_TYPE_TO_AVRO_MAPPING.keys())}"
)
field["type"] = {"type": PYTHON_TYPE_TO_AVRO_MAPPING[data_type_origin], "values": avro_type}
# Case 3: data_type is an attrs class
elif hasattr(data_type, "__attrs_attrs__"):
# Inner Attrs Class
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
{
"name": "CloudEvent",
"type": "record",
"doc": "Avro Event Format for CloudEvents created with openedx_events/schema",
"fields": [
{
"name": "thread",
"type": {
"name": "DiscussionThreadData",
"type": "record",
"fields": [
{
"name": "body",
"type": "string"
},
{
"name": "commentable_id",
"type": "string"
},
{
"name": "id",
"type": "string"
},
{
"name": "truncated",
"type": "boolean"
},
{
"name": "url",
"type": "string"
},
{
"name": "user",
"type": {
"name": "UserData",
"type": "record",
"fields": [
{
"name": "id",
"type": "long"
},
{
"name": "is_active",
"type": "boolean"
},
{
"name": "pii",
"type": {
"name": "UserPersonalData",
"type": "record",
"fields": [
{
"name": "username",
"type": "string"
},
{
"name": "email",
"type": "string"
},
{
"name": "name",
"type": "string"
}
]
}
}
]
}
},
{
"name": "course_id",
"type": "string"
},
{
"name": "thread_type",
"type": [
"null",
"string"
],
"default": null
},
{
"name": "anonymous",
"type": [
"null",
"boolean"
],
"default": null
},
{
"name": "anonymous_to_peers",
"type": [
"null",
"boolean"
],
"default": null
},
{
"name": "title",
"type": [
"null",
"string"
],
"default": null
},
{
"name": "title_truncated",
"type": [
"null",
"boolean"
],
"default": null
},
{
"name": "group_id",
"type": [
"null",
"long"
],
"default": null
},
{
"name": "team_id",
"type": [
"null",
"long"
],
"default": null
},
{
"name": "category_id",
"type": [
"null",
"long"
],
"default": null
},
{
"name": "category_name",
"type": [
"null",
"string"
],
"default": null
},
{
"name": "discussion",
"type": [
"null",
{
"type": "map",
"values": "string"
}
],
"default": null
},
{
"name": "user_course_roles",
"type": {
"type": "array",
"items": "string"
}
},
{
"name": "user_forums_roles",
"type": {
"type": "array",
"items": "string"
}
},
{
"name": "options",
"type": {
"type": "map",
"values": "boolean"
}
}
]
}
}
],
"namespace": "org.openedx.learning.forum.thread.created.v1"
}
Loading
Loading