From 8c32edcc55a4e63eaf6e8be4e4399d75d246fdee Mon Sep 17 00:00:00 2001 From: AKosylo Date: Mon, 9 Oct 2023 14:57:32 +0200 Subject: [PATCH] add CLI DXFeedLiveIpfSample --- DXFeedFramework.xcodeproj/project.pbxproj | 4 + .../xcshareddata/xcschemes/Tools.xcscheme | 4 + Samples/IpfTableApp/ViewController.swift | 1 + Samples/PerfTestCL/LiveIpfCommand.swift | 106 ++++++++++++++++++ Samples/PerfTestCL/main.swift | 6 +- 5 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 Samples/PerfTestCL/LiveIpfCommand.swift diff --git a/DXFeedFramework.xcodeproj/project.pbxproj b/DXFeedFramework.xcodeproj/project.pbxproj index 667cc9c6a..b55092f4a 100644 --- a/DXFeedFramework.xcodeproj/project.pbxproj +++ b/DXFeedFramework.xcodeproj/project.pbxproj @@ -189,6 +189,7 @@ 647426AD2ABC85F20012F793 /* ArgumentParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 647426AC2ABC85F20012F793 /* ArgumentParser.swift */; }; 647426AF2ABC93900012F793 /* EventCode+String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 647426AE2ABC93900012F793 /* EventCode+String.swift */; }; 6479BC2B2A4F35A300A3D404 /* QuoteView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6479BC2A2A4F35A300A3D404 /* QuoteView.swift */; }; + 6486B97F2AD4167800D8D5FA /* LiveIpfCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6486B97E2AD4167800D8D5FA /* LiveIpfCommand.swift */; }; 648BD5692AC450D6004A3A95 /* ConnectCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 648BD5682AC450D6004A3A95 /* ConnectCommand.swift */; }; 648BD56B2AC4576F004A3A95 /* HelpCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 648BD56A2AC4576F004A3A95 /* HelpCommand.swift */; }; 648BD56D2AC56A04004A3A95 /* SubscriptionUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 648BD56C2AC56A04004A3A95 /* SubscriptionUtils.swift */; }; @@ -608,6 +609,7 @@ 647426AC2ABC85F20012F793 /* ArgumentParser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArgumentParser.swift; sourceTree = ""; }; 647426AE2ABC93900012F793 /* EventCode+String.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "EventCode+String.swift"; sourceTree = ""; }; 6479BC2A2A4F35A300A3D404 /* QuoteView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuoteView.swift; sourceTree = ""; }; + 6486B97E2AD4167800D8D5FA /* LiveIpfCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveIpfCommand.swift; sourceTree = ""; }; 648BD5682AC450D6004A3A95 /* ConnectCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectCommand.swift; sourceTree = ""; }; 648BD56A2AC4576F004A3A95 /* HelpCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HelpCommand.swift; sourceTree = ""; }; 648BD56C2AC56A04004A3A95 /* SubscriptionUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionUtils.swift; sourceTree = ""; }; @@ -851,6 +853,7 @@ 641BDD572AC71CCE00236B78 /* LatencyTestCommand.swift */, 645BE8512AC31E7C0028243D /* PerfTestCommand.swift */, 648BD5682AC450D6004A3A95 /* ConnectCommand.swift */, + 6486B97E2AD4167800D8D5FA /* LiveIpfCommand.swift */, 648BD56A2AC4576F004A3A95 /* HelpCommand.swift */, 648BD56C2AC56A04004A3A95 /* SubscriptionUtils.swift */, ); @@ -1847,6 +1850,7 @@ 647426AF2ABC93900012F793 /* EventCode+String.swift in Sources */, 645BE8542AC3229D0028243D /* ToolsCommand.swift in Sources */, 644FE5D12AC1F34000580E3A /* LatencyMetricsPrinter.swift in Sources */, + 6486B97F2AD4167800D8D5FA /* LiveIpfCommand.swift in Sources */, 645BE8522AC31E7C0028243D /* PerfTestCommand.swift in Sources */, 641BDD5D2ACD67A000236B78 /* LatencyListener.swift in Sources */, 641BDD622ACD697B00236B78 /* AbstractEventListener.swift in Sources */, diff --git a/DXFeedFramework.xcodeproj/xcshareddata/xcschemes/Tools.xcscheme b/DXFeedFramework.xcodeproj/xcshareddata/xcschemes/Tools.xcscheme index b9dfa1e6f..e1356a9b5 100644 --- a/DXFeedFramework.xcodeproj/xcshareddata/xcschemes/Tools.xcscheme +++ b/DXFeedFramework.xcodeproj/xcshareddata/xcschemes/Tools.xcscheme @@ -53,6 +53,10 @@ + + ] + + Where: + + where: is URL for the instruments profiles. + Example of url: " + \(LiveIpfCommand.defaultIpfUrl) + """ + var collector: DXInstrumentProfileCollector? + var connection: DXInstrumentProfileConnection? + + func execute() { + var arguments: [String]! + do { + arguments = try ArgumentParser().parse(ProcessInfo.processInfo.arguments, requiredNumberOfArguments: 1) + } catch { + print(fullDescription) + } + do { + collector = try DXInstrumentProfileCollector() + connection = try DXInstrumentProfileConnection(arguments[1], collector!) + // Update period can be used to re-read IPF files, not needed for services supporting IPF "live-update" + try connection?.setUpdatePeriod(60000) + connection?.add(observer: self) + try connection?.start() + // We can wait until we get first full snapshot of instrument profiles + connection?.waitUntilCompleted(10000) + // It is possible to add listener after connection is started - updates will not be missed in this case + try collector?.add(observer: self) + } catch { + print("Error: \(error)") + } + + _ = readLine() + } +} + +extension LiveIpfCommand: DXInstrumentProfileConnectionObserver { + func connectionDidChangeState(old: DXInstrumentProfileConnectionState, new: DXInstrumentProfileConnectionState) { + print("Connection state: \(new)") + } +} + +extension LiveIpfCommand: DXInstrumentProfileUpdateListener { + func instrumentProfilesUpdated(_ instruments: [DXFeedFramework.InstrumentProfile]) { + instruments.forEach { ipf in + if ipf.getIpfType() == .removed { + self.buffer.removeValue(forKey: ipf.symbol) + } else { + self.buffer[ipf.symbol] = ipf + } + } + self.ipfList = self.buffer.map { _, value in + value + }.sorted(by: { ipf1, ipf2 in + ipf1.symbol < ipf2.symbol + }) + print( +""" + +Instrument Profiles: +Total number of profiles (1): \(self.ipfList.count) +Last modified: \(TimeUtil.toLocalDateString(millis: collector?.getLastUpdateTime() ?? 0)) +""" +) + } +} + +extension LiveIpfCommand: Hashable { + static func == (lhs: LiveIpfCommand, rhs: LiveIpfCommand) -> Bool { + return lhs === rhs || lhs.name == rhs.name + } + + func hash(into hasher: inout Hasher) { + hasher.combine(name) + } + +} diff --git a/Samples/PerfTestCL/main.swift b/Samples/PerfTestCL/main.swift index 01475e339..58ba534dc 100644 --- a/Samples/PerfTestCL/main.swift +++ b/Samples/PerfTestCL/main.swift @@ -7,7 +7,11 @@ import Foundation -let commands: [ToolsCommand] = [PerfTestCommand(), ConnectCommand(), LatencyTestCommand(), HelpCommand()] +let commands: [ToolsCommand] = [PerfTestCommand(), + ConnectCommand(), + LatencyTestCommand(), + LiveIpfCommand(), + HelpCommand()] func getCommand(_ cmd: String) -> ToolsCommand? { return commands.first { command in