Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 23 additions & 3 deletions lib/ably/realtime/channels.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,37 @@ def fetch(*args)
super
end

# Detaches the {Ably::Realtime::Channel Realtime Channel} and releases all associated resources.
# Releases the {Ably::Realtime::Channel Realtime Channel} with the given name and all associated resources.
#
# Releasing a Realtime Channel is not typically necessary as a channel, once detached, consumes no resources other than
# the memory footprint of the {Ably::Realtime::Channel Realtime Channel object}. Release channels to free up resources if required
#
# A realtime channel should only be released when it is in the +INITIALIZED+, +DETACHED+, or +FAILED+ state;
# releasing a realtime channel in any other state is deprecated and will raise an error in the next major version.
#
# @spec RTS4b, RTS4c, RTS4d
#
# @param channel [String] The name of the channel
#
# @return [void]
#
def release(channel)
get(channel).detach do
return unless @channels.has_key?(channel)

released_channel = get(channel)
if released_channel.initialized? || released_channel.detached? || released_channel.failed?
@channels.delete(channel)
end if @channels.has_key?(channel)
return
end

logger.warn do
"Channels#release: Calling release on a channel in the #{released_channel.state.to_sym} state is deprecated, " \
"and will raise an error in the next major version. " \
"Call Channel#detach and wait for it to complete before calling Channels#release"
end
released_channel.detach do
@channels.delete(channel)
end
end

# Sets channel serial to each channel from given serials hashmap
Expand Down
36 changes: 31 additions & 5 deletions spec/unit/realtime/channels_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,37 @@
end

context 'destroying channels' do
it '#release detaches and then releases the channel resources' do
released_channel = subject.get(channel_name, options)
expect(released_channel).to receive(:detach).and_yield
subject.release(channel_name)
expect(subject.get(channel_name, options).object_id).to_not eql(released_channel.object_id)
let(:released_channel) { subject.get(channel_name, options) }

def stub_state(state)
allow(released_channel).to receive(:state).and_return(Ably::Realtime::Channel::STATE(state))
end

it '#release does nothing if the channel does not exist (RTS4c)' do
expect { subject.release(channel_name) }.to_not raise_error
expect(subject.length).to eql(0)
end

[:initialized, :detached, :failed].each do |state|
it "#release releases a channel in the #{state} state without detaching or logging a warning (RTS4d)" do
stub_state state
expect(released_channel).to_not receive(:detach)
expect(client.logger).to_not receive(:warn)
subject.release(channel_name)
expect(subject.fetch(channel_name) { nil }).to be_nil
end
end

[:attaching, :attached, :detaching, :suspended].each do |state|
it "#release logs a deprecation warning, then detaches and releases a channel in the #{state} state (RTS4b)" do
stub_state state
expect(client.logger).to receive(:warn) do |&block|
expect(block.call).to match(/release on a channel in the #{state} state is deprecated/)
end
expect(released_channel).to receive(:detach).and_yield
subject.release(channel_name)
expect(subject.get(channel_name, options).object_id).to_not eql(released_channel.object_id)
end
end
end

Expand Down
Loading