Skip to content

Commit 33a66fc

Browse files
committed
fix: extension manager not showing updated extensions due to local storage out of space
1 parent 9477596 commit 33a66fc

File tree

2 files changed

+90
-48
lines changed

2 files changed

+90
-48
lines changed

src/extensibility/ExtensionManager.js

Lines changed: 88 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
*/
2121

2222
/*jslint regexp: true */
23-
/*global Phoenix*/
23+
/*global path, logger*/
2424
/*unittests: ExtensionManager*/
2525

2626
/**
@@ -44,6 +44,7 @@ define(function (require, exports, module) {
4444
ExtensionLoader = require("utils/ExtensionLoader"),
4545
ExtensionUtils = require("utils/ExtensionUtils"),
4646
FileSystem = require("filesystem/FileSystem"),
47+
FileUtils = require("file/FileUtils"),
4748
PreferencesManager = require("preferences/PreferencesManager"),
4849
Strings = require("strings"),
4950
StringUtils = require("utils/StringUtils"),
@@ -54,6 +55,40 @@ define(function (require, exports, module) {
5455
"test_extension_registry" : "extension_registry",
5556
EXTENSION_REGISTRY_LOCAL_STORAGE_VERSION_KEY = Phoenix.isTestWindow ?
5657
"test_extension_registry_version" : "extension_registry_version";
58+
59+
// earlier, we used to cache the full uncompressed registry in ls which has a usual size limit of 5mb, and the
60+
// registry takes a few MB. So we moved this storage and this will clear local storage on any existing installs on
61+
// next update. This migration code can be removed after July 2025(6 Months).
62+
localStorage.removeItem(EXTENSION_REGISTRY_LOCAL_STORAGE_KEY);
63+
64+
const REGISTRY_CACHE_PATH = path.normalize(
65+
Phoenix.app.getExtensionsDirectory() + "/" + "registry_cache.json");
66+
function _getCachedRegistry() {
67+
// never rejects
68+
return new Promise((resolve) => {
69+
const registryFile = FileSystem.getFileForPath(REGISTRY_CACHE_PATH);
70+
FileUtils.readAsText(registryFile)
71+
.done(resolve)
72+
.fail(function (err) {
73+
console.error(`Registry cache not found ${REGISTRY_CACHE_PATH}`, err);
74+
resolve(null);
75+
});
76+
});
77+
}
78+
79+
function _putCachedRegistry(registryFileText) {
80+
// never rejects
81+
return new Promise((resolve) => {
82+
const registryFile = FileSystem.getFileForPath(REGISTRY_CACHE_PATH);
83+
FileUtils.writeText(registryFile, registryFileText)
84+
.done(resolve)
85+
.fail(function (err) {
86+
logger.reportError(err, `Registry cache write error ${REGISTRY_CACHE_PATH}`);
87+
resolve();
88+
});
89+
});
90+
}
91+
5792
// semver.browser is an AMD-compatible module
5893
var semver = require("thirdparty/semver.browser");
5994

@@ -223,38 +258,42 @@ define(function (require, exports, module) {
223258
if(registryVersion.version !== parseInt(currentRegistryVersion)){
224259
resolve(registryVersion.version);
225260
} else {
226-
const registryJson = localStorage.getItem(EXTENSION_REGISTRY_LOCAL_STORAGE_KEY);
227-
if(!registryJson) {
228-
resolve(registryVersion.version);
229-
// if we dont have anything, best to atlest try to fetch the registry now.
230-
return;
231-
}
232-
reject();
261+
_getCachedRegistry() // never rejects
262+
.then(registryJson => {
263+
if(!registryJson) {
264+
resolve(registryVersion.version);
265+
// if we dont have anything, best to atlest try to fetch the registry now.
266+
return;
267+
}
268+
reject();
269+
});
233270
}
234271
})
235272
.fail(function (err) {
236273
console.error("error Fetching Extension Registry version", err);
237-
const registryJson = localStorage.getItem(EXTENSION_REGISTRY_LOCAL_STORAGE_KEY);
238-
if(!registryJson) {
239-
resolve(1); // if we dont have anything, best to atlest try to fetch the registry now.
240-
return;
241-
}
242-
reject();
274+
_getCachedRegistry() // never rejects
275+
.then(registryJson => {
276+
if(!registryJson) {
277+
resolve(1); // if we dont have anything, best to atlest try to fetch the registry now.
278+
return;
279+
}
280+
reject();
281+
});
243282
});
244283
});
245284
}
246285

247-
function _patchDownloadCounts() {
248-
let registryJson = localStorage.getItem(EXTENSION_REGISTRY_LOCAL_STORAGE_KEY);
286+
async function _patchDownloadCounts() {
287+
let registryJson = await _getCachedRegistry();
249288
if(!registryJson){
250289
return;
251290
}
252291
$.ajax({
253292
url: brackets.config.extension_registry_popularity,
254293
dataType: "json",
255294
cache: false
256-
}).done(function (popularity) {
257-
registryJson = localStorage.getItem(EXTENSION_REGISTRY_LOCAL_STORAGE_KEY);
295+
}).done(async function (popularity) {
296+
registryJson = await _getCachedRegistry();
258297
let registry = JSON.parse(registryJson);
259298
for(let key of Object.keys(popularity)){
260299
if(registry[key]) {
@@ -264,7 +303,7 @@ define(function (require, exports, module) {
264303
|| null;
265304
}
266305
}
267-
localStorage.setItem(EXTENSION_REGISTRY_LOCAL_STORAGE_KEY, JSON.stringify(registry));
306+
_putCachedRegistry(JSON.stringify(registry));
268307
});
269308
}
270309

@@ -308,6 +347,7 @@ define(function (require, exports, module) {
308347
pendingDownloadRegistry = new $.Deferred();
309348

310349
function _updateRegistry(newVersion) {
350+
console.log("downloading extension registry: ", newVersion, brackets.config.extension_registry);
311351
$.ajax({
312352
url: brackets.config.extension_registry,
313353
dataType: "json",
@@ -316,20 +356,20 @@ define(function (require, exports, module) {
316356
.done(function (registry) {
317357
registry = _filterIncompatibleEntries(registry);
318358
localStorage.setItem(EXTENSION_REGISTRY_LOCAL_STORAGE_VERSION_KEY, newVersion);
319-
localStorage.setItem(EXTENSION_REGISTRY_LOCAL_STORAGE_KEY, JSON.stringify(registry));
320-
if(!pendingDownloadRegistry.alreadyResolvedFromCache){
321-
_populateExtensions(registry);
322-
pendingDownloadRegistry.resolve();
323-
}
359+
_putCachedRegistry(JSON.stringify(registry)).then(()=>{
360+
if(!pendingDownloadRegistry.alreadyResolvedFromCache){
361+
_populateExtensions(registry);
362+
pendingDownloadRegistry.resolve();
363+
}
364+
}).finally(()=>{
365+
pendingDownloadRegistry = null;
366+
});
324367
})
325368
.fail(function (err) {
326369
console.error("error Fetching Extension Registry", err);
327370
if(!pendingDownloadRegistry.alreadyResolvedFromCache){
328371
pendingDownloadRegistry.reject();
329372
}
330-
})
331-
.always(function () {
332-
// Make sure to clean up the pending registry so that new requests can be made.
333373
pendingDownloadRegistry = null;
334374
});
335375
}
@@ -339,26 +379,28 @@ define(function (require, exports, module) {
339379
return pendingDownloadRegistry.promise();
340380
}
341381

342-
const registryJson = localStorage.getItem(EXTENSION_REGISTRY_LOCAL_STORAGE_KEY);
343-
if(registryJson) {
344-
// we always immediately but after the promise chain is setup after function return (some bug sigh)
345-
// resolve for ui responsiveness and then check for updates.
346-
setTimeout(()=>{
347-
Metrics.countEvent(Metrics.EVENT_TYPE.EXTENSIONS, "registry", "cachedUse");
348-
let registry = JSON.parse(registryJson);
349-
registry = _filterIncompatibleEntries(registry);
350-
_populateExtensions(registry);
351-
pendingDownloadRegistry.resolve();
352-
}, 0);
353-
pendingDownloadRegistry.alreadyResolvedFromCache = true;
354-
}
355-
// check for latest updates even if we have cache
356-
_shouldUpdateExtensionRegistry()
357-
.then(_updateRegistry)
358-
.catch(()=>{
359-
pendingDownloadRegistry = null;
382+
_getCachedRegistry() // never rejects
383+
.then(registryJson => {
384+
if(registryJson) {
385+
// we always immediately but after the promise chain is setup after function return (some bug sigh)
386+
// resolve for ui responsiveness and then check for updates.
387+
setTimeout(()=>{
388+
Metrics.countEvent(Metrics.EVENT_TYPE.EXTENSIONS, "registry", "cachedUse");
389+
let registry = JSON.parse(registryJson);
390+
registry = _filterIncompatibleEntries(registry);
391+
_populateExtensions(registry);
392+
pendingDownloadRegistry.resolve();
393+
}, 0);
394+
pendingDownloadRegistry.alreadyResolvedFromCache = true;
395+
}
396+
// check for latest updates even if we have cache
397+
_shouldUpdateExtensionRegistry()
398+
.then(_updateRegistry)
399+
.catch(()=>{
400+
console.log("Registry update skipped");
401+
});
402+
_patchDownloadCounts();
360403
});
361-
_patchDownloadCounts();
362404

363405
return pendingDownloadRegistry.promise();
364406
}

src/loggerSetup.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@
7272
},
7373
/**
7474
* By default all uncaught exceptions and promise rejections are sent to logger utility. But in some cases
75-
* you may want to sent handled errors too if it is critical. use this function to report those
76-
* @param {Error} error
75+
* you may want to log error without having an error object with you.
76+
*
7777
* @param {string} [message] optional message
7878
*/
7979
reportErrorMessage: function (message) {

0 commit comments

Comments
 (0)