metadatamapper.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. from typing import Dict
  2. from dataladmetadatamodel.mapper.gitmapper.objectreference import (
  3. GitReference,
  4. add_blob_reference,
  5. )
  6. from dataladmetadatamodel.mapper.gitmapper.gitbackend.subprocess import (
  7. git_load_str,
  8. git_save_str,
  9. )
  10. from dataladmetadatamodel.mapper.mapper import Mapper
  11. from dataladmetadatamodel.mapper.reference import Reference
  12. from .gitblobcache import GitBlobCache
  13. class MetadataGitMapper(Mapper):
  14. metadata_caches: Dict[str, GitBlobCache] = dict()
  15. @classmethod
  16. def get_cache(cls, realm: str):
  17. return cls.metadata_caches.get(realm, None)
  18. @classmethod
  19. def cache_realm(cls, realm: str):
  20. if cls.get_cache(realm) is not None:
  21. raise RuntimeError(f"already caching realm: {realm}")
  22. cls.metadata_caches[realm] = GitBlobCache(realm)
  23. @classmethod
  24. def flush_realm(cls, realm: str):
  25. cache = cls.get_cache(realm)
  26. if cache is None:
  27. raise RuntimeError(f"realm is not cached: {realm}")
  28. cache.flush()
  29. del cls.metadata_caches[realm]
  30. def map_in_impl(self,
  31. metadata: "Metadata",
  32. realm: str,
  33. meta_reference: Reference) -> None:
  34. from dataladmetadatamodel.metadata import Metadata
  35. from dataladmetadatamodel.mapper.reference import Reference
  36. assert isinstance(metadata, Metadata)
  37. reference = Reference.from_json_str(
  38. git_load_str(realm, meta_reference.location))
  39. metadata.init_from_json(
  40. git_load_str(realm, reference.location))
  41. def map_out_impl(self,
  42. metadata: "Metadata",
  43. realm: str,
  44. force_write: bool) -> Reference:
  45. from dataladmetadatamodel.metadata import Metadata
  46. assert isinstance(metadata, Metadata)
  47. cache = self.get_cache(realm)
  48. if cache is None:
  49. return self.map_out_impl_immediate(metadata, realm, force_write)
  50. else:
  51. return self.map_out_impl_cached(cache, metadata, realm)
  52. def map_out_impl_immediate(self,
  53. metadata: "Metadata",
  54. realm: str,
  55. force_write: bool) -> Reference:
  56. # Save metadata object and add it to the
  57. # blob-references. That is necessary because
  58. # metadata blobs are only referenced in
  59. # persisted Reference-objects, i.e. in
  60. # JSON-strings that are stored in the
  61. # repository.
  62. metadata_blob_location = git_save_str(realm, metadata.to_json())
  63. add_blob_reference(GitReference.BLOBS, metadata_blob_location)
  64. # Save reference. NB we don't have to save
  65. # metadata_reference_blob_location to the
  66. # reference objects because they will be
  67. # reachable by a git tree entry.
  68. metadata_reference_blob_location = git_save_str(
  69. realm,
  70. Reference(
  71. "Metadata",
  72. metadata_blob_location).to_json_str())
  73. # Return reference to reference, although it specifies
  74. # the class Metadata, it points actually to a
  75. # persisted Reference object. But this is only known
  76. # internally in this mapper.
  77. return Reference(
  78. "Metadata",
  79. metadata_reference_blob_location)
  80. def map_out_impl_cached(self,
  81. cache: GitBlobCache,
  82. metadata: "Metadata",
  83. realm: str) -> Reference:
  84. # Cache metadata, and cache a reference object. the
  85. # following code is "cache"-equivalent to the immediate case
  86. metadata_blob_location = cache.cache_blob(realm, metadata.to_json())
  87. add_blob_reference(GitReference.BLOBS, metadata_blob_location)
  88. metadata_reference_blob_location = cache.cache_blob(
  89. realm,
  90. Reference(
  91. "Metadata",
  92. metadata_blob_location).to_json_str())
  93. return Reference(
  94. "Metadata",
  95. metadata_reference_blob_location)