From cb8a66632d4dc2cda094ba196571abf540f6cef1 Mon Sep 17 00:00:00 2001 From: Kristian Dimitrov Date: Thu, 23 Aug 2018 14:33:55 +0300 Subject: [PATCH] feat: use long living socket connection for sync --- lib/definitions/livesync.d.ts | 10 +++++ ...android-device-livesync-sockets-service.ts | 37 +++++++++++++------ .../livesync/android-livesync-tool.ts | 6 +++ 3 files changed, 42 insertions(+), 11 deletions(-) diff --git a/lib/definitions/livesync.d.ts b/lib/definitions/livesync.d.ts index 4989f16056..0c4bed77c2 100644 --- a/lib/definitions/livesync.d.ts +++ b/lib/definitions/livesync.d.ts @@ -398,6 +398,11 @@ interface IAndroidNativeScriptDeviceLiveSyncService extends INativeScriptDeviceL } interface IAndroidLivesyncTool { + /** + * The protocol version the current app(adnroid runtime) is using. + */ + protocolVersion: string; + /** * Creates new socket connection. * @param configuration - The configuration to the socket connection. @@ -457,6 +462,11 @@ interface IAndroidLivesyncTool { * @param error - Optional error for rejecting pending sync operations */ end(error?: Error): void; + + /** + * Returns true if a connection has been already established + */ + hasConnection(): boolean; } interface IAndroidLivesyncToolConfiguration { diff --git a/lib/services/livesync/android-device-livesync-sockets-service.ts b/lib/services/livesync/android-device-livesync-sockets-service.ts index 9a00dc1e94..bfac2a5392 100644 --- a/lib/services/livesync/android-device-livesync-sockets-service.ts +++ b/lib/services/livesync/android-device-livesync-sockets-service.ts @@ -6,10 +6,12 @@ import { LiveSyncPaths } from "../../common/constants"; import { AndroidLivesyncTool } from "./android-livesync-tool"; import * as path from "path"; import * as temp from "temp"; +import * as semver from "semver"; export class AndroidDeviceSocketsLiveSyncService extends DeviceLiveSyncServiceBase implements IAndroidNativeScriptDeviceLiveSyncService, INativeScriptDeviceLiveSyncService { private livesyncTool: IAndroidLivesyncTool; private static STATUS_UPDATE_INTERVAL = 10000; + private static MINIMAL_VERSION_LONG_LIVING_CONNECTION = "0.2.0"; constructor( private data: IProjectData, @@ -20,19 +22,18 @@ export class AndroidDeviceSocketsLiveSyncService extends DeviceLiveSyncServiceBa protected device: Mobile.IAndroidDevice, private $options: ICommonOptions, private $processService: IProcessService, - private $fs: IFileSystem) { + private $fs: IFileSystem, + private $devicePlatformsConstants: Mobile.IDevicePlatformsConstants) { super($platformsData, device); this.livesyncTool = this.$injector.resolve(AndroidLivesyncTool); } public async beforeLiveSyncAction(deviceAppData: Mobile.IDeviceAppData): Promise { - const platformData = this.$platformsData.getPlatformData(deviceAppData.platform, this.data); - const projectFilesPath = path.join(platformData.appDestinationDirectoryPath, APP_FOLDER_NAME); const pathToLiveSyncFile = temp.path({ prefix: "livesync" }); this.$fs.writeFile(pathToLiveSyncFile, ""); await this.device.fileSystem.putFile(pathToLiveSyncFile, this.getPathToLiveSyncFileOnDevice(deviceAppData.appIdentifier), deviceAppData.appIdentifier); await this.device.applicationManager.startApplication({ appId: deviceAppData.appIdentifier, projectName: this.data.projectName, justLaunch: true }); - await this.connectLivesyncTool(projectFilesPath, this.data.projectId); + await this.connectLivesyncTool(this.data.projectId); } private getPathToLiveSyncFileOnDevice(appIdentifier: string): string { @@ -42,8 +43,11 @@ export class AndroidDeviceSocketsLiveSyncService extends DeviceLiveSyncServiceBa public async finalizeSync(liveSyncInfo: ILiveSyncResultInfo, projectData: IProjectData): Promise { try { const result = await this.doSync(liveSyncInfo, projectData); + if (!semver.gte(this.livesyncTool.protocolVersion, AndroidDeviceSocketsLiveSyncService.MINIMAL_VERSION_LONG_LIVING_CONNECTION)) { + this.livesyncTool.end(); + } return result; - } finally { + } catch (e) { this.livesyncTool.end(); } } @@ -85,6 +89,13 @@ export class AndroidDeviceSocketsLiveSyncService extends DeviceLiveSyncServiceBa const canExecuteFastSync = !liveSyncInfo.isFullSync && this.canExecuteFastSyncForPaths(liveSyncInfo.modifiedFilesData, projectData, this.device.deviceInfo.platform); if (!canExecuteFastSync || !liveSyncInfo.didRefresh) { await this.device.applicationManager.restartApplication({ appId: liveSyncInfo.deviceAppData.appIdentifier, projectName: projectData.projectName }); + if (this.livesyncTool.protocolVersion && semver.gte(this.livesyncTool.protocolVersion, AndroidDeviceSocketsLiveSyncService.MINIMAL_VERSION_LONG_LIVING_CONNECTION)) { + try { + await this.connectLivesyncTool(liveSyncInfo.deviceAppData.appIdentifier); + } catch (e) { + this.$logger.trace("Failed to connect after app restart."); + } + } } } @@ -143,12 +154,16 @@ export class AndroidDeviceSocketsLiveSyncService extends DeviceLiveSyncServiceBa return transferredLocalToDevicePaths; } - private async connectLivesyncTool(projectFilesPath: string, appIdentifier: string) { - await this.livesyncTool.connect({ - appIdentifier, - deviceIdentifier: this.device.deviceInfo.identifier, - appPlatformsPath: projectFilesPath - }); + private async connectLivesyncTool(appIdentifier: string) { + const platformData = this.$platformsData.getPlatformData(this.$devicePlatformsConstants.Android, this.data); + const projectFilesPath = path.join(platformData.appDestinationDirectoryPath, APP_FOLDER_NAME); + if (!this.livesyncTool.hasConnection()) { + await this.livesyncTool.connect({ + appIdentifier, + deviceIdentifier: this.device.deviceInfo.identifier, + appPlatformsPath: projectFilesPath + }); + } } public getDeviceHashService(appIdentifier: string): Mobile.IAndroidDeviceHashService { diff --git a/lib/services/livesync/android-livesync-tool.ts b/lib/services/livesync/android-livesync-tool.ts index 0f319faacb..9ef6cdeb3d 100644 --- a/lib/services/livesync/android-livesync-tool.ts +++ b/lib/services/livesync/android-livesync-tool.ts @@ -20,6 +20,7 @@ const TRY_CONNECT_TIMEOUT = 30000; const DEFAULT_LOCAL_HOST_ADDRESS = "127.0.0.1"; export class AndroidLivesyncTool implements IAndroidLivesyncTool { + public protocolVersion: string; private operationPromises: IDictionary; private socketError: string | Error; private socketConnection: INetSocket; @@ -179,6 +180,10 @@ export class AndroidLivesyncTool implements IAndroidLivesyncTool { } } + public hasConnection(): boolean { + return !!this.socketConnection; + } + private sendFileHeader(filePath: string): Promise { return new Promise((resolve, reject) => { let error; @@ -292,6 +297,7 @@ export class AndroidLivesyncTool implements IAndroidLivesyncTool { const protocolVersion = versionBuffer.toString(); const appIdentifier = appIdentifierBuffer.toString(); this.$logger.trace(`Handle socket connection for app identifier: ${appIdentifier} with protocol version: ${protocolVersion}.`); + this.protocolVersion = protocolVersion; this.socketConnection.on("data", (connectionData: NodeBuffer) => this.handleData(socket.uid, connectionData)); this.socketConnection.on("close", (hasError: boolean) => this.handleSocketClose(socket.uid, hasError));