foobara 0.2.2 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -0
  3. data/README.md +2 -2
  4. data/projects/builtin_types/src/builtin_types.rb +3 -3
  5. data/projects/callback/src/registry/chained_multiple_action.rb +1 -1
  6. data/projects/callback/src/registry/conditioned.rb +1 -1
  7. data/projects/callback/src/registry/multiple_action.rb +1 -1
  8. data/projects/command_connectors/src/command_connector.rb +4 -2
  9. data/projects/command_connectors/src/serializers/errors_serializer.rb +1 -1
  10. data/projects/command_connectors/src/serializers/success_serializer.rb +1 -1
  11. data/projects/common/src/runtime_error.rb +1 -1
  12. data/projects/foobara/lib/foobara/all.rb +0 -1
  13. data/projects/foobara/src/foobara.rb +3 -0
  14. data/projects/namespace/src/namespace.rb +1 -1
  15. data/projects/persistence/src/entity_base/transaction/concerns/state_transitions.rb +1 -0
  16. data/projects/persistence/src/entity_base/transaction_table/concerns/record_tracking.rb +6 -1
  17. data/projects/persistence/src/entity_base/transaction_table.rb +1 -2
  18. data/projects/persistence/src/persistence.rb +2 -0
  19. data/projects/state_machine/src/state_machine.rb +4 -4
  20. data/projects/type_declarations/src/desugarizer.rb +1 -1
  21. data/projects/type_declarations/src/handlers/extend_array_type_declaration/array_desugarizer.rb +2 -2
  22. data/projects/type_declarations/src/handlers/extend_array_type_declaration/to_type_transformer.rb +2 -2
  23. data/projects/type_declarations/src/handlers/extend_associative_array_type_declaration/to_type_transformer.rb +1 -4
  24. data/projects/type_declarations/src/handlers/extend_associative_array_type_declaration.rb +1 -1
  25. data/projects/type_declarations/src/handlers/extend_attributes_type_declaration/dsl_desugarizer.rb +1 -1
  26. data/projects/type_declarations/src/handlers/extend_attributes_type_declaration/element_type_declarations_desugarizer.rb +3 -3
  27. data/projects/type_declarations/src/handlers/extend_attributes_type_declaration/hash_desugarizer.rb +2 -2
  28. data/projects/type_declarations/src/handlers/extend_attributes_type_declaration/to_type_transformer.rb +2 -2
  29. data/projects/type_declarations/src/handlers/extend_registered_type_declaration/to_type_transformer.rb +2 -2
  30. data/projects/type_declarations/src/handlers/extend_registered_type_declaration.rb +1 -1
  31. data/projects/type_declarations/src/handlers/extend_tuple_type_declaration/array_desugarizer.rb +2 -2
  32. data/projects/type_declarations/src/handlers/extend_tuple_type_declaration/to_type_transformer.rb +2 -2
  33. data/projects/type_declarations/src/handlers/registered_type_declaration/to_type_transformer.rb +1 -1
  34. data/projects/type_declarations/src/handlers/registered_type_declaration.rb +1 -1
  35. data/projects/type_declarations/src/to_type_transformer.rb +1 -1
  36. data/projects/type_declarations/src/type_declaration_handler.rb +1 -1
  37. data/projects/type_declarations/src/type_declarations.rb +2 -2
  38. data/projects/types/src/type.rb +5 -0
  39. data/projects/value/lib/foobara/value.rb +1 -1
  40. data/projects/value/src/processor/casting.rb +1 -1
  41. data/projects/value/src/processor/pipeline.rb +1 -1
  42. data/projects/value/src/processor/selection.rb +2 -2
  43. data/projects/value/src/transformer.rb +1 -1
  44. data/version.rb +1 -1
  45. metadata +3 -6
  46. data/projects/weak_object_hash/lib/foobara/weak_object_hash.rb +0 -3
  47. data/projects/weak_object_hash/src/weak_object_hash.rb +0 -225
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 98a887c0ee93ae63163439a5da9df03c3f450672723f1e32ac124ff564564f09
4
- data.tar.gz: 119f2e70b854d56ff961a055eb4ca779547e13a8ed1db68e306e4b6c9a37fa6b
3
+ metadata.gz: 7febf2c9b13ecbbbeb552dbfa7cf278805b60e808b01c64abcbd531264ff3486
4
+ data.tar.gz: 72386588ea5c433a61585c48cd904143baf9b04165a2c62328a87f089851c4d0
5
5
  SHA512:
6
- metadata.gz: f315b9474cff424bb466deb81ddfe59ce64e640677f660e0020b837d61097654c2732eafdd754b2cf5d7e91c552cf3fa3869263aefc648462258f50e1c9f5c3b
7
- data.tar.gz: 220f4dc902f9f478d083c22b89d54a4c886eb7e3c9e1e439b3ddd8134277b77571b05c47968cc884e038a7fbb7287502a77f3fda4fb39e1923c5e6e03ad6f6fa
6
+ metadata.gz: 746004fcedb4287688d6f333b02c50d1b083591837be43f762eb4916670c7c65640d0c9cbbc6a202aaff84a461a20dce5d59c7ba6bc46ce0c5ffa28754baa374
7
+ data.tar.gz: 1cae511fedd5916ec97c872eb07ffdae224f9cf76e6f2643de3138a4d146d1049bac68af3ed5ba60ec3b9778a779db051f067562ed64982e6bfeb16e4702e759
data/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ # [0.2.4] -2025-10-26
2
+
3
+ - Remove all uses of .require_project_file and deprecate it
4
+ - Replace custom WeakObjectHash with similar standard library ObjectSpace::WeakMap
5
+ - Call #committed only after whole transaction has been fully committed
6
+ - Add/fire a :persisted event for callbacks when an entity receives a primary key and is committed
7
+ - Add Type#add_caster
8
+
9
+ # [0.2.3] - 2025-10-22
10
+
11
+ - Fix Persistence.register_base bug
12
+
1
13
  # [0.2.2] - 2025-10-21
2
14
 
3
15
  - Add a connect: option to EntityAttributesCrudDriver#initialize to allow skipping connecting by
data/README.md CHANGED
@@ -2100,11 +2100,11 @@ TODO: give some code examples
2100
2100
  # Additional learning materials/Documentation
2101
2101
 
2102
2102
  * Overview and code demo videos:
2103
- * https://foobara.com/videos
2103
+ * https://foobara.org/videos
2104
2104
  * https://www.youtube.com/@FoobaraFlix
2105
2105
  * YARD Docs
2106
2106
  * All docs combined: https://docs.foobara.com/all/
2107
- * Per-repository docs: https://foobara.com/docs
2107
+ * Per-repository docs: https://foobara.org/docs
2108
2108
 
2109
2109
  # Help
2110
2110
 
@@ -1,7 +1,7 @@
1
1
  module Foobara
2
- Foobara.require_project_file("builtin_types", "duck")
3
- Foobara.require_project_file("builtin_types", "atomic_duck")
4
- Foobara.require_project_file("builtin_types", "duckture")
2
+ require_relative "duck"
3
+ require_relative "atomic_duck"
4
+ require_relative "duckture"
5
5
 
6
6
  module BuiltinTypes
7
7
  class << self
@@ -1,4 +1,4 @@
1
- Foobara.require_project_file("callback", "registry/multiple_action")
1
+ require_relative "multiple_action"
2
2
 
3
3
  module Foobara
4
4
  module Callback
@@ -1,4 +1,4 @@
1
- Foobara.require_project_file("callback", "registry/base")
1
+ require_relative "base"
2
2
 
3
3
  module Foobara
4
4
  module Callback
@@ -1,4 +1,4 @@
1
- Foobara.require_project_file("callback", "registry/base")
1
+ require_relative "base"
2
2
 
3
3
  module Foobara
4
4
  module Callback
@@ -116,9 +116,10 @@ module Foobara
116
116
  end
117
117
  end
118
118
 
119
- attr_accessor :command_registry, :authenticator, :capture_unknown_error
119
+ attr_accessor :command_registry, :authenticator, :capture_unknown_error, :name
120
120
 
121
- def initialize(authenticator: nil,
121
+ def initialize(name: nil,
122
+ authenticator: nil,
122
123
  capture_unknown_error: nil,
123
124
  default_serializers: nil,
124
125
  default_pre_commit_transformers: nil)
@@ -127,6 +128,7 @@ module Foobara
127
128
  self.authenticator = authenticator
128
129
  self.command_registry = CommandRegistry.new(authenticator:)
129
130
  self.capture_unknown_error = capture_unknown_error
131
+ self.name = name
130
132
 
131
133
  Util.array(default_serializers).each do |serializer|
132
134
  add_default_serializer(serializer)
@@ -1,5 +1,5 @@
1
1
  module Foobara
2
- require_project_file("command_connectors", "serializer")
2
+ require_relative "../serializer"
3
3
 
4
4
  module CommandConnectors
5
5
  module Serializers
@@ -1,5 +1,5 @@
1
1
  module Foobara
2
- require_project_file("command_connectors", "serializer")
2
+ require_relative "../serializer"
3
3
 
4
4
  module CommandConnectors
5
5
  module Serializers
@@ -1,4 +1,4 @@
1
- Foobara.require_project_file("common", "error")
1
+ require_relative "error"
2
2
 
3
3
  module Foobara
4
4
  # NOTE: annoyingly this will clash with ::RuntimeError if not fully qualified when using
@@ -16,7 +16,6 @@ module Foobara
16
16
  # could be independent projects
17
17
  projects "delegate", # Let's just kill delegate
18
18
  "concerns",
19
- "weak_object_hash",
20
19
  "enumerated",
21
20
  "callback",
22
21
  "state_machine",
@@ -5,7 +5,10 @@ module Foobara
5
5
 
6
6
  class << self
7
7
  def require_project_file(project, path)
8
+ # :nocov:
9
+ warn "DEPRECATION WARNING: require_project_file is deprecated. Use require_relative instead."
8
10
  require_relative("../../#{project}/src/#{path}")
11
+ # :nocov:
9
12
  end
10
13
 
11
14
  attr_accessor :is_installed
@@ -51,7 +51,7 @@ module Foobara
51
51
  end
52
52
 
53
53
  def on_change(object, method_name)
54
- @on_change ||= WeakObjectHash.new
54
+ @on_change ||= ObjectSpace::WeakMap.new
55
55
 
56
56
  @on_change[object] = method_name
57
57
  end
@@ -60,6 +60,7 @@ module Foobara
60
60
  state_machine.commit! do
61
61
  each_table(&:commit!)
62
62
  entity_attributes_crud_driver.commit_transaction(raw_tx)
63
+ each_table(&:committed)
63
64
  each_table(&:transaction_closed)
64
65
  end
65
66
  rescue => e
@@ -86,6 +86,10 @@ module Foobara
86
86
  end
87
87
 
88
88
  def committed
89
+ marked_persisted.each do |record|
90
+ record.fire(:persisted)
91
+ end
92
+
89
93
  closed
90
94
  end
91
95
 
@@ -113,7 +117,8 @@ module Foobara
113
117
  :updated,
114
118
  :hard_deleted,
115
119
  :created,
116
- :loading
120
+ :loading,
121
+ :persisted
117
122
  ]
118
123
 
119
124
  interesting_record_states.each do |state|
@@ -656,6 +656,7 @@ module Foobara
656
656
  record.is_persisted = record.is_loaded = true
657
657
  record.is_created = false
658
658
  record.save_persisted_attributes
659
+ mark_persisted(record)
659
660
  end
660
661
 
661
662
  marked_created.clear
@@ -695,8 +696,6 @@ module Foobara
695
696
  validate!
696
697
  flush_created!
697
698
  flush_updated_and_hard_deleted!
698
-
699
- committed
700
699
  end
701
700
 
702
701
  def revert!
@@ -173,6 +173,8 @@ module Foobara
173
173
  # :nocov:
174
174
  in [] | [Array] | [Array, Hash]
175
175
  rest
176
+ in Array
177
+ [rest]
176
178
  end
177
179
 
178
180
  crud_driver = crud_driver_class.new(*crud_args, **opts, table_prefix:)
@@ -1,8 +1,8 @@
1
1
  module Foobara
2
- require_project_file("state_machine", "sugar")
3
- require_project_file("state_machine", "callbacks")
4
- require_project_file("state_machine", "validations")
5
- require_project_file("state_machine", "transitions")
2
+ require_relative "sugar"
3
+ require_relative "callbacks"
4
+ require_relative "validations"
5
+ require_relative "transitions"
6
6
 
7
7
  # TODO: allow quick creation of a statemachine either through better options to #initialize or a
8
8
  # .for method.
@@ -1,4 +1,4 @@
1
- Foobara.require_project_file("type_declarations", "with_registries")
1
+ require_relative "with_registries"
2
2
 
3
3
  module Foobara
4
4
  module TypeDeclarations
@@ -1,5 +1,5 @@
1
- Foobara.require_project_file("type_declarations", "desugarizer")
2
- Foobara.require_project_file("type_declarations", "handlers/extend_associative_array_type_declaration")
1
+ require_relative "../../desugarizer"
2
+ require_relative "../extend_associative_array_type_declaration"
3
3
 
4
4
  module Foobara
5
5
  module TypeDeclarations
@@ -1,5 +1,5 @@
1
- Foobara.require_project_file("type_declarations", "handlers/registered_type_declaration/to_type_transformer")
2
- Foobara.require_project_file("type_declarations", "handlers/extend_associative_array_type_declaration")
1
+ require_relative "../registered_type_declaration/to_type_transformer"
2
+ require_relative "../extend_associative_array_type_declaration"
3
3
 
4
4
  module Foobara
5
5
  module TypeDeclarations
@@ -1,7 +1,4 @@
1
- Foobara.require_project_file(
2
- "type_declarations",
3
- "handlers/extend_registered_type_declaration/to_type_transformer"
4
- )
1
+ require_relative "../extend_registered_type_declaration/to_type_transformer"
5
2
 
6
3
  module Foobara
7
4
  module TypeDeclarations
@@ -1,4 +1,4 @@
1
- Foobara.require_project_file("type_declarations", "handlers/extend_registered_type_declaration")
1
+ require_relative "extend_registered_type_declaration"
2
2
 
3
3
  module Foobara
4
4
  module TypeDeclarations
@@ -1,4 +1,4 @@
1
- Foobara.require_project_file("type_declarations", "handlers/extend_attributes_type_declaration/hash_desugarizer")
1
+ require_relative "hash_desugarizer"
2
2
 
3
3
  module Foobara
4
4
  module TypeDeclarations
@@ -1,6 +1,6 @@
1
- Foobara.require_project_file("type_declarations", "desugarizer")
2
- Foobara.require_project_file("type_declarations", "handlers/extend_associative_array_type_declaration")
3
- Foobara.require_project_file("type_declarations", "handlers/extend_attributes_type_declaration/hash_desugarizer")
1
+ require_relative "../../desugarizer"
2
+ require_relative "../extend_associative_array_type_declaration"
3
+ require_relative "hash_desugarizer"
4
4
 
5
5
  module Foobara
6
6
  module TypeDeclarations
@@ -1,5 +1,5 @@
1
- Foobara.require_project_file("type_declarations", "desugarizer")
2
- Foobara.require_project_file("type_declarations", "handlers/extend_associative_array_type_declaration")
1
+ require_relative "../../desugarizer"
2
+ require_relative "../extend_associative_array_type_declaration"
3
3
 
4
4
  module Foobara
5
5
  module TypeDeclarations
@@ -1,5 +1,5 @@
1
- Foobara.require_project_file("type_declarations", "handlers/registered_type_declaration/to_type_transformer")
2
- Foobara.require_project_file("type_declarations", "handlers/extend_associative_array_type_declaration")
1
+ require_relative "../registered_type_declaration/to_type_transformer"
2
+ require_relative "../extend_associative_array_type_declaration"
3
3
 
4
4
  module Foobara
5
5
  module TypeDeclarations
@@ -1,5 +1,5 @@
1
- Foobara.require_project_file("type_declarations", "handlers/registered_type_declaration/to_type_transformer")
2
- Foobara.require_project_file("type_declarations", "handlers/extend_associative_array_type_declaration")
1
+ require_relative "../registered_type_declaration/to_type_transformer"
2
+ require_relative "../extend_associative_array_type_declaration"
3
3
 
4
4
  module Foobara
5
5
  module TypeDeclarations
@@ -1,4 +1,4 @@
1
- Foobara.require_project_file("type_declarations", "handlers/registered_type_declaration")
1
+ require_relative "registered_type_declaration"
2
2
 
3
3
  module Foobara
4
4
  module TypeDeclarations
@@ -1,5 +1,5 @@
1
- Foobara.require_project_file("type_declarations", "desugarizer")
2
- Foobara.require_project_file("type_declarations", "handlers/extend_associative_array_type_declaration")
1
+ require_relative "../../desugarizer"
2
+ require_relative "../extend_associative_array_type_declaration"
3
3
 
4
4
  module Foobara
5
5
  module TypeDeclarations
@@ -1,5 +1,5 @@
1
- Foobara.require_project_file("type_declarations", "handlers/registered_type_declaration/to_type_transformer")
2
- Foobara.require_project_file("type_declarations", "handlers/extend_associative_array_type_declaration")
1
+ require_relative "../registered_type_declaration/to_type_transformer"
2
+ require_relative "../extend_associative_array_type_declaration"
3
3
 
4
4
  module Foobara
5
5
  module TypeDeclarations
@@ -1,4 +1,4 @@
1
- Foobara.require_project_file("type_declarations", "to_type_transformer")
1
+ require_relative "../../to_type_transformer"
2
2
 
3
3
  module Foobara
4
4
  module TypeDeclarations
@@ -1,4 +1,4 @@
1
- Foobara.require_project_file("type_declarations", "type_declaration_handler")
1
+ require_relative "../type_declaration_handler"
2
2
 
3
3
  module Foobara
4
4
  module TypeDeclarations
@@ -1,4 +1,4 @@
1
- Foobara.require_project_file("type_declarations", "transformer")
1
+ require_relative "transformer"
2
2
 
3
3
  module Foobara
4
4
  module TypeDeclarations
@@ -1,4 +1,4 @@
1
- Foobara.require_project_file("type_declarations", "with_registries")
1
+ require_relative "with_registries"
2
2
 
3
3
  module Foobara
4
4
  module TypeDeclarations
@@ -1,8 +1,8 @@
1
1
  require "inheritable_thread_vars"
2
2
 
3
3
  module Foobara
4
- require_project_file("type_declarations", "type_builder")
5
- require_project_file("type_declarations", "error_extension")
4
+ require_relative "type_builder"
5
+ require_relative "error_extension"
6
6
 
7
7
  module TypeDeclarations
8
8
  module Mode
@@ -346,6 +346,11 @@ module Foobara
346
346
  @casters = processors
347
347
  end
348
348
 
349
+ def add_caster(processor)
350
+ casters << processor
351
+ clear_caches
352
+ end
353
+
349
354
  def transformers=(processors)
350
355
  clear_caches
351
356
  @transformers = processors
@@ -3,5 +3,5 @@ module Foobara
3
3
  foobara_domain!
4
4
  end
5
5
 
6
- Foobara.require_project_file("value", "processor")
6
+ require_relative "../../src/processor"
7
7
  end
@@ -1,4 +1,4 @@
1
- Foobara.require_project_file("value", "data_error")
1
+ require_relative "../data_error"
2
2
 
3
3
  module Foobara
4
4
  module Value
@@ -1,4 +1,4 @@
1
- Foobara.require_project_file("value", "processor/multi")
1
+ require_relative "multi"
2
2
 
3
3
  module Foobara
4
4
  module Value
@@ -1,5 +1,5 @@
1
- Foobara.require_project_file("value", "processor/multi")
2
- Foobara.require_project_file("value", "data_error")
1
+ require_relative "multi"
2
+ require_relative "../data_error"
3
3
 
4
4
  module Foobara
5
5
  module Value
@@ -1,6 +1,6 @@
1
1
  require "securerandom"
2
2
 
3
- Foobara.require_project_file("value", "processor/runner")
3
+ require_relative "processor/runner"
4
4
 
5
5
  module Foobara
6
6
  module Value
data/version.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module Foobara
2
2
  module Version
3
- VERSION = "0.2.2".freeze
3
+ VERSION = "0.2.4".freeze
4
4
  MINIMUM_RUBY_VERSION = ">= 3.4.0".freeze
5
5
  end
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foobara
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Miles Georgi
@@ -491,16 +491,14 @@ files:
491
491
  - projects/value/src/processor/selection.rb
492
492
  - projects/value/src/transformer.rb
493
493
  - projects/value/src/validator.rb
494
- - projects/weak_object_hash/lib/foobara/weak_object_hash.rb
495
- - projects/weak_object_hash/src/weak_object_hash.rb
496
494
  - projects/weak_object_set/lib/foobara/weak_object_set.rb
497
495
  - projects/weak_object_set/src/weak_object_set.rb
498
496
  - version.rb
499
- homepage: https://foobara.com
497
+ homepage: https://foobara.org
500
498
  licenses:
501
499
  - MPL-2.0
502
500
  metadata:
503
- homepage_uri: https://foobara.com
501
+ homepage_uri: https://foobara.org
504
502
  source_code_uri: https://github.com/foobara/foobara
505
503
  changelog_uri: https://github.com/foobara/foobara/blob/main/CHANGELOG.md
506
504
  rubygems_mfa_required: 'true'
@@ -531,7 +529,6 @@ require_paths:
531
529
  - "./projects/type_declarations/lib"
532
530
  - "./projects/types/lib"
533
531
  - "./projects/value/lib"
534
- - "./projects/weak_object_hash/lib"
535
532
  - "./projects/weak_object_set/lib"
536
533
  required_ruby_version: !ruby/object:Gem::Requirement
537
534
  requirements:
@@ -1,3 +0,0 @@
1
- require "weakref"
2
-
3
- class Foobara::WeakObjectHash; end
@@ -1,225 +0,0 @@
1
- require "monitor"
2
-
3
- module Foobara
4
- # TODO: a possible optimization: have a certain number of records before the Weakref approach kicks in
5
- # that way we don't just immediately clear out useful information without any actual memory burden
6
- class WeakObjectHash
7
- class ClosedError < StandardError; end
8
-
9
- def initialize(skip_finalizer: false)
10
- if skip_finalizer
11
- self.skip_finalizer = true
12
- end
13
- self.monitor = Monitor.new
14
- self.object_ids_to_weak_refs_and_values = {}
15
- end
16
-
17
- def []=(object, value)
18
- object_id = object.object_id
19
- weak_ref = WeakRef.new(object)
20
-
21
- if closed?
22
- raise ClosedError, "Cannot add objects to a closed WeakObjectHash"
23
- end
24
-
25
- monitor.synchronize do
26
- delete(object)
27
-
28
- object_ids_to_weak_refs_and_values[object_id] = [weak_ref, value]
29
-
30
- unless skip_finalizer?
31
- ObjectSpace.define_finalizer(object, finalizer_proc)
32
- end
33
-
34
- value
35
- end
36
- end
37
-
38
- def [](object)
39
- object_id = object.object_id
40
-
41
- if closed?
42
- raise ClosedError, "Cannot retrieve objects from a closed WeakObjectHash"
43
- end
44
-
45
- monitor.synchronize do
46
- pair = object_ids_to_weak_refs_and_values[object_id]
47
-
48
- return nil unless pair
49
-
50
- weak_ref, value = pair
51
-
52
- if weak_ref.weakref_alive?
53
- if skip_finalizer?
54
- if weak_ref.__getobj__ == object
55
- value
56
- else
57
- # :nocov:
58
- object_ids_to_weak_refs_and_values.delete(object_id)
59
- nil
60
- # :nocov:
61
- end
62
- else
63
- value
64
- end
65
- else
66
- # Seems unreachable... if it's been garbage collected how could we have a reference to the object
67
- # to pass it in?
68
- # :nocov:
69
- object_ids_to_weak_refs_and_values.delete(object_id)
70
- nil
71
- # :nocov:
72
- end
73
- end
74
- end
75
-
76
- def delete(object)
77
- object_id = object.object_id
78
-
79
- monitor.synchronize do
80
- pair = object_ids_to_weak_refs_and_values.delete(object_id)
81
-
82
- return nil unless pair
83
-
84
- weak_ref, value = pair
85
-
86
- if weak_ref.weakref_alive?
87
-
88
- if skip_finalizer?
89
- if weak_ref.__getobj__ == object
90
- value
91
- end
92
- else
93
- # Hmmm, there's seemingly no safe way to remove the finalizer for the previous entry
94
- # if it exists. This is because we can only remove all finalizers on object. Not only
95
- # the ones we've created.
96
- # We will just do this anyway with that caveat and maybe make this configuratble in the future.
97
- unless skip_finalizer?
98
- ObjectSpace.undefine_finalizer(object)
99
- end
100
-
101
- value
102
- end
103
- end
104
- end
105
- end
106
-
107
- def each_pair
108
- monitor.synchronize do
109
- object_ids_to_weak_refs_and_values.each_pair do |object_id, pair|
110
- weak_ref, value = pair
111
-
112
- if weak_ref.weakref_alive?
113
- yield weak_ref.__getobj__, value
114
- else
115
- object_ids_to_weak_refs_and_values.delete(object_id)
116
- end
117
- end
118
- end
119
-
120
- self
121
- end
122
-
123
- def values
124
- values = []
125
-
126
- monitor.synchronize do
127
- each_pair do |_key, value|
128
- values << value
129
- end
130
- end
131
-
132
- values
133
- end
134
-
135
- def keys
136
- keys = []
137
-
138
- monitor.synchronize do
139
- each_pair do |key, _value|
140
- keys << key
141
- end
142
- end
143
-
144
- keys
145
- end
146
-
147
- def size
148
- size = 0
149
- to_delete = nil
150
-
151
- monitor.synchronize do
152
- object_ids_to_weak_refs_and_values.each_pair do |object_id, pair|
153
- weak_ref = pair.first
154
-
155
- if weak_ref.weakref_alive?
156
- size += 1
157
- else
158
- to_delete ||= []
159
- to_delete << object_id
160
- end
161
- end
162
-
163
- to_delete&.each do |object_id|
164
- object_ids_to_weak_refs_and_values.delete(object_id)
165
- end
166
- end
167
-
168
- size
169
- end
170
-
171
- def empty?
172
- size == 0
173
- end
174
-
175
- def close!
176
- if closed?
177
- raise ClosedError, "Already closed"
178
- end
179
-
180
- monitor.synchronize do
181
- self.closed = true
182
- clear
183
- @finalizer_proc = nil
184
- self.object_ids_to_weak_refs_and_values = nil
185
- self.monitor = nil
186
- end
187
- end
188
-
189
- def clear
190
- monitor.synchronize do
191
- unless skip_finalizer?
192
- object_ids_to_weak_refs_and_values.each_value do |pair|
193
- weak_ref = pair.first
194
-
195
- if weak_ref.weakref_alive?
196
- ObjectSpace.undefine_finalizer(weak_ref.__getobj__)
197
- end
198
- end
199
- end
200
-
201
- object_ids_to_weak_refs_and_values.clear
202
- end
203
- end
204
-
205
- def closed?
206
- closed
207
- end
208
-
209
- def skip_finalizer?
210
- @skip_finalizer
211
- end
212
-
213
- private
214
-
215
- attr_accessor :object_ids_to_weak_refs_and_values, :monitor, :closed, :skip_finalizer
216
-
217
- def finalizer_proc
218
- @finalizer_proc ||= ->(object_id) do
219
- unless closed?
220
- object_ids_to_weak_refs_and_values.delete(object_id)
221
- end
222
- end
223
- end
224
- end
225
- end