async-matrix-bridge 2.0.0 → 3.0.0

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.
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the Apache License, Version 2.0.
4
+ # Copyright, 2026, by General Intelligence Systems.
5
+
6
+ require "async/matrix"
7
+ require "async/rest/wrapper/json"
8
+
9
+ module Async
10
+ module Matrix
11
+ module Bridge
12
+ # What the homeserver pushed, which is to a service what a sync batch is to a client.
13
+ #
14
+ # A representation is an instance of a resource at a point in time, and that is what this is:
15
+ # the difference is that it was handed over rather than fetched, so the value is given at
16
+ # construction and never read from a response.
17
+ #
18
+ # Being a representation is what makes it match: {Async::Matrix::Representation} already
19
+ # deconstructs to its own document, so a whole transaction can be a pattern.
20
+ class Transaction < Async::Matrix::Representation
21
+ # Read one from a request, parsing it with the wrapper a response would have used.
22
+ #
23
+ # @parameter request [Protocol::HTTP::Request] the request the homeserver made.
24
+ # @parameter txn_id [String] the transaction, which the homeserver numbers.
25
+ # @parameter version [String] the specification version to type the events as.
26
+ # @returns [Transaction] the transaction it carried.
27
+ def self.for(request, txn_id, version: Async::Matrix::LATEST)
28
+ value = ::Async::REST::Wrapper::JSON::Parser.new(request.body).join
29
+
30
+ self.new(nil, value: value, metadata: request.headers, txn_id: txn_id, version: version)
31
+ end
32
+
33
+ # @parameter resource [Nil] nothing: there is no resource to fetch this again from.
34
+ # @parameter value [Hash] the document the homeserver sent.
35
+ # @parameter metadata [Protocol::HTTP::Headers] the headers it arrived with.
36
+ # @parameter txn_id [String] the transaction, which the homeserver numbers.
37
+ # @parameter version [String] the specification version to type the events as.
38
+ def initialize(resource, value:, metadata: {}, txn_id: nil, version: Async::Matrix::LATEST)
39
+ super(resource, value: value, metadata: metadata)
40
+
41
+ @txn_id = txn_id
42
+ @events = Async::Matrix::Events.registry(version)
43
+ end
44
+
45
+ # @attribute [String] the transaction, which makes handling it twice unnecessary.
46
+ attr :txn_id
47
+
48
+ # The timeline, typed as the registry describes it.
49
+ #
50
+ # @returns [Array(Async::Matrix::Events::Envelope)] the events.
51
+ def events
52
+ (self.value[:events] || []).map{|value| @events.wrap(value)}
53
+ end
54
+
55
+ # Read receipts, typing and presence, which arrive only when the registration asked for them.
56
+ #
57
+ # @returns [Array(Async::Matrix::Events::Envelope)] the events.
58
+ def ephemeral
59
+ (self.value[:ephemeral] || []).map{|value| @events.wrap(value)}
60
+ end
61
+
62
+ # @returns [Boolean] whether this transaction carried nothing at all.
63
+ def empty?
64
+ self.events.empty? and self.ephemeral.empty?
65
+ end
66
+
67
+ # The events of each room, in the order they were sent.
68
+ #
69
+ # Events in one room are ordered and must stay so, because a message can depend on the
70
+ # membership before it and a key on the session before that. Different rooms are independent,
71
+ # so a caller may handle them at the same time.
72
+ #
73
+ # @yields {|room_id, events| ...}
74
+ # @parameter room_id [String] the room.
75
+ # @parameter events [Array(Async::Matrix::Events::Envelope)] its events, in order.
76
+ def each_room
77
+ if block_given?
78
+ self.events.group_by(&:room_id).each do |room_id, events|
79
+ yield room_id, events
80
+ end
81
+ else
82
+ to_enum(:each_room)
83
+ end
84
+ end
85
+
86
+ def inspect = "\#<#{self.class} #{@txn_id} #{self.events.size} event(s)>"
87
+ end
88
+ end
89
+ end
90
+ end
@@ -41,42 +41,3 @@ module Async
41
41
  end
42
42
  end
43
43
  end
44
-
45
- __END__
46
- describe "Async::Matrix::Bridge::TransactionStore" do
47
- it "tracks seen transaction IDs" do
48
- store = Async::Matrix::Bridge::TransactionStore.new
49
- store.seen?("txn1").should == false
50
- store.mark_seen("txn1")
51
- store.seen?("txn1").should == true
52
- end
53
-
54
- it "reports size" do
55
- store = Async::Matrix::Bridge::TransactionStore.new
56
- store.size.should == 0
57
- store.mark_seen("a")
58
- store.mark_seen("b")
59
- store.size.should == 2
60
- end
61
-
62
- it "prunes oldest entries when capacity is reached" do
63
- store = Async::Matrix::Bridge::TransactionStore.new(capacity: 4)
64
- store.mark_seen("a")
65
- store.mark_seen("b")
66
- store.mark_seen("c")
67
- store.mark_seen("d")
68
- # This triggers prune — drops oldest half (a, b)
69
- store.mark_seen("e")
70
- store.seen?("a").should == false
71
- store.seen?("b").should == false
72
- store.seen?("d").should == true
73
- store.seen?("e").should == true
74
- end
75
-
76
- it "does not prune below capacity" do
77
- store = Async::Matrix::Bridge::TransactionStore.new(capacity: 10)
78
- 5.times { |i| store.mark_seen("txn#{i}") }
79
- store.size.should == 5
80
- store.seen?("txn0").should == true
81
- end
82
- end
@@ -6,7 +6,7 @@
6
6
  module Async
7
7
  module Matrix
8
8
  module Bridge
9
- VERSION = "2.0.0"
9
+ VERSION = "3.0.0"
10
10
  end
11
11
  end
12
12
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: async-matrix-bridge
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nathan Kidd
@@ -29,42 +29,34 @@ dependencies:
29
29
  requirements:
30
30
  - - "~>"
31
31
  - !ruby/object:Gem::Version
32
- version: '3.0'
33
- type: :runtime
34
- prerelease: false
35
- version_requirements: !ruby/object:Gem::Requirement
36
- requirements:
37
- - - "~>"
38
- - !ruby/object:Gem::Version
39
- version: '3.0'
40
- - !ruby/object:Gem::Dependency
41
- name: json_schemer
42
- requirement: !ruby/object:Gem::Requirement
43
- requirements:
44
- - - "~>"
32
+ version: '4.0'
33
+ - - ">="
45
34
  - !ruby/object:Gem::Version
46
- version: '2.5'
35
+ version: 4.0.1
47
36
  type: :runtime
48
37
  prerelease: false
49
38
  version_requirements: !ruby/object:Gem::Requirement
50
39
  requirements:
51
40
  - - "~>"
52
41
  - !ruby/object:Gem::Version
53
- version: '2.5'
42
+ version: '4.0'
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: 4.0.1
54
46
  - !ruby/object:Gem::Dependency
55
- name: scampi
47
+ name: protocol-http
56
48
  requirement: !ruby/object:Gem::Requirement
57
49
  requirements:
58
50
  - - "~>"
59
51
  - !ruby/object:Gem::Version
60
- version: '1.0'
61
- type: :development
52
+ version: '0.72'
53
+ type: :runtime
62
54
  prerelease: false
63
55
  version_requirements: !ruby/object:Gem::Requirement
64
56
  requirements:
65
57
  - - "~>"
66
58
  - !ruby/object:Gem::Version
67
- version: '1.0'
59
+ version: '0.72'
68
60
  - !ruby/object:Gem::Dependency
69
61
  name: logger
70
62
  requirement: !ruby/object:Gem::Requirement
@@ -102,13 +94,14 @@ executables: []
102
94
  extensions: []
103
95
  extra_rdoc_files: []
104
96
  files:
97
+ - CHANGELOG.md
105
98
  - LICENSE
106
99
  - README.md
107
100
  - lib/async/matrix/bridge.rb
108
- - lib/async/matrix/bridge/endpoint.rb
101
+ - lib/async/matrix/bridge/puppet.rb
109
102
  - lib/async/matrix/bridge/registration.rb
110
- - lib/async/matrix/bridge/registration/schema/namespace_list.json
111
- - lib/async/matrix/bridge/registration/schema/registration.json
103
+ - lib/async/matrix/bridge/service.rb
104
+ - lib/async/matrix/bridge/transaction.rb
112
105
  - lib/async/matrix/bridge/transaction_store.rb
113
106
  - lib/async/matrix/bridge/version.rb
114
107
  homepage: https://github.com/general-intelligence-systems/async-matrix-bridge