|
14 | 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
15 | 15 | # See the License for the specific language governing permissions and |
16 | 16 | # limitations under the License. |
| 17 | +import asyncio as _locks |
17 | 18 | import io |
18 | 19 | import logging |
19 | 20 | from typing import Any, Callable, Coroutine, Optional, Tuple, Union, cast |
@@ -214,6 +215,7 @@ class AsyncJSONSerializer(AsyncBaseSerializer): |
214 | 215 | '_to_dict', |
215 | 216 | '_parsed_schemas', |
216 | 217 | '_validators', |
| 218 | + '_validators_lock', |
217 | 219 | '_validate', |
218 | 220 | '_json_encode', |
219 | 221 | ] |
@@ -255,6 +257,7 @@ async def __init_impl( |
255 | 257 | self._known_subjects: set[str] = set() |
256 | 258 | self._parsed_schemas = ParsedSchemaCache() |
257 | 259 | self._validators: LRUCache[Schema, Validator] = LRUCache(1000) |
| 260 | + self._validators_lock = _locks.Lock() |
258 | 261 |
|
259 | 262 | if to_dict is not None and not callable(to_dict): |
260 | 263 | raise ValueError( |
@@ -404,7 +407,7 @@ def field_transformer(rule_ctx, field_transform, msg): |
404 | 407 |
|
405 | 408 | if self._validate and schema is not None and parsed_schema is not None and ref_registry is not None: |
406 | 409 | try: |
407 | | - validator = self._get_validator(schema, parsed_schema, ref_registry) |
| 410 | + validator = await self._get_validator(schema, parsed_schema, ref_registry) |
408 | 411 | validator.validate(value) |
409 | 412 | except ValidationError as ve: |
410 | 413 | raise SerializationError(ve.message) |
@@ -441,16 +444,18 @@ async def _get_parsed_schema(self, schema: Optional[Schema]) -> Tuple[Optional[J |
441 | 444 | self._parsed_schemas.set(schema, (parsed_schema, ref_registry)) |
442 | 445 | return parsed_schema, ref_registry |
443 | 446 |
|
444 | | - def _get_validator(self, schema: Schema, parsed_schema: JsonSchema, registry: Registry) -> Validator: |
445 | | - validator = self._validators.get(schema, None) |
446 | | - if validator is not None: |
447 | | - return validator |
| 447 | + async def _get_validator(self, schema: Schema, parsed_schema: JsonSchema, registry: Registry) -> Validator: |
| 448 | + async with self._validators_lock: |
| 449 | + validator = self._validators.get(schema, None) |
| 450 | + if validator is not None: |
| 451 | + return validator |
448 | 452 |
|
449 | 453 | cls = validator_for(parsed_schema) |
450 | 454 | cls.check_schema(parsed_schema) |
451 | 455 | validator = cls(parsed_schema, registry=registry) |
452 | 456 |
|
453 | | - self._validators[schema] = validator |
| 457 | + async with self._validators_lock: |
| 458 | + self._validators[schema] = validator |
454 | 459 | return validator |
455 | 460 |
|
456 | 461 |
|
@@ -518,6 +523,7 @@ class AsyncJSONDeserializer(AsyncBaseDeserializer): |
518 | 523 | '_schema', |
519 | 524 | '_parsed_schemas', |
520 | 525 | '_validators', |
| 526 | + '_validators_lock', |
521 | 527 | '_validate', |
522 | 528 | '_json_decode', |
523 | 529 | ] |
@@ -562,6 +568,7 @@ async def __init_impl( |
562 | 568 | self._rule_registry = rule_registry if rule_registry else RuleRegistry.get_global_instance() |
563 | 569 | self._parsed_schemas = ParsedSchemaCache() |
564 | 570 | self._validators: LRUCache[Schema, Validator] = LRUCache(1000) |
| 571 | + self._validators_lock = _locks.Lock() |
565 | 572 | self._json_decode = json_decode or orjson.loads |
566 | 573 | self._use_schema_id = None |
567 | 574 |
|
@@ -708,7 +715,7 @@ def field_transformer(rule_ctx, field_transform, message): |
708 | 715 | if self._validate: |
709 | 716 | if reader_schema_raw is not None and reader_schema is not None and reader_ref_registry is not None: |
710 | 717 | try: |
711 | | - validator = self._get_validator(reader_schema_raw, reader_schema, reader_ref_registry) |
| 718 | + validator = await self._get_validator(reader_schema_raw, reader_schema, reader_ref_registry) |
712 | 719 | validator.validate(obj_dict) |
713 | 720 | except ValidationError as ve: |
714 | 721 | raise SerializationError(ve.message) |
@@ -745,14 +752,16 @@ async def _get_parsed_schema(self, schema: Schema) -> Tuple[Optional[JsonSchema] |
745 | 752 | self._parsed_schemas.set(schema, (parsed_schema, ref_registry)) |
746 | 753 | return parsed_schema, ref_registry |
747 | 754 |
|
748 | | - def _get_validator(self, schema: Schema, parsed_schema: JsonSchema, registry: Registry) -> Validator: |
749 | | - validator = self._validators.get(schema, None) |
750 | | - if validator is not None: |
751 | | - return validator |
| 755 | + async def _get_validator(self, schema: Schema, parsed_schema: JsonSchema, registry: Registry) -> Validator: |
| 756 | + async with self._validators_lock: |
| 757 | + validator = self._validators.get(schema, None) |
| 758 | + if validator is not None: |
| 759 | + return validator |
752 | 760 |
|
753 | 761 | cls = validator_for(parsed_schema) |
754 | 762 | cls.check_schema(parsed_schema) |
755 | 763 | validator = cls(parsed_schema, registry=registry) |
756 | 764 |
|
757 | | - self._validators[schema] = validator |
| 765 | + async with self._validators_lock: |
| 766 | + self._validators[schema] = validator |
758 | 767 | return validator |
0 commit comments