gethue
Version:
Hue is an Open source SQL Query Editor for Databases/Warehouses
167 lines (145 loc) • 5.03 kB
JavaScript
// Licensed to Cloudera, Inc. under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. Cloudera, Inc. licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import * as ko from 'knockout';
import 'ko/components/ko.catalogEntriesList';
import componentUtils from './componentUtils';
import dataCatalog from '../../catalog/dataCatalog';
export const NAME = 'polling-catalog-entries-list';
const TEMPLATE = `
<div>
<!-- ko hueSpinner: { spin: !catalogEntryExists(), inline: true } --><!-- /ko -->
<!-- ko if: catalogEntryExists -->
<!-- ko component: { name: 'catalog-entries-list', params: {
catalogEntry: catalogEntry,
selectedEntries: selectedEntries,
editableDescriptions: editableDescriptions,
contextPopoverEnabled: contextPopoverEnabled,
onSampleClick: onSampleClick,
refreshSampleInterval: refreshSampleInterval
}} --><!-- /ko -->
<!-- /ko -->
</div>
`;
class PollingCatalogEntriesList {
/**
* This is the same as the 'catalog-entries-list' component with the difference that this
* one waits until a catalog entry exists.
*
* Example usage:
*
* <div data-bind="component: { name: 'polling-catalog-entries-list', params: {
* sourceType: sourceType,
* namespace: ko.observable({ id: 'default' }),
* compute: ko.observable({ id: 'default' }),
* path: ko.observable('default.foo'),
* refreshSampleInterval: 3000
* }}"></div>
*
* @param params
* @constructor
*/
constructor(params) {
const self = this;
self.selectedEntries = params.selectedEntries;
self.editableDescriptions = params.editableDescriptions;
self.contextPopoverEnabled = params.contextPopoverEnabled;
self.onSampleClick = params.onSampleClick;
self.sourceType = params.sourceType;
self.namespace = params.namespace;
self.compute = params.compute;
self.path = params.path;
self.refreshSampleInterval = params.refreshSampleInterval;
self.pollTimeout = -1;
self.pollCount = 0;
self.disposals = [];
self.lastPollSourceMetaPromise = undefined;
self.catalogEntryExists = ko.observable(false);
self.catalogEntry = ko.observable();
self.intialize();
if (ko.isObservable(self.path)) {
const pathSub = self.path.subscribe(newValue => {
if (newValue) {
self.intialize();
}
});
self.disposals.push(() => {
pathSub.dispose();
});
}
}
pollForSourceMeta() {
const self = this;
window.clearTimeout(self.pollTimeout);
const pollInternal = function () {
self.pollCount++;
if (self.catalogEntry()) {
self.lastPollSourceMetaPromise = self
.catalogEntry()
.getSourceMeta({
silenceErrors: true,
refreshCache: self.pollCount > 0,
cancellable: true
})
.then(sourceMeta => {
if (sourceMeta.notFound) {
self.pollForSourceMeta();
} else {
self.catalogEntryExists(true);
}
})
.catch(() => {
self.pollForSourceMeta();
});
}
};
if (self.pollCount === 0) {
pollInternal();
} else {
self.pollTimeout = window.setTimeout(pollInternal, Math.min(1000 * self.pollCount, 3000));
}
}
intialize() {
const self = this;
self.pollCount = 0;
window.clearTimeout(self.pollTimeout);
self.catalogEntryExists(false);
if (self.lastPollSourceMetaPromise && self.lastPollSourceMetaPromise.cancel) {
self.lastPollSourceMetaPromise.cancel();
}
dataCatalog
.getEntry({
namespace: ko.unwrap(self.namespace),
compute: ko.unwrap(self.compute),
connector: { id: ko.unwrap(self.sourceType) }, // TODO: Use connectors in polling catalog entries list
path: ko.unwrap(self.path)
})
.then(catalogEntry => {
self.catalogEntry(catalogEntry);
self.pollForSourceMeta();
});
}
dispose() {
const self = this;
window.clearTimeout(self.pollTimeout);
if (self.lastPollSourceMetaPromise && self.lastPollSourceMetaPromise.cancel) {
self.lastPollSourceMetaPromise.cancel();
}
while (self.disposals.length) {
self.disposals.pop()();
}
}
}
componentUtils.registerComponent(NAME, PollingCatalogEntriesList, TEMPLATE);