Support empty offers for serverless accounts (#132)

* Add support for no offers when serverless accounts

* Add workaround for ignoring failed /offers when using connection string

* Revert @azure/cosmos upgrade
This commit is contained in:
Tanuj Mittal 2020-08-14 17:45:13 -07:00 committed by GitHub
parent 2752d6af00
commit 22b2e1df48
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 50 additions and 41 deletions

View File

@ -454,6 +454,10 @@ export function readCollectionQuotaInfo(
} }
export function readOffers(options: any): Q.Promise<DataModels.Offer[]> { export function readOffers(options: any): Q.Promise<DataModels.Offer[]> {
if (options.isServerless) {
return Q([]); // Reading offers is not supported for serverless accounts
}
try { try {
if (configContext.platform === Platform.Portal) { if (configContext.platform === Platform.Portal) {
return sendCachedDataMessage<DataModels.Offer[]>(MessageTypes.AllOffers, [ return sendCachedDataMessage<DataModels.Offer[]>(MessageTypes.AllOffers, [
@ -469,6 +473,13 @@ export function readOffers(options: any): Q.Promise<DataModels.Offer[]> {
.offers.readAll() .offers.readAll()
.fetchAll() .fetchAll()
.then(response => response.resources) .then(response => response.resources)
.catch(error => {
// This should be removed when we can correctly identify if an account is serverless when connected using connection string too.
if (error.message.includes("Reading or replacing offers is not supported for serverless accounts")) {
return [];
}
throw error;
})
); );
} }

View File

@ -1475,38 +1475,33 @@ export default class Explorer {
); );
}; };
if (this.isServerlessEnabled()) { const offerPromise: Q.Promise<DataModels.Offer[]> = readOffers({ isServerless: this.isServerlessEnabled() });
// Serverless accounts don't support offers call this._setLoadingStatusText("Fetching offers...");
refreshDatabases(); offerPromise.then(
} else { (offers: DataModels.Offer[]) => {
const offerPromise: Q.Promise<DataModels.Offer[]> = readOffers(); this._setLoadingStatusText("Successfully fetched offers.");
this._setLoadingStatusText("Fetching offers..."); refreshDatabases(offers);
offerPromise.then( },
(offers: DataModels.Offer[]) => { error => {
this._setLoadingStatusText("Successfully fetched offers."); this._setLoadingStatusText("Failed to fetch offers.");
refreshDatabases(offers); this.isRefreshingExplorer(false);
}, deferred.reject(error);
error => { TelemetryProcessor.traceFailure(
this._setLoadingStatusText("Failed to fetch offers."); Action.LoadDatabases,
this.isRefreshingExplorer(false); {
deferred.reject(error); databaseAccountName: this.databaseAccount().name,
TelemetryProcessor.traceFailure( defaultExperience: this.defaultExperience(),
Action.LoadDatabases, dataExplorerArea: Constants.Areas.ResourceTree,
{ error: JSON.stringify(error)
databaseAccountName: this.databaseAccount().name, },
defaultExperience: this.defaultExperience(), startKey
dataExplorerArea: Constants.Areas.ResourceTree, );
error: JSON.stringify(error) NotificationConsoleUtils.logConsoleMessage(
}, ConsoleDataType.Error,
startKey `Error while refreshing databases: ${JSON.stringify(error)}`
); );
NotificationConsoleUtils.logConsoleMessage( }
ConsoleDataType.Error, );
`Error while refreshing databases: ${JSON.stringify(error)}`
);
}
);
}
return deferred.promise.then( return deferred.promise.then(
() => { () => {

View File

@ -648,7 +648,9 @@ export default class Collection implements ViewModels.Collection {
}); });
// TODO: Use the collection entity cache to get quota info // TODO: Use the collection entity cache to get quota info
const quotaInfoPromise: Q.Promise<DataModels.CollectionQuotaInfo> = readCollectionQuotaInfo(this); const quotaInfoPromise: Q.Promise<DataModels.CollectionQuotaInfo> = readCollectionQuotaInfo(this);
const offerInfoPromise: Q.Promise<DataModels.Offer[]> = readOffers(); const offerInfoPromise: Q.Promise<DataModels.Offer[]> = readOffers({
isServerless: this.container.isServerlessEnabled()
});
Q.all([quotaInfoPromise, offerInfoPromise]).then( Q.all([quotaInfoPromise, offerInfoPromise]).then(
() => { () => {
this.container.isRefreshingExplorer(false); this.container.isRefreshingExplorer(false);
@ -657,9 +659,7 @@ export default class Collection implements ViewModels.Collection {
const quotaInfo = _.omit(quotaInfoWithUniqueKeyPolicy, "uniqueKeyPolicy"); const quotaInfo = _.omit(quotaInfoWithUniqueKeyPolicy, "uniqueKeyPolicy");
const collectionOffer = this._getOfferForCollection(offerInfoPromise.valueOf(), collectionDataModel); const collectionOffer = this._getOfferForCollection(offerInfoPromise.valueOf(), collectionDataModel);
const isDatabaseShared = this.getDatabase() && this.getDatabase().isDatabaseShared(); if (!collectionOffer) {
const isServerless = this.container.isServerlessEnabled();
if ((isDatabaseShared || isServerless) && !collectionOffer) {
this.quotaInfo(quotaInfo); this.quotaInfo(quotaInfo);
TelemetryProcessor.traceSuccess( TelemetryProcessor.traceSuccess(
Action.LoadOffers, Action.LoadOffers,

View File

@ -123,10 +123,6 @@ export default class Database implements ViewModels.Database {
public readSettings(): Q.Promise<void> { public readSettings(): Q.Promise<void> {
const deferred: Q.Deferred<void> = Q.defer<void>(); const deferred: Q.Deferred<void> = Q.defer<void>();
if (this.container.isServerlessEnabled()) {
deferred.resolve();
}
this.container.isRefreshingExplorer(true); this.container.isRefreshingExplorer(true);
const databaseDataModel: DataModels.Database = <DataModels.Database>{ const databaseDataModel: DataModels.Database = <DataModels.Database>{
id: this.id(), id: this.id(),
@ -138,7 +134,9 @@ export default class Database implements ViewModels.Database {
defaultExperience: this.container.defaultExperience() defaultExperience: this.container.defaultExperience()
}); });
const offerInfoPromise: Q.Promise<DataModels.Offer[]> = readOffers(); const offerInfoPromise: Q.Promise<DataModels.Offer[]> = readOffers({
isServerless: this.container.isServerlessEnabled()
});
Q.all([offerInfoPromise]).then( Q.all([offerInfoPromise]).then(
() => { () => {
this.container.isRefreshingExplorer(false); this.container.isRefreshingExplorer(false);
@ -147,6 +145,11 @@ export default class Database implements ViewModels.Database {
offerInfoPromise.valueOf(), offerInfoPromise.valueOf(),
databaseDataModel databaseDataModel
); );
if (!databaseOffer) {
return;
}
readOffer(databaseOffer).then((offerDetail: DataModels.OfferWithHeaders) => { readOffer(databaseOffer).then((offerDetail: DataModels.OfferWithHeaders) => {
const offerThroughputInfo: DataModels.OfferThroughputInfo = { const offerThroughputInfo: DataModels.OfferThroughputInfo = {
minimumRUForCollection: minimumRUForCollection: