Merge pull request #3444 from w33ble/pattern-selection
Pattern selection race conditions
This commit is contained in:
commit
0148f8f934
|
@ -12,11 +12,12 @@ define(function (require) {
|
|||
});
|
||||
|
||||
require('modules').get('apps/settings')
|
||||
.controller('settingsIndicesCreate', function ($scope, kbnUrl, Private, Notifier, indexPatterns, es, config) {
|
||||
.controller('settingsIndicesCreate', function ($scope, kbnUrl, Private, Notifier, indexPatterns, es, config, Promise) {
|
||||
var notify = new Notifier();
|
||||
var MissingIndices = errors.IndexPatternMissingIndices;
|
||||
var refreshKibanaIndex = Private(require('plugins/settings/sections/indices/_refresh_kibana_index'));
|
||||
var intervals = indexPatterns.intervals;
|
||||
var samplePromise;
|
||||
|
||||
// this and child scopes will write pattern vars here
|
||||
var index = $scope.index = {
|
||||
|
@ -33,83 +34,8 @@ define(function (require) {
|
|||
index.nameInterval = _.find(index.nameIntervalOptions, { name: 'daily' });
|
||||
index.timeField = null;
|
||||
|
||||
var updateSamples = function () {
|
||||
index.samples = null;
|
||||
index.existing = null;
|
||||
index.patternErrors = [];
|
||||
|
||||
if (!index.nameInterval || !index.name) {
|
||||
return;
|
||||
}
|
||||
|
||||
var pattern = mockIndexPattern(index);
|
||||
|
||||
indexPatterns.mapper.getIndicesForIndexPattern(pattern)
|
||||
.then(function (existing) {
|
||||
var all = existing.all;
|
||||
var matches = existing.matches;
|
||||
if (all.length) {
|
||||
index.existing = {
|
||||
class: 'success',
|
||||
all: all,
|
||||
matches: matches,
|
||||
matchPercent: Math.round((matches.length / all.length) * 100) + '%',
|
||||
failures: _.difference(all, matches)
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
index.patternErrors.push('Pattern does not match any existing indices');
|
||||
var radius = Math.round(index.sampleCount / 2);
|
||||
var samples = intervals.toIndexList(index.name, index.nameInterval, -radius, radius);
|
||||
|
||||
if (_.uniq(samples).length !== samples.length) {
|
||||
index.patternErrors.push('Invalid pattern, interval does not create unique index names');
|
||||
} else {
|
||||
index.samples = samples;
|
||||
}
|
||||
})
|
||||
.catch(notify.error);
|
||||
};
|
||||
|
||||
$scope.refreshFieldList = function () {
|
||||
index.dateFields = index.timeField = index.listUsed = null;
|
||||
var useIndexList = index.isTimeBased && index.nameIsPattern;
|
||||
|
||||
// we don't have enough info to continue
|
||||
if (!index.name) {
|
||||
index.fetchFieldsError = 'Set an index name first';
|
||||
return;
|
||||
}
|
||||
|
||||
if (useIndexList && !index.nameInterval) {
|
||||
index.fetchFieldsError = 'Select the interval at which your indices are populated.';
|
||||
return;
|
||||
}
|
||||
|
||||
return indexPatterns.mapper.clearCache(index.name)
|
||||
.then(function () {
|
||||
var pattern = mockIndexPattern(index);
|
||||
|
||||
return indexPatterns.mapper.getFieldsForIndexPattern(pattern, true)
|
||||
.catch(function (err) {
|
||||
// TODO: we should probably display a message of some kind
|
||||
if (err instanceof MissingIndices) {
|
||||
index.fetchFieldsError = 'Unable to fetch mapping. Do you have indices matching the pattern?';
|
||||
return [];
|
||||
}
|
||||
|
||||
throw err;
|
||||
});
|
||||
})
|
||||
.then(function (fields) {
|
||||
if (fields.length > 0) {
|
||||
index.fetchFieldsError = null;
|
||||
index.dateFields = fields.filter(function (field) {
|
||||
return field.type === 'date';
|
||||
});
|
||||
}
|
||||
}, notify.fatal);
|
||||
fetchFieldList().then(updateFieldList);
|
||||
};
|
||||
|
||||
$scope.createIndexPattern = function () {
|
||||
|
@ -156,24 +82,6 @@ define(function (require) {
|
|||
'index.nameIsPattern',
|
||||
'index.nameInterval.name'
|
||||
], function (newVal, oldVal) {
|
||||
|
||||
function getPatternDefault(interval) {
|
||||
switch (interval) {
|
||||
case 'hours':
|
||||
return '[logstash-]YYYY.MM.DD.HH';
|
||||
case 'days':
|
||||
return '[logstash-]YYYY.MM.DD';
|
||||
case 'weeks':
|
||||
return '[logstash-]GGGG.WW';
|
||||
case 'months':
|
||||
return '[logstash-]YYYY.MM';
|
||||
case 'years':
|
||||
return '[logstash-]YYYY';
|
||||
default:
|
||||
return 'logstash-*';
|
||||
}
|
||||
}
|
||||
|
||||
var isTimeBased = newVal[0];
|
||||
var nameIsPattern = newVal[1];
|
||||
var newDefault = getPatternDefault(newVal[2]);
|
||||
|
@ -194,17 +102,8 @@ define(function (require) {
|
|||
index.nameInterval = index.nameInterval || intervals.byName['days'];
|
||||
index.name = index.name || getPatternDefault(index.nameInterval);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
var mockIndexPattern = function (index) {
|
||||
// trick the mapper into thinking this is an indexPattern
|
||||
return {
|
||||
id: index.name,
|
||||
intervalName: index.nameInterval
|
||||
};
|
||||
};
|
||||
|
||||
$scope.moreSamples = function (andUpdate) {
|
||||
index.sampleCount += 5;
|
||||
if (andUpdate) updateSamples();
|
||||
|
@ -213,13 +112,164 @@ define(function (require) {
|
|||
$scope.$watchMulti([
|
||||
'index.name',
|
||||
'index.nameInterval'
|
||||
], updateSamples);
|
||||
], function (newVal, oldVal) {
|
||||
var lastPromise;
|
||||
samplePromise = lastPromise = updateSamples()
|
||||
.then(function () {
|
||||
promiseMatch(lastPromise, function () {
|
||||
index.samples = null;
|
||||
index.patternErrors = [];
|
||||
});
|
||||
})
|
||||
.catch(function (errors) {
|
||||
promiseMatch(lastPromise, function () {
|
||||
index.existing = null;
|
||||
index.patternErrors = errors;
|
||||
});
|
||||
})
|
||||
.finally(function () {
|
||||
// prevent running when no change happened (ie, first watcher call)
|
||||
if (!_.isEqual(newVal, oldVal)) {
|
||||
fetchFieldList().then(function (results) {
|
||||
if (lastPromise === samplePromise) {
|
||||
updateFieldList(results);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$scope.$watchMulti([
|
||||
'index.name',
|
||||
'index.isTimeBased',
|
||||
'index.nameInterval',
|
||||
'index.sampleCount'
|
||||
], $scope.refreshFieldList);
|
||||
|
||||
function updateSamples() {
|
||||
var patternErrors = [];
|
||||
|
||||
if (!index.nameInterval || !index.name) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
var pattern = mockIndexPattern(index);
|
||||
|
||||
return indexPatterns.mapper.getIndicesForIndexPattern(pattern)
|
||||
.catch(notify.error)
|
||||
.then(function (existing) {
|
||||
var all = existing.all;
|
||||
var matches = existing.matches;
|
||||
if (all.length) {
|
||||
index.existing = {
|
||||
class: 'success',
|
||||
all: all,
|
||||
matches: matches,
|
||||
matchPercent: Math.round((matches.length / all.length) * 100) + '%',
|
||||
failures: _.difference(all, matches)
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
patternErrors.push('Pattern does not match any existing indices');
|
||||
var radius = Math.round(index.sampleCount / 2);
|
||||
var samples = intervals.toIndexList(index.name, index.nameInterval, -radius, radius);
|
||||
|
||||
if (_.uniq(samples).length !== samples.length) {
|
||||
patternErrors.push('Invalid pattern, interval does not create unique index names');
|
||||
} else {
|
||||
index.samples = samples;
|
||||
}
|
||||
|
||||
throw patternErrors;
|
||||
});
|
||||
}
|
||||
|
||||
function fetchFieldList() {
|
||||
index.dateFields = index.timeField = index.listUsed = null;
|
||||
var useIndexList = index.isTimeBased && index.nameIsPattern;
|
||||
var fetchFieldsError;
|
||||
var dateFields;
|
||||
|
||||
// we don't have enough info to continue
|
||||
if (!index.name) {
|
||||
fetchFieldsError = 'Set an index name first';
|
||||
return;
|
||||
}
|
||||
|
||||
if (useIndexList && !index.nameInterval) {
|
||||
fetchFieldsError = 'Select the interval at which your indices are populated.';
|
||||
return;
|
||||
}
|
||||
|
||||
return indexPatterns.mapper.clearCache(index.name)
|
||||
.then(function () {
|
||||
var pattern = mockIndexPattern(index);
|
||||
|
||||
return indexPatterns.mapper.getFieldsForIndexPattern(pattern, true)
|
||||
.catch(function (err) {
|
||||
// TODO: we should probably display a message of some kind
|
||||
if (err instanceof MissingIndices) {
|
||||
fetchFieldsError = 'Unable to fetch mapping. Do you have indices matching the pattern?';
|
||||
return [];
|
||||
}
|
||||
|
||||
throw err;
|
||||
});
|
||||
})
|
||||
.then(function (fields) {
|
||||
if (fields.length > 0) {
|
||||
fetchFieldsError = null;
|
||||
dateFields = fields.filter(function (field) {
|
||||
return field.type === 'date';
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
fetchFieldsError: fetchFieldsError,
|
||||
dateFields: dateFields
|
||||
};
|
||||
}, notify.fatal);
|
||||
}
|
||||
|
||||
function updateFieldList(results) {
|
||||
index.fetchFieldsError = results.fetchFieldsError;
|
||||
index.dateFields = results.dateFields;
|
||||
}
|
||||
|
||||
function promiseMatch(lastPromise, cb) {
|
||||
if (lastPromise === samplePromise) {
|
||||
cb();
|
||||
} else if (samplePromise != null) {
|
||||
// haven't hit the last promise yet, reset index params
|
||||
index.patternErrors = [];
|
||||
index.samples = null;
|
||||
index.existing = null;
|
||||
index.fetchFieldsError = 'Loading';
|
||||
}
|
||||
}
|
||||
|
||||
function getPatternDefault(interval) {
|
||||
switch (interval) {
|
||||
case 'hours':
|
||||
return '[logstash-]YYYY.MM.DD.HH';
|
||||
case 'days':
|
||||
return '[logstash-]YYYY.MM.DD';
|
||||
case 'weeks':
|
||||
return '[logstash-]GGGG.WW';
|
||||
case 'months':
|
||||
return '[logstash-]YYYY.MM';
|
||||
case 'years':
|
||||
return '[logstash-]YYYY';
|
||||
default:
|
||||
return 'logstash-*';
|
||||
}
|
||||
}
|
||||
|
||||
function mockIndexPattern(index) {
|
||||
// trick the mapper into thinking this is an indexPattern
|
||||
return {
|
||||
id: index.name,
|
||||
intervalName: index.nameInterval
|
||||
};
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue