mqtt-v5 0.0.1.ci.release
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.
- checksums.yaml +7 -0
- data/lib/mqtt/v5/async/client.rb +27 -0
- data/lib/mqtt/v5/client/authenticator.rb +83 -0
- data/lib/mqtt/v5/client/connection.rb +192 -0
- data/lib/mqtt/v5/client/session.rb +45 -0
- data/lib/mqtt/v5/client.rb +61 -0
- data/lib/mqtt/v5/errors.rb +19 -0
- data/lib/mqtt/v5/packet/auth.rb +57 -0
- data/lib/mqtt/v5/packet/connack.rb +110 -0
- data/lib/mqtt/v5/packet/connect.rb +130 -0
- data/lib/mqtt/v5/packet/disconnect.rb +78 -0
- data/lib/mqtt/v5/packet/ping_req.rb +20 -0
- data/lib/mqtt/v5/packet/ping_resp.rb +20 -0
- data/lib/mqtt/v5/packet/pub_ack.rb +60 -0
- data/lib/mqtt/v5/packet/pub_comp.rb +53 -0
- data/lib/mqtt/v5/packet/pub_rec.rb +60 -0
- data/lib/mqtt/v5/packet/pub_rel.rb +53 -0
- data/lib/mqtt/v5/packet/publish.rb +122 -0
- data/lib/mqtt/v5/packet/reason_code.rb +112 -0
- data/lib/mqtt/v5/packet/sub_ack.rb +66 -0
- data/lib/mqtt/v5/packet/subscribe.rb +87 -0
- data/lib/mqtt/v5/packet/unsub_ack.rb +59 -0
- data/lib/mqtt/v5/packet/unsubscribe.rb +112 -0
- data/lib/mqtt/v5/packet.rb +147 -0
- data/lib/mqtt/v5/packets.rb +25 -0
- data/lib/mqtt/v5/topic_alias/cache.rb +87 -0
- data/lib/mqtt/v5/topic_alias/frequency_weighted_policy.rb +50 -0
- data/lib/mqtt/v5/topic_alias/length_weighted_policy.rb +20 -0
- data/lib/mqtt/v5/topic_alias/lru_policy.rb +36 -0
- data/lib/mqtt/v5/topic_alias/manager.rb +143 -0
- data/lib/mqtt/v5/topic_alias/policy.rb +34 -0
- data/lib/mqtt/v5/topic_alias/weighted_policy.rb +48 -0
- data/lib/mqtt/v5/topic_alias.rb +27 -0
- data/lib/mqtt/v5/version.rb +11 -0
- data/lib/mqtt/v5.rb +4 -0
- metadata +88 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'weighted_policy'
|
|
4
|
+
|
|
5
|
+
module MQTT
|
|
6
|
+
module V5
|
|
7
|
+
module TopicAlias
|
|
8
|
+
# Scores topics by `hits * bytesize. Tracks hit counts for all topics
|
|
9
|
+
class FrequencyWeightedPolicy
|
|
10
|
+
include WeightedPolicy
|
|
11
|
+
|
|
12
|
+
# The minimum topic size for a new topic to avoid O(n) scan of the topic list for each eviction
|
|
13
|
+
attr_reader :min_topic_score
|
|
14
|
+
|
|
15
|
+
def initialize
|
|
16
|
+
super
|
|
17
|
+
@hits = Hash.new(0)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# @!attribute [r] hits
|
|
21
|
+
# @return [Hash<String,Integer>] (frozen) topics by the number of times they have been published to.
|
|
22
|
+
def hits
|
|
23
|
+
@hits.dup.freeze
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Delete topics from the map (ie because they won't be used again) and recalculate the minimum topic score.
|
|
27
|
+
def clean!(*topics)
|
|
28
|
+
topics.each { |t| @hits.delete(t) }
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Evict the topic with the lowest score, unless the new_topic is even lower.
|
|
32
|
+
def evict(new_topic, &)
|
|
33
|
+
super.tap { |victim| @hits[new_topic] += 1 unless victim }
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Record a hit for topic, check if lower than minimum score.
|
|
37
|
+
def alias_hit(topic)
|
|
38
|
+
@hits[topic] += 1
|
|
39
|
+
super
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
def topic_score(topic, new: false)
|
|
45
|
+
(@hits[topic] + (new ? 1 : 0)) * topic.bytesize
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'weighted_policy'
|
|
4
|
+
|
|
5
|
+
module MQTT
|
|
6
|
+
module V5
|
|
7
|
+
module TopicAlias
|
|
8
|
+
# Minimum length policy - only aliases topics above a minimum size, evicts shortest
|
|
9
|
+
class LengthWeightedPolicy
|
|
10
|
+
include WeightedPolicy
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def topic_score(topic, **)
|
|
15
|
+
topic.bytesize
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MQTT
|
|
4
|
+
module V5
|
|
5
|
+
module TopicAlias
|
|
6
|
+
# Least Recently Used replacement policy
|
|
7
|
+
class LRUPolicy
|
|
8
|
+
def initialize
|
|
9
|
+
@topics = Set.new
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Alias any topic
|
|
13
|
+
def aliasable?(_packet)
|
|
14
|
+
true
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Evict the first entry in the Set (ie the least recently used)
|
|
18
|
+
def evict(_topic, &)
|
|
19
|
+
@topics.first
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Move the topic to the end of the Set (ie make it the most recently used)
|
|
23
|
+
def alias_hit(topic)
|
|
24
|
+
# Move the topic to the end of the set (relies on Set being ordered)
|
|
25
|
+
@topics.delete(topic)
|
|
26
|
+
@topics << topic
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Delete the evicted topic from the Set
|
|
30
|
+
def alias_evicted(topic)
|
|
31
|
+
@topics.delete(topic)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'cache'
|
|
4
|
+
require_relative 'lru_policy'
|
|
5
|
+
|
|
6
|
+
module MQTT
|
|
7
|
+
module V5
|
|
8
|
+
module TopicAlias
|
|
9
|
+
# Manages topic aliases for a connection
|
|
10
|
+
class Manager
|
|
11
|
+
# maximum size of alias caches
|
|
12
|
+
MAXIMUM_ALIAS_ID = 65_535
|
|
13
|
+
|
|
14
|
+
# @return [Cache|nil] the incoming Cache
|
|
15
|
+
attr_reader :incoming
|
|
16
|
+
|
|
17
|
+
# @return [Cache|nil] the outgoing Cache
|
|
18
|
+
attr_reader :outgoing
|
|
19
|
+
|
|
20
|
+
# @return [Policy] the policy used to manage the outgoing Cache
|
|
21
|
+
attr_reader :policy
|
|
22
|
+
|
|
23
|
+
# Topic Alias Management
|
|
24
|
+
#
|
|
25
|
+
# Outgoing aliasing upper limit and replacement policy is configured by properties to {#initialize}
|
|
26
|
+
#
|
|
27
|
+
# For a Client...
|
|
28
|
+
# - Outgoing limit is further restricted by the CONNACK response from the Server.
|
|
29
|
+
# - Incoming limit is configured in the CONNECT packet. Records alias information as received from Server.
|
|
30
|
+
#
|
|
31
|
+
# For a Server...
|
|
32
|
+
# - Outgoing limit is further restricted by the CONNECT packet received from the Client.
|
|
33
|
+
# - Incoming limit is configured in the CONNACK packet. Records alias information as received from Client.
|
|
34
|
+
#
|
|
35
|
+
# @param [Integer|nil] send_maximum
|
|
36
|
+
# maximum number of topic aliases to hold for outgoing PUBLISH packets
|
|
37
|
+
#
|
|
38
|
+
# - `nil` will mean the value is determined only by the response from the other side
|
|
39
|
+
# - `0` (default) disables outgoing aliasing regardless of what the other side will accept
|
|
40
|
+
#
|
|
41
|
+
# @param [Policy|nil] policy replacement policy for evicting topics from the outgoing cache when
|
|
42
|
+
# it is full.
|
|
43
|
+
#
|
|
44
|
+
# - `nil` will use {LRUPolicy} as the default policy
|
|
45
|
+
#
|
|
46
|
+
# @return [Manager]
|
|
47
|
+
def initialize(send_maximum: 0, policy: nil)
|
|
48
|
+
@configured_outgoing_maximum = send_maximum || MAXIMUM_ALIAS_ID
|
|
49
|
+
@policy = policy
|
|
50
|
+
@policy ||= LRUPolicy.new if @configured_outgoing_maximum.positive?
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# @visibility private
|
|
54
|
+
# Clear incoming alias cache
|
|
55
|
+
# - called from Client with CONNECT packet it will send to Server
|
|
56
|
+
# - called from Server with CONNACK packet it will send to Client
|
|
57
|
+
def clear_incoming!(packet)
|
|
58
|
+
@incoming = Cache.create(packet.topic_alias_maximum)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# @visibility private
|
|
62
|
+
# Clear outgoing alias cache
|
|
63
|
+
# - called from Client with CONNACK packet received from Server
|
|
64
|
+
# - called from Server with CONNECT packet received from Client
|
|
65
|
+
def clear_outgoing!(packet)
|
|
66
|
+
max = [@configured_outgoing_maximum, packet.topic_alias_maximum || 0].min
|
|
67
|
+
@outgoing = Cache.create(max)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# @visibility private
|
|
71
|
+
# Process incoming PUBLISH packet - resolve alias and update packet
|
|
72
|
+
# @param packet [Packet::Publish] incoming PUBLISH packet
|
|
73
|
+
# @raise [ProtocolError] if alias exceeds the maximum or cannot be resolved
|
|
74
|
+
def handle_incoming(packet)
|
|
75
|
+
return unless packet.topic_alias&.positive?
|
|
76
|
+
|
|
77
|
+
if (max = incoming&.max || 0) < packet.topic_alias
|
|
78
|
+
raise TopicAliasInvalid, "#{packet.topic_alias} exceeds maximum #{max}"
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
if packet.topic_name.empty?
|
|
82
|
+
resolved_topic = @incoming.resolve(packet.topic_alias)
|
|
83
|
+
raise TopicAliasInvalid, "Unknown topic alias #{packet.topic_alias}" unless resolved_topic
|
|
84
|
+
|
|
85
|
+
# override the empty topic name with the resolved topic
|
|
86
|
+
packet.apply_alias(name: resolved_topic)
|
|
87
|
+
else
|
|
88
|
+
@incoming.add(packet.topic_alias, packet.topic_name)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Force removal of an outgoing topic from the alias cache. eg. because it is not going to be used any more.
|
|
93
|
+
# @param [Array<String>] topics the topics to remove
|
|
94
|
+
# @return [void]
|
|
95
|
+
# @note Prefer sending `topic_alias: false` to {Client#publish} to indicate topics that should not be aliased
|
|
96
|
+
def evict!(*topics)
|
|
97
|
+
topics.each do |topic|
|
|
98
|
+
@outgoing&.remove(topic) && @policy.alias_evicted(topic)
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# @visibility private
|
|
103
|
+
# Get outgoing alias for topic (policy decides whether to alias and what to evict)
|
|
104
|
+
def handle_outgoing(packet)
|
|
105
|
+
return unless @outgoing && @policy&.aliasable?(packet)
|
|
106
|
+
|
|
107
|
+
if (alias_id = @outgoing.resolve(packet.topic_name))
|
|
108
|
+
return outgoing_alias_hit(alias_id, packet)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
outgoing_alias_miss(packet)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
private
|
|
115
|
+
|
|
116
|
+
def outgoing_alias_hit(alias_id, packet)
|
|
117
|
+
# We had one already, but we don't want to keep it any more (might as well use it now though)
|
|
118
|
+
evict!(packet.topic_name) unless packet.assign_alias?
|
|
119
|
+
|
|
120
|
+
@policy.alias_hit(packet.topic_name)
|
|
121
|
+
# We've seen and sent this one before, just send the alias_id and an empty topic name
|
|
122
|
+
packet.apply_alias(alias: alias_id, name: '')
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def outgoing_alias_miss(packet)
|
|
126
|
+
return unless packet.assign_alias? # We don't want to alias this topic
|
|
127
|
+
|
|
128
|
+
alias_id = @outgoing.assign
|
|
129
|
+
unless alias_id
|
|
130
|
+
(evict = @policy.evict(packet.topic_name) { @outgoing.topics }) && evict!(evict)
|
|
131
|
+
alias_id = @outgoing.assign
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
return unless alias_id # evicting did not result in an available alias
|
|
135
|
+
|
|
136
|
+
@policy.alias_hit(packet.topic_name)
|
|
137
|
+
@outgoing.add(alias_id, packet.topic_name)
|
|
138
|
+
packet.apply_alias(alias: alias_id)
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MQTT
|
|
4
|
+
module V5
|
|
5
|
+
module TopicAlias
|
|
6
|
+
# Defaults the policy interface for evicting topics from a full Cache
|
|
7
|
+
# @abstract
|
|
8
|
+
module Policy
|
|
9
|
+
# @!method aliasable?(packet)
|
|
10
|
+
# @abstract
|
|
11
|
+
# @param [Packet::Publish] packet
|
|
12
|
+
# @return [Boolean] whether the packet is eligible for aliasing
|
|
13
|
+
|
|
14
|
+
# @method alias_evicted(topic)
|
|
15
|
+
# Called when an alias is evicted
|
|
16
|
+
# @param [String] topic The topic that was evicted.
|
|
17
|
+
# @return [void]
|
|
18
|
+
|
|
19
|
+
# @!method alias_hit(topic)
|
|
20
|
+
# Called when an alias is used (including the first time a topic is aliased)
|
|
21
|
+
# @param [String] topic
|
|
22
|
+
# @return [void]
|
|
23
|
+
|
|
24
|
+
# @!method evict(topic)
|
|
25
|
+
# Choose a topic to evict
|
|
26
|
+
# @param [String] topic The new topic that is looking for an alias
|
|
27
|
+
# @yield()
|
|
28
|
+
# @yieldreturn [Array<String>] the list of topics currently in the cache
|
|
29
|
+
# @return [String, nil] topic to evict
|
|
30
|
+
# @return [nil] evict nothing (ie do not alias the topic)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MQTT
|
|
4
|
+
module V5
|
|
5
|
+
module TopicAlias
|
|
6
|
+
# Base module for evicting {Policy} based on a minimum topic score
|
|
7
|
+
module WeightedPolicy
|
|
8
|
+
def initialize
|
|
9
|
+
@min_topic_score = 0
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Aliases everything
|
|
13
|
+
def aliasable?(_packet)
|
|
14
|
+
true
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Evict the topic with the lowest score, unless the new_topic is even lower.
|
|
18
|
+
def evict(new_topic, &topics)
|
|
19
|
+
new_topic_score = topic_score(new_topic, new: true)
|
|
20
|
+
|
|
21
|
+
return nil unless new_topic_score >= @min_topic_score
|
|
22
|
+
|
|
23
|
+
victim = topics.call.min_by { |t| topic_score(t) }
|
|
24
|
+
@min_topic_score = topic_score(victim)
|
|
25
|
+
return victim if new_topic_score >= @min_topic_score
|
|
26
|
+
|
|
27
|
+
nil
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Record a hit for topic, check if lower than minimum score.
|
|
31
|
+
def alias_hit(topic)
|
|
32
|
+
@min_topic_score = [topic_score(topic), @min_topic_score].min
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Does nothing on eviction.
|
|
36
|
+
def alias_evicted(_topic)
|
|
37
|
+
# does not change scores
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# @!method topic_score(topic, new: false)
|
|
41
|
+
# @abstract
|
|
42
|
+
# @param topic [String]
|
|
43
|
+
# @param new [Boolean] whether the topic is new (ie has not been aliased before)
|
|
44
|
+
# @return [Integer] the score of the topic
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'topic_alias/cache'
|
|
4
|
+
require_relative 'topic_alias/policy'
|
|
5
|
+
require_relative 'topic_alias/lru_policy'
|
|
6
|
+
require_relative 'topic_alias/frequency_weighted_policy'
|
|
7
|
+
require_relative 'topic_alias/length_weighted_policy'
|
|
8
|
+
require_relative 'topic_alias/manager'
|
|
9
|
+
|
|
10
|
+
module MQTT
|
|
11
|
+
module V5
|
|
12
|
+
# Topic Alias support for MQTT 5.0
|
|
13
|
+
#
|
|
14
|
+
# Provides bidirectional topic aliasing for Clients/Servers to reduce bandwidth usage by replacing
|
|
15
|
+
# repetitive topic names with small integer identifiers.
|
|
16
|
+
#
|
|
17
|
+
# @example Basic usage with default LRUPolicy policy
|
|
18
|
+
# alias_manager = MQTT::V5::TopicAlias::Manager.new(send_maximum: 100)
|
|
19
|
+
#
|
|
20
|
+
# @example Custom policy
|
|
21
|
+
# policy = MQTT::V5::TopicAlias::FrequencyWeightedPolicy.new
|
|
22
|
+
# alias_manager = MQTT::V5::TopicAlias::Manager.new(send_maximum: 50, policy: policy )
|
|
23
|
+
# @see Client#topic_aliases
|
|
24
|
+
module TopicAlias
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
data/lib/mqtt/v5.rb
ADDED
metadata
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: mqtt-v5
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1.ci.release
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Grant Gardner
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: mqtt-core
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '0'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '0'
|
|
26
|
+
description: MQTT version 5.0 protocol implementation
|
|
27
|
+
email:
|
|
28
|
+
- grant@lastweekend.com.au
|
|
29
|
+
executables: []
|
|
30
|
+
extensions: []
|
|
31
|
+
extra_rdoc_files: []
|
|
32
|
+
files:
|
|
33
|
+
- lib/mqtt/v5.rb
|
|
34
|
+
- lib/mqtt/v5/async/client.rb
|
|
35
|
+
- lib/mqtt/v5/client.rb
|
|
36
|
+
- lib/mqtt/v5/client/authenticator.rb
|
|
37
|
+
- lib/mqtt/v5/client/connection.rb
|
|
38
|
+
- lib/mqtt/v5/client/session.rb
|
|
39
|
+
- lib/mqtt/v5/errors.rb
|
|
40
|
+
- lib/mqtt/v5/packet.rb
|
|
41
|
+
- lib/mqtt/v5/packet/auth.rb
|
|
42
|
+
- lib/mqtt/v5/packet/connack.rb
|
|
43
|
+
- lib/mqtt/v5/packet/connect.rb
|
|
44
|
+
- lib/mqtt/v5/packet/disconnect.rb
|
|
45
|
+
- lib/mqtt/v5/packet/ping_req.rb
|
|
46
|
+
- lib/mqtt/v5/packet/ping_resp.rb
|
|
47
|
+
- lib/mqtt/v5/packet/pub_ack.rb
|
|
48
|
+
- lib/mqtt/v5/packet/pub_comp.rb
|
|
49
|
+
- lib/mqtt/v5/packet/pub_rec.rb
|
|
50
|
+
- lib/mqtt/v5/packet/pub_rel.rb
|
|
51
|
+
- lib/mqtt/v5/packet/publish.rb
|
|
52
|
+
- lib/mqtt/v5/packet/reason_code.rb
|
|
53
|
+
- lib/mqtt/v5/packet/sub_ack.rb
|
|
54
|
+
- lib/mqtt/v5/packet/subscribe.rb
|
|
55
|
+
- lib/mqtt/v5/packet/unsub_ack.rb
|
|
56
|
+
- lib/mqtt/v5/packet/unsubscribe.rb
|
|
57
|
+
- lib/mqtt/v5/packets.rb
|
|
58
|
+
- lib/mqtt/v5/topic_alias.rb
|
|
59
|
+
- lib/mqtt/v5/topic_alias/cache.rb
|
|
60
|
+
- lib/mqtt/v5/topic_alias/frequency_weighted_policy.rb
|
|
61
|
+
- lib/mqtt/v5/topic_alias/length_weighted_policy.rb
|
|
62
|
+
- lib/mqtt/v5/topic_alias/lru_policy.rb
|
|
63
|
+
- lib/mqtt/v5/topic_alias/manager.rb
|
|
64
|
+
- lib/mqtt/v5/topic_alias/policy.rb
|
|
65
|
+
- lib/mqtt/v5/topic_alias/weighted_policy.rb
|
|
66
|
+
- lib/mqtt/v5/version.rb
|
|
67
|
+
licenses:
|
|
68
|
+
- MIT
|
|
69
|
+
metadata:
|
|
70
|
+
rubygems_mfa_required: 'true'
|
|
71
|
+
rdoc_options: []
|
|
72
|
+
require_paths:
|
|
73
|
+
- lib
|
|
74
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
75
|
+
requirements:
|
|
76
|
+
- - ">="
|
|
77
|
+
- !ruby/object:Gem::Version
|
|
78
|
+
version: '3.4'
|
|
79
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
80
|
+
requirements:
|
|
81
|
+
- - ">="
|
|
82
|
+
- !ruby/object:Gem::Version
|
|
83
|
+
version: '0'
|
|
84
|
+
requirements: []
|
|
85
|
+
rubygems_version: 3.6.9
|
|
86
|
+
specification_version: 4
|
|
87
|
+
summary: Ruby MQTT 5.0
|
|
88
|
+
test_files: []
|