From d2b6bb5013e5064eb89b6a57955e4783e5ec91ad Mon Sep 17 00:00:00 2001 From: ibuler Date: Fri, 24 Feb 2023 18:06:11 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E8=BF=81=E7=A7=BB=20?= =?UTF-8?q?accounts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit perf: 优化账号迁移,同名的迁移到历史中 --- .../migrations/0100_auto_20220711_1413.py | 61 +++++++++++++++---- 1 file changed, 49 insertions(+), 12 deletions(-) diff --git a/apps/assets/migrations/0100_auto_20220711_1413.py b/apps/assets/migrations/0100_auto_20220711_1413.py index bba1dad43..128535c8b 100644 --- a/apps/assets/migrations/0100_auto_20220711_1413.py +++ b/apps/assets/migrations/0100_auto_20220711_1413.py @@ -1,12 +1,15 @@ # Generated by Django 3.2.12 on 2022-07-11 06:13 import time +from django.utils import timezone +from itertools import groupby from django.db import migrations def migrate_asset_accounts(apps, schema_editor): auth_book_model = apps.get_model('assets', 'AuthBook') account_model = apps.get_model('accounts', 'Account') + account_history_model = apps.get_model('accounts', 'HistoricalAccount') count = 0 bulk_size = 1000 @@ -20,34 +23,35 @@ def migrate_asset_accounts(apps, schema_editor): break count += len(auth_books) - accounts = [] # auth book 和 account 相同的属性 same_attrs = [ 'id', 'username', 'comment', 'date_created', 'date_updated', 'created_by', 'asset_id', 'org_id', ] - # 认证的属性,可能是 authbook 的,可能是 systemuser 的 + # 认证的属性,可能是 auth_book 的,可能是 system_user 的 auth_attrs = ['password', 'private_key', 'token'] all_attrs = same_attrs + auth_attrs + accounts = [] for auth_book in auth_books: - values = {'version': 1} + account_values = {'version': 1} system_user = auth_book.systemuser if system_user: # 更新一次系统用户的认证属性 - values.update({attr: getattr(system_user, attr, '') for attr in all_attrs}) - values['created_by'] = str(system_user.id) - values['privileged'] = system_user.type == 'admin' + account_values.update({attr: getattr(system_user, attr, '') for attr in all_attrs}) + account_values['created_by'] = str(system_user.id) + account_values['privileged'] = system_user.type == 'admin' \ + or system_user.username in ['root', 'Administrator'] auth_book_auth = {attr: getattr(auth_book, attr, '') for attr in all_attrs if getattr(auth_book, attr, '')} - # 最终使用 authbook 的认证属性 - values.update(auth_book_auth) + # 最终优先使用 auth_book 的认证属性 + account_values.update(auth_book_auth) auth_infos = [] - username = values['username'] + username = account_values['username'] for attr in auth_attrs: - secret = values.pop(attr, None) + secret = account_values.pop(attr, None) if not secret: continue @@ -66,13 +70,46 @@ def migrate_asset_accounts(apps, schema_editor): auth_infos.append((username, 'password', '')) for name, secret_type, secret in auth_infos: - account = account_model(**values, name=name, secret=secret, secret_type=secret_type) + account = account_model(**account_values, name=name, secret=secret, secret_type=secret_type) accounts.append(account) - account_model.objects.bulk_create(accounts, ignore_conflicts=True) + accounts.sort(key=lambda x: (x.name, x.asset_id, x.date_updated)) + grouped_accounts = groupby(accounts, lambda x: (x.name, x.asset_id)) + + accounts_to_add = [] + accounts_to_history = [] + for key, _accounts in grouped_accounts: + _accounts = list(_accounts) + if not _accounts: + continue + _account = _accounts[-1] + accounts_to_add.append(_account) + _account_history = [] + + for ac in _accounts: + if not ac.secret: + continue + if ac.id != _account.id and ac.secret == _account.secret: + continue + history_data = { + 'id': _account.id, + 'secret': ac.secret, + 'secret_type': ac.secret_type, + 'history_date': ac.date_updated, + 'history_type': '~', + 'history_change_reason': 'from account {}'.format(_account.name), + } + _account_history.append(account_history_model(**history_data)) + _account.version = len(_account_history) + accounts_to_history.extend(_account_history) + + account_model.objects.bulk_create(accounts_to_add, ignore_conflicts=True) + account_history_model.objects.bulk_create(accounts_to_history, ignore_conflicts=True) print("\t - Create asset accounts: {}-{} using: {:.2f}s".format( count - len(auth_books), count, time.time() - start )) + print("\t - accounts: {}".format(len(accounts_to_add))) + print("\t - histories: {}".format(len(accounts_to_history))) def migrate_db_accounts(apps, schema_editor):