Return cached data source schema when available (#4934)

This commit is contained in:
Gabriel Dutra 2020-06-02 05:26:53 -03:00 committed by GitHub
parent 733bc1c109
commit 100c7be5e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 38 additions and 25 deletions

View File

@ -1,11 +1,11 @@
import { reduce } from "lodash"; import { reduce, has } from "lodash";
import { useCallback, useEffect, useRef, useState, useMemo } from "react"; import { useCallback, useEffect, useRef, useState, useMemo } from "react";
import { axios } from "@/services/axios"; import { axios } from "@/services/axios";
import DataSource, { SCHEMA_NOT_SUPPORTED } from "@/services/data-source"; import DataSource, { SCHEMA_NOT_SUPPORTED } from "@/services/data-source";
import notification from "@/services/notification"; import notification from "@/services/notification";
function sleep(ms) { function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms)); return new Promise(resolve => setTimeout(resolve, ms));
} }
function getSchema(dataSource, refresh = undefined) { function getSchema(dataSource, refresh = undefined) {
@ -13,24 +13,27 @@ function getSchema(dataSource, refresh = undefined) {
return Promise.resolve([]); return Promise.resolve([]);
} }
const fetchSchemaFromJob = (data) => { const fetchSchemaFromJob = data => {
return sleep(1000).then(() => { return axios.get(`api/jobs/${data.job.id}`).then(data => {
return axios.get(`api/jobs/${data.job.id}`).then((data) => { if (data.job.status < 3) {
if (data.job.status < 3) { return sleep(1000).then(() => fetchSchemaFromJob(data));
return fetchSchemaFromJob(data); } else if (data.job.status === 3) {
} else if (data.job.status === 3) { return data.job.result;
return data.job.result; } else if (data.job.status === 4 && data.job.error.code === SCHEMA_NOT_SUPPORTED) {
} else if (data.job.status === 4 && data.job.error.code === SCHEMA_NOT_SUPPORTED) { return [];
return []; } else {
} else { return Promise.reject(new Error(data.job.error));
return Promise.reject(new Error(data.job.error)); }
}
});
}); });
}; };
return DataSource.fetchSchema(dataSource, refresh) return DataSource.fetchSchema(dataSource, refresh)
.then(fetchSchemaFromJob) .then(data => {
if (has(data, "job")) {
return fetchSchemaFromJob(data);
}
return has(data, "schema") ? data.schema : Promise.reject();
})
.catch(() => { .catch(() => {
notification.error("Schema refresh failed.", "Please try again later."); notification.error("Schema refresh failed.", "Please try again later.");
return Promise.resolve([]); return Promise.resolve([]);
@ -48,9 +51,11 @@ export default function useDataSourceSchema(dataSource) {
const reloadSchema = useCallback( const reloadSchema = useCallback(
(refresh = undefined) => { (refresh = undefined) => {
const refreshToken = Math.random().toString(36).substr(2); const refreshToken = Math.random()
.toString(36)
.substr(2);
refreshSchemaTokenRef.current = refreshToken; refreshSchemaTokenRef.current = refreshToken;
getSchema(dataSource, refresh).then((data) => { getSchema(dataSource, refresh).then(data => {
if (refreshSchemaTokenRef.current === refreshToken) { if (refreshSchemaTokenRef.current === refreshToken) {
setSchema(prepareSchema(data)); setSchema(prepareSchema(data));
} }

View File

@ -187,6 +187,12 @@ class DataSourceSchemaResource(BaseResource):
require_access(data_source, self.current_user, view_only) require_access(data_source, self.current_user, view_only)
refresh = request.args.get("refresh") is not None refresh = request.args.get("refresh") is not None
if not refresh:
cached_schema = data_source.get_cached_schema()
if cached_schema is not None:
return {"schema": cached_schema}
job = get_schema.delay(data_source.id, refresh) job = get_schema.delay(data_source.id, refresh)
return serialize_job(job) return serialize_job(job)

View File

@ -182,12 +182,16 @@ class DataSource(BelongsToOrgMixin, db.Model):
return res return res
def get_schema(self, refresh=False): def get_cached_schema(self):
cache = None cache = redis_connection.get(self._schema_key)
if not refresh: return json_loads(cache) if cache else None
cache = redis_connection.get(self._schema_key)
if cache is None: def get_schema(self, refresh=False):
out_schema = None
if not refresh:
out_schema = self.get_cached_schema()
if out_schema is None:
query_runner = self.query_runner query_runner = self.query_runner
schema = query_runner.get_schema(get_stats=refresh) schema = query_runner.get_schema(get_stats=refresh)
@ -200,8 +204,6 @@ class DataSource(BelongsToOrgMixin, db.Model):
out_schema = schema out_schema = schema
finally: finally:
redis_connection.set(self._schema_key, json_dumps(out_schema)) redis_connection.set(self._schema_key, json_dumps(out_schema))
else:
out_schema = json_loads(cache)
return out_schema return out_schema