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

WIP: Support changing servertypes #57

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft

Conversation

HerrSpace
Copy link
Contributor

This adds support for changing the servertype via the normal commit API. It performs some sanity checking and finally modifies the commit to include attribute removals if an attribute was available on the old servertype and set but is not available on the new servertype. This guarantees no zombie attributes on the database and a clean history.

@HerrSpace HerrSpace changed the title Support changing servertypes WIP: Support changing servertypes Jan 10, 2019
serveradmin/serverdb/query_committer.py Outdated Show resolved Hide resolved
serveradmin/serverdb/query_committer.py Outdated Show resolved Hide resolved
serveradmin/serverdb/query_committer.py Outdated Show resolved Hide resolved
involved_servertypes = chain(*[
[change['servertype']['old'], change['servertype']['new']]
for change in servertype_changes
])
Copy link
Contributor

Choose a reason for hiding this comment

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

No need to *[].

Copy link
Contributor Author

@HerrSpace HerrSpace Jan 10, 2019

Choose a reason for hiding this comment

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

Actually this doesn't seem to get flattened without *[] 🤔

Traceback (most recent call last):
  File "/Users/space/.local/share/virtualenvs/serveradmin-m3Kn4UAw/lib/python3.5/site-packages/django/core/handlers/exception.py", line 41, in inner
    response = get_response(request)
  File "/Users/space/.local/share/virtualenvs/serveradmin-m3Kn4UAw/lib/python3.5/site-packages/django/core/handlers/base.py", line 249, in _legacy_get_response
    response = self._get_response(request)
  File "/Users/space/.local/share/virtualenvs/serveradmin-m3Kn4UAw/lib/python3.5/site-packages/django/core/handlers/base.py", line 187, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/Users/space/.local/share/virtualenvs/serveradmin-m3Kn4UAw/lib/python3.5/site-packages/django/core/handlers/base.py", line 185, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/Users/space/.local/share/virtualenvs/serveradmin-m3Kn4UAw/lib/python3.5/site-packages/django/contrib/auth/decorators.py", line 23, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "./serveradmin/servershell/views.py", line 305, in commit
    commit_query(changed=changed, deleted=deleted, user=user)
  File "./serveradmin/serverdb/query_committer.py", line 80, in commit_query
    _resolve_servertype_changes(changed, joined_attributes)
  File "./serveradmin/serverdb/query_committer.py", line 663, in _resolve_servertype_changes
    involved_servertype_ids
  File "./serveradmin/serverdb/query_committer.py", line 398, in _get_servertype_attributes
    for servertype_id in set(servertype_ids):
TypeError: unhashable type: 'list'

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, now I see, chain() doesn't seem to be the right thing though. Some use sum(([...] for x in y), []) to concatenate items, but a simple for to append items is more efficient and more readable.

serveradmin/serverdb/query_committer.py Outdated Show resolved Hide resolved
serveradmin/serverdb/query_committer.py Outdated Show resolved Hide resolved
# the real attribute changes, resulting from a servertype change, before
# sending the pre_commit signal. Alternatively we could send the
# pre_commit signal inside the commit_query transaction but sending the
# signal can take many seconds if a receiver misbehaves.
Copy link
Contributor

Choose a reason for hiding this comment

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

I couldn't get this.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Check out commit_query(). There we have the real transaction committing changes to the database. You chose to put the signals before and after the transactions as the signals are blocking until all receivers are done. To expand what attributes I have to delete I first have to materialize the object though. I need to expand the changes first as otherwise the pre_commit and post_commit hook would have different values for 'changed'. That would suck.

Copy link
Contributor Author

@HerrSpace HerrSpace Jan 10, 2019

Choose a reason for hiding this comment

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

So before my change the behavior was:

  • pre_commit hook
  • transaction
    • materialize the objects
    • commit the objects
  • post_commit hook

Now the behavior is:

  • transaction
    • materialize objects with changed servertypes
  • expand servertype changes to real attribute changes
  • pre_commit hook
  • transaction
    • materialize all objects
    • commit the objects
  • post_commit hook

Copy link
Contributor

Choose a reason for hiding this comment

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

otherwise the pre_commit and post_commit hook would have different values for 'changed'. That would suck.

I think it is fair that they are different. Complicating the flow in here may have more downsides.

# sending the pre_commit signal. Alternatively we could send the
# pre_commit signal inside the commit_query transaction but sending the
# signal can take many seconds if a receiver misbehaves.
with transaction.atomic():
Copy link
Contributor

Choose a reason for hiding this comment

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

It is not okay to start another transaction in the same request. If things fail after committing this one, you would end up persisting part of the commit. Whatever critical need to go the .atomic() block started after calling this function.

Copy link
Contributor

Choose a reason for hiding this comment

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

Everything that write to the database is "critical". There are more of them later on this function.

Copy link
Contributor Author

@HerrSpace HerrSpace Jan 10, 2019

Choose a reason for hiding this comment

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

I believe this function doesn't write to the database at all, except for the _fetch_servers row lock, which is why I added this transaction in the first place. I want this function to only expand the changes and then put the changes through the normal commit process. Am I missing something here?

serveradmin/serverdb/query_committer.py Outdated Show resolved Hide resolved
# commit for now. While this is not super clean, the user will be forced
# to set a correct value once he opens an edit dialog for this object in
# servershell. I think that's good enough for now as changing servertypes
# is an edgecase anyway.
Copy link
Contributor

Choose a reason for hiding this comment

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

I am not convince it would be good enough. Especially not having the defaults on the changed objects may cause real trouble.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So I loop over all servertype_attributes of the new servertype and if it has a default value and the object does not have that attribute set, I set the default. Would that be enough?

Copy link
Contributor

Choose a reason for hiding this comment

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

I guess. See get_default_attribute_values().

@kofrezo kofrezo marked this pull request as draft July 21, 2021 10:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants