Fixed memory leak in Battle and MyCompanies classes

This commit is contained in:
Eriks K 2020-07-28 18:28:03 +03:00
parent e8c81d17e6
commit a316f277fb
3 changed files with 50 additions and 13 deletions

View File

@ -1314,9 +1314,6 @@ class CitizenMilitary(CitizenTravel):
boosters: Dict[int, Dict[int, int]] = {100: {}, 50: {}} boosters: Dict[int, Dict[int, int]] = {100: {}, 50: {}}
def update_war_info(self): def update_war_info(self):
if not self.details.current_country:
self.update_citizen_info()
if self.__last_war_update_data and self.__last_war_update_data.get('last_updated', if self.__last_war_update_data and self.__last_war_update_data.get('last_updated',
0) + 30 > self.now.timestamp(): 0) + 30 > self.now.timestamp():
r_json = self.__last_war_update_data r_json = self.__last_war_update_data
@ -1341,7 +1338,10 @@ class CitizenMilitary(CitizenTravel):
all_battles = {} all_battles = {}
for battle_data in r_json.get("battles", {}).values(): for battle_data in r_json.get("battles", {}).values():
all_battles[battle_data.get('id')] = classes.Battle(battle_data) all_battles[battle_data.get('id')] = classes.Battle(battle_data)
old_all_battles = self.all_battles
self.all_battles = all_battles self.all_battles = all_battles
for battle in old_all_battles.values():
utils._clear_up_battle_memory(battle)
def get_battle_for_war(self, war_id: int) -> Optional[classes.Battle]: def get_battle_for_war(self, war_id: int) -> Optional[classes.Battle]:
self.update_war_info() self.update_war_info()

View File

@ -1,6 +1,7 @@
import datetime import datetime
import hashlib import hashlib
import threading import threading
import weakref
from decimal import Decimal from decimal import Decimal
from typing import Any, Dict, List, NamedTuple, Optional, Tuple, Union from typing import Any, Dict, List, NamedTuple, Optional, Tuple, Union
@ -27,9 +28,10 @@ class Holding:
id: int id: int
region: int region: int
companies: List["Company"] companies: List["Company"]
_citizen = weakref.ReferenceType
def __init__(self, _id: int, region: int, citizen): def __init__(self, _id: int, region: int, citizen):
self.citizen = citizen self._citizen = weakref.ref(citizen)
self.id: int = _id self.id: int = _id
self.region: int = region self.region: int = region
self.companies: List["Company"] = list() self.companies: List["Company"] = list()
@ -93,8 +95,13 @@ class Holding:
def as_dict(self): def as_dict(self):
return dict(name=str(self), id=self.id, region=self.region, companies=self.companies, wam_count=self.wam_count) return dict(name=str(self), id=self.id, region=self.region, companies=self.companies, wam_count=self.wam_count)
@property
def citizen(self):
return self._citizen()
class Company: class Company:
_holding: weakref.ReferenceType
holding: Holding holding: Holding
id: int id: int
quality: int quality: int
@ -113,7 +120,7 @@ class Company:
base_production: Decimal, wam_enabled: bool, can_wam: bool, cannot_wam_reason: str, industry: int, base_production: Decimal, wam_enabled: bool, can_wam: bool, cannot_wam_reason: str, industry: int,
already_worked: bool, preset_works: int already_worked: bool, preset_works: int
): ):
self.holding: Holding = holding self._holding = weakref.ref(holding)
self.id: int = _id self.id: int = _id
self.industry: int = industry self.industry: int = industry
self.quality: int = self._get_real_quality(quality) self.quality: int = self._get_real_quality(quality)
@ -211,6 +218,10 @@ class Company:
# noinspection PyProtectedMember # noinspection PyProtectedMember
return self.holding.citizen._post_economy_upgrade_company(self.id, level, self.holding.citizen.details.pin) return self.holding.citizen._post_economy_upgrade_company(self.id, level, self.holding.citizen.details.pin)
@property
def holding(self):
return self._holding()
class MyCompanies: class MyCompanies:
work_units: int = 0 work_units: int = 0
@ -218,13 +229,13 @@ class MyCompanies:
ff_lockdown: int = 0 ff_lockdown: int = 0
holdings: Dict[int, Holding] holdings: Dict[int, Holding]
companies: List[Company] companies: weakref.WeakSet
_citizen: weakref.ReferenceType
def __init__(self, citizen): def __init__(self, citizen):
from erepublik import Citizen self._citizen = weakref.ref(citizen)
self.citizen: Citizen = citizen
self.holdings: Dict[int, Holding] = dict() self.holdings: Dict[int, Holding] = dict()
self.companies: List[Company] = list() self.companies: weakref.WeakSet = weakref.WeakSet()
self.next_ot_time = utils.now() self.next_ot_time = utils.now()
def prepare_holdings(self, holdings: Dict[str, Dict[str, Any]]): def prepare_holdings(self, holdings: Dict[str, Dict[str, Any]]):
@ -258,7 +269,7 @@ class MyCompanies:
company_dict.get('can_work_as_manager'), company_dict.get('cannot_work_as_manager_reason'), company_dict.get('can_work_as_manager'), company_dict.get('cannot_work_as_manager_reason'),
company_dict.get('industry_id'), company_dict.get('already_worked'), company_dict.get('preset_works') company_dict.get('industry_id'), company_dict.get('already_worked'), company_dict.get('preset_works')
) )
self.companies.append(company) self.companies.add(company)
holding.add_company(company) holding.add_company(company)
def get_employable_factories(self) -> Dict[int, int]: def get_employable_factories(self) -> Dict[int, int]:
@ -290,6 +301,10 @@ class MyCompanies:
return dict(name=str(self), work_units=self.work_units, next_ot_time=self.next_ot_time, return dict(name=str(self), work_units=self.work_units, next_ot_time=self.next_ot_time,
ff_lockdown=self.ff_lockdown, holdings=self.holdings, company_count=len(self.companies)) ff_lockdown=self.ff_lockdown, holdings=self.holdings, company_count=len(self.companies))
@property
def citizen(self):
return self._citizen()
class Config: class Config:
email = "" email = ""
@ -528,7 +543,7 @@ class Reporter:
queue=self.__to_update) queue=self.__to_update)
def __init__(self, citizen): def __init__(self, citizen):
self.citizen = citizen self._citizen = weakref.ref(citizen)
self._req = Session() self._req = Session()
self.url = "https://api.erep.lv" self.url = "https://api.erep.lv"
self._req.headers.update({"user-agent": "Bot reporter v2"}) self._req.headers.update({"user-agent": "Bot reporter v2"})
@ -541,6 +556,10 @@ class Reporter:
self.register_account() self.register_account()
self.allowed = True self.allowed = True
@property
def citizen(self):
return self._citizen()
def __update_key(self): def __update_key(self):
self.key = hashlib.md5(bytes(f"{self.name}:{self.email}", encoding="UTF-8")).hexdigest() self.key = hashlib.md5(bytes(f"{self.name}:{self.email}", encoding="UTF-8")).hexdigest()
@ -645,12 +664,13 @@ class BattleSide:
deployed: List[constants.Country] deployed: List[constants.Country]
allies: List[constants.Country] allies: List[constants.Country]
battle: "Battle" battle: "Battle"
_battle: weakref.ReferenceType
country: constants.Country country: constants.Country
defender: bool defender: bool
def __init__(self, battle: "Battle", country: constants.Country, points: int, allies: List[constants.Country], def __init__(self, battle: "Battle", country: constants.Country, points: int, allies: List[constants.Country],
deployed: List[constants.Country], defender: bool): deployed: List[constants.Country], defender: bool):
self.battle = battle self._battle = weakref.ref(battle)
self.country = country self.country = country
self.points = points self.points = points
self.allies = allies self.allies = allies
@ -677,6 +697,10 @@ class BattleSide:
return dict(points=self.points, country=self.country, defender=self.defender, allies=self.allies, return dict(points=self.points, country=self.country, defender=self.defender, allies=self.allies,
deployed=self.deployed, battle=repr(self.battle)) deployed=self.deployed, battle=repr(self.battle))
@property
def battle(self):
return self._battle()
class BattleDivision: class BattleDivision:
id: int id: int
@ -689,6 +713,7 @@ class BattleDivision:
terrain: int terrain: int
div: int div: int
battle: "Battle" battle: "Battle"
_battle: weakref.ReferenceType
@property @property
def as_dict(self): def as_dict(self):
@ -715,7 +740,7 @@ class BattleDivision:
:type wall_for: int :type wall_for: int
:type wall_dom: float :type wall_dom: float
""" """
self.battle = battle self._battle = weakref.ref(battle)
self.id = div_id self.id = div_id
self.end = end self.end = end
self.epic = epic self.epic = epic
@ -738,6 +763,10 @@ class BattleDivision:
def __repr__(self): def __repr__(self):
return f"<BattleDivision #{self.id} (battle #{self.battle.id})>" return f"<BattleDivision #{self.id} (battle #{self.battle.id})>"
@property
def battle(self):
return self._battle()
class Battle: class Battle:
id: int id: int

View File

@ -368,3 +368,11 @@ def get_air_hit_dmg_value(citizen_id: int, natural_enemy: bool = False, true_pat
rang = r['military']['militaryData']['aircraft']['rankNumber'] rang = r['military']['militaryData']['aircraft']['rankNumber']
elite = r['citizenAttributes']['level'] > 100 elite = r['citizenAttributes']['level'] > 100
return calculate_hit(0, rang, true_patriot, elite, natural_enemy, booster, weapon_power) return calculate_hit(0, rang, true_patriot, elite, natural_enemy, booster, weapon_power)
def _clear_up_battle_memory(battle):
from . import classes
battle: classes.Battle
del battle.invader._battle, battle.defender._battle
for div_id, division in battle.div.items():
del division._battle