Skip to content

Implement a way to return the sequential_number after create#3326

Merged
luisa-beerboom merged 9 commits intoOpenSlides:mainfrom
luisa-beerboom:3299-make-backend-return-seq-nums
Feb 25, 2026
Merged

Implement a way to return the sequential_number after create#3326
luisa-beerboom merged 9 commits intoOpenSlides:mainfrom
luisa-beerboom:3299-make-backend-return-seq-nums

Conversation

@luisa-beerboom
Copy link
Member

@luisa-beerboom luisa-beerboom commented Feb 10, 2026

Closes #3299

@luisa-beerboom luisa-beerboom added this to the 4.3 milestone Feb 10, 2026
@luisa-beerboom luisa-beerboom self-assigned this Feb 10, 2026
@luisa-beerboom luisa-beerboom marked this pull request as ready for review February 12, 2026 12:26
Copy link
Member

@hjanott hjanott left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More questions than a review. Let's talk tomorrow.

self.print_stats()
self.print_summary()
return sorted(modified_models)
return modified_models
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sorting is obsolete?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

modified_models was a set of fqids before and this sorting transformed it into a sorted list, however it is now a fqid to model data dict and thus sorting it would turn it into a list of sorted fqid-model data tuples. As far as I could see, all places calling this ought to be able to handle a dict just as well as a sorted list, but I could be wrong. It's a bit hard to see if this breaks anything when this is still based on a version of reldb with many regularly broken tests.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the end this was a temporary fix that was resolved cleanly now.

if element:
self.update_action_data_with_write_results(element, results)
elif isinstance(data, dict):
edit_fn = data.pop(META_POST_EDIT_FN_KEY, None)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still need to think if I like this function thing.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You and me both, however as far as I can see, the alternatives would be to
A. Move the write calls into the action class. I think that'd be quite a bit of work, and, since there's so many different kinds of action classes and restructuring something so central in that invasive manner is a bit dangerous, risky.
B. Use a meta field containing the information necessary to find the fqid. That way it could filter for that instead and then just use a generalized update function. That would make individual solutions like the nested post-editing in the motion_forward impossible though.

I think A would actually be the optimum. Then again, I don't think doing it this way is particularly unsafe or bad in terms of performance. The function field will be consistently filtered out. It won't break anything unless we actually add a field META_EDIT_FN_GHETZHSRHSRGG to a model (unlikely), and even in that case we can just change the constant to another string and it'll work again. Also the entire filtering through the object in search of a meta edit field only happens if a meta edit field was set anyway, so most actions won't even be affected.

If you prefer any of the other options, or you would rather have something completely different happen, feel free to tell me though, I'll work on that then.

Comment on lines +355 to +361
def post_edit_fn(self, data: dict, results: dict[str, dict[str, Any]]) -> None:
super().post_edit_fn(data, results)
dates = [*data.get("amendment_result_data", [])]
while len(dates):
date = dates.pop(0)
super().post_edit_fn(date, results)
dates.extend(date.get("amendment_result_data", []))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this is some special casing, that was also broken?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See this actions create_action_result_element method and the create_forwarded test: The forwarding action creates a nested result element with the result elements of created amendments in an array of their lead motion. If I want the sequential_number for each of them in their part of the element, I'm going to need to parse through the stuff iteratively, when I don't have to do it for regular actions. That's why I overrode the edit function in this way.

This is the reason I stayed with the callback function variant of this instead of just adding a meta field.
I had some doubt if this was actually technically necessary since I'm not sure if the client even has a need for the amendment seq nums, however for the sake of consistency...

Comment on lines +822 to +827
def get_post_edit_function(self) -> EditFunction | None:
"""
Returns a function that allows post-editing the action result
with the return data from the database writer.
"""
return None
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think? Could we handle the id in this base class in an analogue manner? Since in the future we don't want to use reserve_ids.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean the return id of the create actions?

Because as far as I could see it while looking at the write action, it already kind of read the id in that manner...

Idk. If the sub-actions (or actions in general) use the write function directly, maybe. But currently I think it's only used in the action_handler when reading out the write requests. That is too late to use the ids within the actions f.e. to write the new models id into foreign id fields of newly created sub-models or vice versa. However, if we moved the writing to the action class it may be possible, at least in some cases. I think that's a reldb2 issue though.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we should first implement the direct writes and then we will change the system for ids and seq numbers.

self.print_stats()
self.print_summary()
return sorted(modified_models)
return modified_models
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

modified_models was a set of fqids before and this sorting transformed it into a sorted list, however it is now a fqid to model data dict and thus sorting it would turn it into a list of sorted fqid-model data tuples. As far as I could see, all places calling this ought to be able to handle a dict just as well as a sorted list, but I could be wrong. It's a bit hard to see if this breaks anything when this is still based on a version of reldb with many regularly broken tests.

Comment on lines +355 to +361
def post_edit_fn(self, data: dict, results: dict[str, dict[str, Any]]) -> None:
super().post_edit_fn(data, results)
dates = [*data.get("amendment_result_data", [])]
while len(dates):
date = dates.pop(0)
super().post_edit_fn(date, results)
dates.extend(date.get("amendment_result_data", []))
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See this actions create_action_result_element method and the create_forwarded test: The forwarding action creates a nested result element with the result elements of created amendments in an array of their lead motion. If I want the sequential_number for each of them in their part of the element, I'm going to need to parse through the stuff iteratively, when I don't have to do it for regular actions. That's why I overrode the edit function in this way.

This is the reason I stayed with the callback function variant of this instead of just adding a meta field.
I had some doubt if this was actually technically necessary since I'm not sure if the client even has a need for the amendment seq nums, however for the sake of consistency...

Comment on lines +822 to +827
def get_post_edit_function(self) -> EditFunction | None:
"""
Returns a function that allows post-editing the action result
with the return data from the database writer.
"""
return None
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean the return id of the create actions?

Because as far as I could see it while looking at the write action, it already kind of read the id in that manner...

Idk. If the sub-actions (or actions in general) use the write function directly, maybe. But currently I think it's only used in the action_handler when reading out the write requests. That is too late to use the ids within the actions f.e. to write the new models id into foreign id fields of newly created sub-models or vice versa. However, if we moved the writing to the action class it may be possible, at least in some cases. I think that's a reldb2 issue though.

if element:
self.update_action_data_with_write_results(element, results)
elif isinstance(data, dict):
edit_fn = data.pop(META_POST_EDIT_FN_KEY, None)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You and me both, however as far as I can see, the alternatives would be to
A. Move the write calls into the action class. I think that'd be quite a bit of work, and, since there's so many different kinds of action classes and restructuring something so central in that invasive manner is a bit dangerous, risky.
B. Use a meta field containing the information necessary to find the fqid. That way it could filter for that instead and then just use a generalized update function. That would make individual solutions like the nested post-editing in the motion_forward impossible though.

I think A would actually be the optimum. Then again, I don't think doing it this way is particularly unsafe or bad in terms of performance. The function field will be consistently filtered out. It won't break anything unless we actually add a field META_EDIT_FN_GHETZHSRHSRGG to a model (unlikely), and even in that case we can just change the constant to another string and it'll work again. Also the entire filtering through the object in search of a meta edit field only happens if a meta edit field was set anyway, so most actions won't even be affected.

If you prefer any of the other options, or you would rather have something completely different happen, feel free to tell me though, I'll work on that then.

Comment on lines 481 to 500
"id": 18,
"sequential_number": 4,
"non_forwarded_amendment_amount": 1,
"amendment_result_data": [
{
"id": 19,
"sequential_number": 1,
"non_forwarded_amendment_amount": 0,
"amendment_result_data": [],
},
{
"id": 20,
"sequential_number": 3,
"non_forwarded_amendment_amount": 1,
"amendment_result_data": [
{
"id": 21,
"sequential_number": 2,
"non_forwarded_amendment_amount": 0,
"amendment_result_data": [],
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Btw. I find the seq num generation here confusing. I have no idea if there even is a way to change it though. Maybe a future issue?

@hjanott hjanott deleted the branch OpenSlides:main February 20, 2026 18:40
@hjanott hjanott closed this Feb 20, 2026
@hjanott hjanott reopened this Feb 20, 2026
@luisa-beerboom luisa-beerboom changed the base branch from feature/relational-db to main February 24, 2026 15:15
Copy link
Member

@hjanott hjanott left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good now. Thank you for deleting those commented out lines.

Comment on lines +822 to +827
def get_post_edit_function(self) -> EditFunction | None:
"""
Returns a function that allows post-editing the action result
with the return data from the database writer.
"""
return None
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we should first implement the direct writes and then we will change the system for ids and seq numbers.

@luisa-beerboom luisa-beerboom merged commit a46899a into OpenSlides:main Feb 25, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[rel-db] Backend should return sequential numbers on create actions

2 participants