@capgo/capacitor-updater 8.51.10 → 8.51.12

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.
@@ -146,7 +146,7 @@ public class CapacitorUpdaterPlugin extends Plugin {
146
146
  static final int APPLICATION_EXIT_REASON_USER_REQUESTED = 10;
147
147
  static final int APPLICATION_EXIT_REASON_DEPENDENCY_DIED = 12;
148
148
 
149
- private final String pluginVersion = "8.51.10";
149
+ private final String pluginVersion = "8.51.12";
150
150
  private static final String DELAY_CONDITION_PREFERENCES = "";
151
151
 
152
152
  private SharedPreferences.Editor editor;
@@ -12,11 +12,9 @@ package ee.forgr.capacitor_updater;
12
12
  * references: http://stackoverflow.com/questions/12471999/rsa-encryption-decryption-in-android
13
13
  */
14
14
  import android.util.Base64;
15
- import java.io.BufferedReader;
16
15
  import java.io.File;
17
16
  import java.io.FileInputStream;
18
17
  import java.io.FileOutputStream;
19
- import java.io.FileReader;
20
18
  import java.io.IOException;
21
19
  import java.io.InputStream;
22
20
  import java.security.GeneralSecurityException;
@@ -174,8 +172,7 @@ public class CryptoCipher {
174
172
  File tempFile = File.createTempFile("capgo-aes-", ".tmp", file.getParentFile());
175
173
  try {
176
174
  byte[] inBuf = new byte[ioBufferBytes()];
177
- // Reuse one output buffer. cipher.update(in) allocates a new byte[] per chunk
178
- // and 64 workers * 5MB was why AES barely won on heap in local benches.
175
+ // Reuse one output buffer. cipher.update(in) allocates a new byte[] per chunk.
179
176
  byte[] outBuf = new byte[inBuf.length + 16];
180
177
  try (FileInputStream fis = new FileInputStream(file); FileOutputStream fos = new FileOutputStream(tempFile)) {
181
178
  int n;
@@ -330,73 +327,20 @@ public class CryptoCipher {
330
327
  }
331
328
  }
332
329
 
333
- private static final long TWO_GIB = 2L * 1024 * 1024 * 1024;
334
- private static final long THREE_GIB = 3L * 1024 * 1024 * 1024;
335
- private static final long FOUR_GIB = 4L * 1024 * 1024 * 1024;
336
- private static final long EIGHT_GIB = 8L * 1024 * 1024 * 1024;
337
- private static final int FLAGSHIP_IO_BUFFER_BYTES = 5 * 1024 * 1024;
338
- private static volatile long cachedPhysicalRamBytes = -1;
339
-
340
- // Checksum and copy share one ladder. 64-wide peak RAM = 64 * buffer.
341
- // <2GB: 64KB. <3GB: 256KB. <4GB: 512KB. <8GB: 1MB. Else 5MB (flagship / unknown).
342
- static int ioBufferBytes(long physicalRamBytes) {
343
- if (physicalRamBytes <= 0) {
344
- return FLAGSHIP_IO_BUFFER_BYTES;
345
- }
346
- if (physicalRamBytes < TWO_GIB) {
347
- return 64 * 1024;
348
- }
349
- if (physicalRamBytes < THREE_GIB) {
350
- return 256 * 1024;
351
- }
352
- if (physicalRamBytes < FOUR_GIB) {
353
- return 512 * 1024;
354
- }
355
- if (physicalRamBytes < EIGHT_GIB) {
356
- return 1024 * 1024;
357
- }
358
- return FLAGSHIP_IO_BUFFER_BYTES;
359
- }
360
-
361
- static int checksumBufferBytes(long physicalRamBytes) {
362
- return ioBufferBytes(physicalRamBytes);
363
- }
364
-
365
- static int copyBufferBytes(long physicalRamBytes) {
366
- return ioBufferBytes(physicalRamBytes);
367
- }
330
+ // 256 KiB: one size for checksum, copy, and decode.
331
+ // 64 workers * 256 KiB = 16 MiB for one buffer; AES/Brotli hold two (~32 MiB).
332
+ static final int IO_BUFFER_BYTES = 256 * 1024;
368
333
 
369
334
  static int ioBufferBytes() {
370
- return ioBufferBytes(physicalRamBytes());
335
+ return IO_BUFFER_BYTES;
371
336
  }
372
337
 
373
338
  static int checksumBufferBytes() {
374
- return ioBufferBytes(physicalRamBytes());
339
+ return IO_BUFFER_BYTES;
375
340
  }
376
341
 
377
342
  static int copyBufferBytes() {
378
- return ioBufferBytes(physicalRamBytes());
379
- }
380
-
381
- static long physicalRamBytes() {
382
- long cached = cachedPhysicalRamBytes;
383
- if (cached >= 0) {
384
- return cached;
385
- }
386
- long parsed = 0;
387
- try (BufferedReader reader = new BufferedReader(new FileReader("/proc/meminfo"))) {
388
- String line = reader.readLine();
389
- if (line != null && line.startsWith("MemTotal:")) {
390
- String[] parts = line.split("\\s+");
391
- if (parts.length >= 2) {
392
- parsed = Long.parseLong(parts[1]) * 1024L;
393
- }
394
- }
395
- } catch (Exception ignored) {
396
- parsed = 0;
397
- }
398
- cachedPhysicalRamBytes = parsed;
399
- return parsed;
343
+ return IO_BUFFER_BYTES;
400
344
  }
401
345
 
402
346
  public static String calcChecksum(File file) {
@@ -76,8 +76,8 @@ public class DownloadService extends Worker {
76
76
  public static final String DEFAULT_CHANNEL = "default_channel";
77
77
  public static final String IS_PROD = "is_prod";
78
78
  public static final String IS_EMULATOR = "is_emulator";
79
- // Match HTTP dispatcher so 64 workers actually fetch in parallel (HTTP/2 multiplexes).
80
- private static final int MANIFEST_MAX_CONCURRENT_FILES = 64;
79
+ // HTTP + decode share one pool. Cap by CPU: 8 on 4 cores, 16 on 8 cores, 64 max.
80
+ private static final int MANIFEST_MAX_CONCURRENT_FILES = manifestMaxConcurrentFiles();
81
81
  private static final String UPDATE_FILE = "update.dat";
82
82
 
83
83
  // Shared OkHttpClient to prevent resource leaks
@@ -103,6 +103,15 @@ public class DownloadService extends Worker {
103
103
  .build();
104
104
  }
105
105
 
106
+ static int manifestMaxConcurrentFiles() {
107
+ return manifestMaxConcurrentFiles(Runtime.getRuntime().availableProcessors());
108
+ }
109
+
110
+ static int manifestMaxConcurrentFiles(int processors) {
111
+ int cores = Math.max(1, processors);
112
+ return Math.min(64, Math.max(8, cores * 2));
113
+ }
114
+
106
115
  static String buildUserAgent(String appId, String pluginVersion, String versionOs) {
107
116
  return (
108
117
  "CapacitorUpdater/" +
@@ -1038,14 +1047,14 @@ public class DownloadService extends Worker {
1038
1047
  }
1039
1048
 
1040
1049
  /**
1041
- * Atomically write a stream to a file using the RAM-ladder IO buffer.
1050
+ * Atomically write a stream to a file using the 256 KiB IO buffer.
1042
1051
  */
1043
1052
  static void writeFileAtomic(File targetFile, InputStream inputStream, String expectedChecksum) throws IOException {
1044
1053
  File tempFile = File.createTempFile("capgo-", ".tmp", targetFile.getParentFile());
1045
1054
 
1046
1055
  try {
1047
- // Okio's default segment is 8KB. Copy with the RAM-ladder buffer so
1048
- // 8MB wrapper unwraps are not 1000 tiny writes.
1056
+ // Okio's default segment is 8 KiB. Copy with 256 KiB so 8 MiB wrapper unwraps
1057
+ // are not 1000 tiny writes.
1049
1058
  byte[] buffer = new byte[CryptoCipher.ioBufferBytes()];
1050
1059
  try (FileOutputStream fos = new FileOutputStream(tempFile)) {
1051
1060
  int n;
@@ -96,7 +96,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
96
96
  deinit {
97
97
  implementation.shutdown()
98
98
  }
99
- private let pluginVersion: String = "8.51.10"
99
+ private let pluginVersion: String = "8.51.12"
100
100
  private let launchStartedAtMs = Int64(Date().timeIntervalSince1970 * 1000)
101
101
  static let updateUrlDefault = "https://plugin.capgo.app/updates"
102
102
  static let statsUrlDefault = "https://plugin.capgo.app/stats"
@@ -25,8 +25,12 @@ import UIKit
25
25
  private let PENDING_DELETE_IDS: String = "pendingDeleteIds"
26
26
  private var unzipPercent = 0
27
27
  private let TEMP_UNZIP_PREFIX: String = "capgo_unzip_"
28
- /// Match URLSession per-host limit so 64 workers actually fetch in parallel.
29
- private static let manifestMaxConcurrentFiles = 64
28
+ /// HTTP + decode share one pool. Cap by CPU: 8 on 4 cores, 16 on 8 cores, 64 max.
29
+ static let manifestMaxConcurrentFiles = clampedManifestConcurrency(processorCount: ProcessInfo.processInfo.processorCount)
30
+
31
+ static func clampedManifestConcurrency(processorCount: Int) -> Int {
32
+ min(64, max(8, max(1, processorCount) * 2))
33
+ }
30
34
  private static let emptySha256 = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
31
35
  private let deletePaceSeconds: TimeInterval = 0.075
32
36
  private let deleteLock = NSLock()
@@ -141,39 +141,20 @@ public struct CryptoCipher {
141
141
  }
142
142
  }
143
143
 
144
- private static let twoGiB: UInt64 = 2 * 1024 * 1024 * 1024
145
- private static let threeGiB: UInt64 = 3 * 1024 * 1024 * 1024
146
- private static let fourGiB: UInt64 = 4 * 1024 * 1024 * 1024
147
- private static let eightGiB: UInt64 = 8 * 1024 * 1024 * 1024
148
- private static let flagshipIoBufferBytes = 5 * 1024 * 1024
149
-
150
- /// Checksum and copy share one ladder. 64-wide peak RAM = 64 * buffer.
151
- /// <2GB: 64KB. <3GB: 256KB. <4GB: 512KB. <8GB: 1MB. Else 5MB (flagship / unknown).
152
- static func ioBufferBytes(_ physicalRamBytes: UInt64 = ProcessInfo.processInfo.physicalMemory) -> Int {
153
- if physicalRamBytes == 0 {
154
- return flagshipIoBufferBytes
155
- }
156
- if physicalRamBytes < twoGiB {
157
- return 64 * 1024
158
- }
159
- if physicalRamBytes < threeGiB {
160
- return 256 * 1024
161
- }
162
- if physicalRamBytes < fourGiB {
163
- return 512 * 1024
164
- }
165
- if physicalRamBytes < eightGiB {
166
- return 1024 * 1024
167
- }
168
- return flagshipIoBufferBytes
144
+ /// 256 KiB: one size for checksum, copy, and decode.
145
+ /// 64 workers * 256 KiB = 16 MiB for one buffer; AES/Brotli hold two (~32 MiB).
146
+ static let ioBufferBytesValue = 256 * 1024
147
+
148
+ static func ioBufferBytes() -> Int {
149
+ return ioBufferBytesValue
169
150
  }
170
151
 
171
- static func checksumBufferBytes(_ physicalRamBytes: UInt64 = ProcessInfo.processInfo.physicalMemory) -> Int {
172
- return ioBufferBytes(physicalRamBytes)
152
+ static func checksumBufferBytes() -> Int {
153
+ return ioBufferBytesValue
173
154
  }
174
155
 
175
- static func copyBufferBytes(_ physicalRamBytes: UInt64 = ProcessInfo.processInfo.physicalMemory) -> Int {
176
- return ioBufferBytes(physicalRamBytes)
156
+ static func copyBufferBytes() -> Int {
157
+ return ioBufferBytesValue
177
158
  }
178
159
 
179
160
  public static func calcChecksum(filePath: URL) -> String {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capgo/capacitor-updater",
3
- "version": "8.51.10",
3
+ "version": "8.51.12",
4
4
  "license": "MPL-2.0",
5
5
  "description": "Live update for capacitor apps",
6
6
  "main": "dist/plugin.cjs.js",