Skip to content

Commit

Permalink
feat: improve performance of websocket message processing (#66)
Browse files Browse the repository at this point in the history
Make the calls to the object type lookups normal attributes to avoid
the function calls
  • Loading branch information
bdraco authored Jun 15, 2024
1 parent 9b6ab01 commit d6a6472
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 26 deletions.
12 changes: 6 additions & 6 deletions src/uiprotect/data/bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,8 @@ def unifi_dict_to_dict(cls, data: dict[str, Any]) -> dict[str, Any]:
)
data["macLookup"] = {}
data["idLookup"] = {}
for model_type in ModelType.bootstrap_models_types_set():
key = model_type.devices_key
for model_type in ModelType.bootstrap_models_types_set:
key = model_type.devices_key # type: ignore[attr-defined]
items: dict[str, ProtectModel] = {}
for item in data[key]:
if (
Expand Down Expand Up @@ -230,8 +230,8 @@ def unifi_dict(
if "idLookup" in data:
del data["idLookup"]

for model_type in ModelType.bootstrap_models_types_set():
attr = model_type.devices_key
for model_type in ModelType.bootstrap_models_types_set:
attr = model_type.devices_key # type: ignore[attr-defined]
if attr in data and isinstance(data[attr], dict):
data[attr] = list(data[attr].values())

Expand Down Expand Up @@ -353,7 +353,7 @@ def _process_add_packet(
if TYPE_CHECKING:
assert isinstance(obj, NVR)
self.nvr = obj
elif model_type in ModelType.bootstrap_models_types_set():
elif model_type in ModelType.bootstrap_models_types_set:
if TYPE_CHECKING:
assert isinstance(obj, ProtectAdoptableDeviceModel)
if not self._api.ignore_unadopted or (
Expand Down Expand Up @@ -550,7 +550,7 @@ def process_ws_packet(
if action_action == "update":
if model_type is ModelType.NVR:
return self._process_nvr_update(packet, data, ignore_stats)
if model_type in ModelType.bootstrap_models_types_and_event_set():
if model_type in ModelType.bootstrap_models_types_and_event_set:
return self._process_device_update(
model_type,
packet,
Expand Down
52 changes: 33 additions & 19 deletions src/uiprotect/data/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,12 @@ class ModelType(str, UnknownValuesEnumMixin, enum.Enum):
RECORDING_SCHEDULE = "recordingSchedule"
UNKNOWN = "unknown"

bootstrap_model_types: tuple[ModelType, ...]
bootstrap_models: tuple[str, ...]
bootstrap_models_set: set[str]
bootstrap_models_types_set: set[ModelType]
bootstrap_models_types_and_event_set: set[ModelType]

@cached_property
def devices_key(self) -> str:
"""Return the devices key."""
Expand All @@ -119,9 +125,8 @@ def devices_key(self) -> str:
def from_string(cls, value: str) -> ModelType:
return cls(value)

@staticmethod
@cache
def bootstrap_model_types() -> tuple[ModelType, ...]:
@classmethod
def _bootstrap_model_types(cls) -> tuple[ModelType, ...]:
"""Return the bootstrap models as a tuple."""
# TODO:
# legacyUFV
Expand All @@ -139,31 +144,40 @@ def bootstrap_model_types() -> tuple[ModelType, ...]:
ModelType.CHIME,
)

@staticmethod
@cache
def bootstrap_models() -> tuple[str, ...]:
@classmethod
def _bootstrap_models(cls) -> tuple[str, ...]:
"""Return the bootstrap models strings as a tuple."""
return tuple(
model_type.value for model_type in ModelType.bootstrap_model_types()
model_type.value for model_type in ModelType._bootstrap_model_types()
)

@staticmethod
@cache
def bootstrap_models_set() -> set[str]:
@classmethod
def _bootstrap_models_set(cls) -> set[str]:
"""Return the set of bootstrap models strings as a set."""
return set(ModelType.bootstrap_models())
return set(ModelType._bootstrap_models())

@staticmethod
@cache
def bootstrap_models_types_set() -> set[ModelType]:
@classmethod
def _bootstrap_models_types_set(cls) -> set[ModelType]:
"""Return the set of bootstrap models as a set."""
return set(ModelType.bootstrap_model_types())
return set(ModelType._bootstrap_model_types())

@staticmethod
@cache
def bootstrap_models_types_and_event_set() -> set[ModelType]:
@classmethod
def _bootstrap_models_types_and_event_set(cls) -> set[ModelType]:
"""Return the set of bootstrap models and the event model as a set."""
return ModelType.bootstrap_models_types_set() | {ModelType.EVENT}
return ModelType._bootstrap_models_types_set() | {ModelType.EVENT}

def _immutable(self, name: str, value: Any) -> None:
raise AttributeError("Cannot modify ModelType")


ModelType.bootstrap_model_types = ModelType._bootstrap_model_types()
ModelType.bootstrap_models = ModelType._bootstrap_models()
ModelType.bootstrap_models_set = ModelType._bootstrap_models_set()
ModelType.bootstrap_models_types_set = ModelType._bootstrap_models_types_set()
ModelType.bootstrap_models_types_and_event_set = (
ModelType._bootstrap_models_types_and_event_set()
)
ModelType.__setattr__ = ModelType._immutable # type: ignore[method-assign, assignment]


@enum.unique
Expand Down
2 changes: 1 addition & 1 deletion tests/data/test_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ def test_bootstrap(bootstrap: dict[str, Any]):
if "deviceGroups" in bootstrap:
del bootstrap["deviceGroups"]

for model_type in ModelType.bootstrap_models():
for model_type in ModelType.bootstrap_models:
key = model_type + "s"
expected_data = bootstrap.pop(key)
actual_data = obj_dict.pop(key)
Expand Down

0 comments on commit d6a6472

Please sign in to comment.