Skip to content

Commit

Permalink
Merge pull request #1965 from ably/feature/1960-channel-properties
Browse files Browse the repository at this point in the history
[ECO-4933] Added readonly `ARTChannelProperties` object to the public interface
  • Loading branch information
maratal authored Sep 3, 2024
2 parents 8661e4c + 9d213e4 commit 64967f7
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 6 deletions.
33 changes: 32 additions & 1 deletion Source/ARTRealtimeChannel.m
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ - (ARTRealtimeChannelState)state {
return _internal.state;
}

- (ARTChannelProperties *)properties {
return _internal.properties;
}

- (ARTErrorInfo *)errorReason {
return _internal.errorReason;
}
Expand Down Expand Up @@ -636,7 +640,7 @@ - (void)setAttached:(ARTProtocolMessage *)message {
if (message.resumed) {
ARTLogDebug(self.logger, @"R:%p C:%p (%@) channel has resumed", _realtime, self, self.name);
}

// RTL15a
self.attachSerial = message.channelSerial;
// RTL15b
if (message.channelSerial) {
Expand Down Expand Up @@ -1078,6 +1082,18 @@ - (ARTRealtimeChannelOptions *)getOptions_nosync {
return (ARTRealtimeChannelOptions *)[self options_nosync];
}

- (ARTChannelProperties *)properties {
__block ARTChannelProperties *ret;
dispatch_sync(_queue, ^{
ret = [self properties_nosync];
});
return ret;
}

- (ARTChannelProperties *)properties_nosync {
return [[ARTChannelProperties alloc] initWithAttachSerial:_attachSerial channelSerial:_channelSerial];
}

- (void)setOptions:(ARTRealtimeChannelOptions *_Nullable)options callback:(nullable ARTCallback)callback {
if (callback) {
ARTCallback userCallback = callback;
Expand Down Expand Up @@ -1119,6 +1135,21 @@ - (void)setOptions_nosync:(ARTRealtimeChannelOptions *_Nullable)options callback

@end

#pragma mark - Channel Properties (RTL15)

@implementation ARTChannelProperties

- (instancetype)initWithAttachSerial:(NSString *)attachSerial channelSerial:(NSString *)channelSerial {
self = [super init];
if (self) {
_attachSerial = attachSerial;
_channelSerial = channelSerial;
}
return self;
}

@end

#pragma mark - ARTEvent

@implementation ARTEvent (ChannelEvent)
Expand Down
7 changes: 7 additions & 0 deletions Source/PrivateHeaders/Ably/ARTRealtimeChannel+Private.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ NS_ASSUME_NONNULL_BEGIN
- (NSString * _Nullable)clientId_nosync;
- (BOOL)canBeReattached;
- (BOOL)shouldAttach;
- (ARTChannelProperties *)properties_nosync;

@property (readonly, weak, nonatomic) ARTRealtimeInternal *realtime; // weak because realtime owns self
@property (readonly, nonatomic) ARTRestChannelInternal *restChannel;
Expand Down Expand Up @@ -95,4 +96,10 @@ NS_ASSUME_NONNULL_BEGIN

@end

@interface ARTChannelProperties ()

- (instancetype)initWithAttachSerial:(nullable NSString *)attachSerial channelSerial:(nullable NSString *)channelSerial;

@end

NS_ASSUME_NONNULL_END
21 changes: 21 additions & 0 deletions Source/include/Ably/ARTRealtimeChannel.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ NS_ASSUME_NONNULL_BEGIN

@class ARTRealtimePresence;
@class ARTRealtimeChannelOptions;
@class ARTChannelProperties;
#if TARGET_OS_IPHONE
@class ARTPushChannel;
#endif
Expand All @@ -25,6 +26,11 @@ NS_ASSUME_NONNULL_BEGIN
*/
@property (readonly) ARTRealtimeChannelState state;

/**
* An `ARTChannelProperties` object.
*/
@property (readonly) ARTChannelProperties *properties;

/**
* An `ARTErrorInfo` object describing the last error which occurred on the channel, if any.
*/
Expand Down Expand Up @@ -145,6 +151,21 @@ ART_EMBED_INTERFACE_EVENT_EMITTER(ARTChannelEvent, ARTChannelStateChange *)

@end

/**
* Describes the properties of the channel state.
*/
@interface ARTChannelProperties : NSObject
/**
* Starts unset when a channel is instantiated, then updated with the `channelSerial` from each `ARTChannelEventAttached` event that matches the channel. Used as the value for `ARTRealtimeHistoryQuery.untilAttach`.
*/
@property (nonatomic, readonly, nullable) NSString *attachSerial; // CP2a
/**
* Updated by the framework whenever there is some activity on the channel (user message received, presence updated or a channel attached).
*/
@property (nonatomic, readonly, nullable) NSString *channelSerial; // CP2b

@end

/**
* Enables messages to be published and subscribed to. Also enables historic messages to be retrieved and provides access to the `ARTRealtimePresence` object of a channel.
* Also implements `ARTEventEmitter` interface and emits `ARTChannelEvent` events, where a `ARTChannelEvent` is either a `ARTRealtimeChannelState` or an `ARTChannelEvent.ARTChannelEventUpdate`.
Expand Down
11 changes: 6 additions & 5 deletions Test/Tests/RealtimeClientChannelTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ private func testWithUntilAttach(_ untilAttach: Bool, for test: Test, channelNam
let queryString = testHTTPExecutor.requests.last!.url!.query

if query.untilAttach {
expect(queryString).to(contain("fromSerial=\(channel.internal.attachSerial!)"))
expect(queryString).to(contain("fromSerial=\(channel.properties.attachSerial!)"))
} else {
expect(queryString).toNot(contain("fromSerial"))
}
Expand Down Expand Up @@ -4238,7 +4238,7 @@ class RealtimeClientChannelTests: XCTestCase {

// RTL15

// RTL15b
// RTL15a/RTL15b
func test__200__channel_serial_is_updated_whenever_a_protocol_message_with_either_message_presence_or_attached_actions_is_received_in_a_channel() throws {
let test = Test()
let options = try AblyTests.commonAppSetup(for: test)
Expand All @@ -4256,22 +4256,23 @@ class RealtimeClientChannelTests: XCTestCase {
expect(error).to(beNil())
let attachMessage = transport.protocolMessagesReceived.filter { $0.action == .attached }[0]
if attachMessage.channelSerial != nil {
expect(attachMessage.channelSerial).to(equal(channel.internal.channelSerial))
expect(attachMessage.channelSerial).to(equal(channel.properties.attachSerial)) // RTL15a
expect(attachMessage.channelSerial).to(equal(channel.properties.channelSerial)) // RTL15b
}
partialDone()

channel.subscribe { message in
let messageMessage = transport.protocolMessagesReceived.filter { $0.action == .message }[0]
if messageMessage.channelSerial != nil {
expect(messageMessage.channelSerial).to(equal(channel.internal.channelSerial))
expect(messageMessage.channelSerial).to(equal(channel.properties.channelSerial)) // RTL15b
}
channel.presence.enterClient("client1", data: "Hey")
partialDone()
}
channel.presence.subscribe { presenceMessage in
let presenceMessage = transport.protocolMessagesReceived.filter { $0.action == .presence }[0]
if presenceMessage.channelSerial != nil {
expect(presenceMessage.channelSerial).to(equal(channel.internal.channelSerial))
expect(presenceMessage.channelSerial).to(equal(channel.properties.channelSerial)) // RTL15b
}
partialDone()
}
Expand Down

0 comments on commit 64967f7

Please sign in to comment.