/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF 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 React from 'react'; import PropTypes from 'prop-types'; import { bindActionCreators } from 'redux'; import { connect } from 'react-redux'; import { SupersetClient } from '@superset-ui/core'; import * as Actions from 'src/SqlLab/actions/sqlLab'; const QUERY_UPDATE_FREQ = 2000; const QUERY_UPDATE_BUFFER_MS = 5000; const MAX_QUERY_AGE_TO_POLL = 21600000; const QUERY_TIMEOUT_LIMIT = 10000; class QueryAutoRefresh extends React.PureComponent { constructor(props) { super(props); this.state = { offline: props.offline, }; } UNSAFE_componentWillMount() { this.startTimer(); } componentDidUpdate(prevProps) { if (prevProps.offline !== this.state.offline) { this.props.actions.setUserOffline(this.state.offline); } } componentWillUnmount() { this.stopTimer(); } shouldCheckForQueries() { // if there are started or running queries, this method should return true const { queries } = this.props; const now = new Date().getTime(); const isQueryRunning = q => ['running', 'started', 'pending', 'fetching'].indexOf(q.state) >= 0; return Object.values(queries).some( q => isQueryRunning(q) && now - q.startDttm < MAX_QUERY_AGE_TO_POLL, ); } startTimer() { if (!this.timer) { this.timer = setInterval(this.stopwatch.bind(this), QUERY_UPDATE_FREQ); } } stopTimer() { clearInterval(this.timer); this.timer = null; } stopwatch() { // only poll /superset/queries/ if there are started or running queries if (this.shouldCheckForQueries()) { SupersetClient.get({ endpoint: `/superset/queries/${ this.props.queriesLastUpdate - QUERY_UPDATE_BUFFER_MS }`, timeout: QUERY_TIMEOUT_LIMIT, }) .then(({ json }) => { if (Object.keys(json).length > 0) { this.props.actions.refreshQueries(json); } this.setState({ offline: false }); }) .catch(() => { this.setState({ offline: true }); }); } else { this.setState({ offline: false }); } } render() { return null; } } QueryAutoRefresh.propTypes = { offline: PropTypes.bool.isRequired, queries: PropTypes.object.isRequired, actions: PropTypes.object.isRequired, queriesLastUpdate: PropTypes.number.isRequired, }; function mapStateToProps({ sqlLab }) { return { offline: sqlLab.offline, queries: sqlLab.queries, queriesLastUpdate: sqlLab.queriesLastUpdate, }; } function mapDispatchToProps(dispatch) { return { actions: bindActionCreators(Actions, dispatch), }; } export default connect(mapStateToProps, mapDispatchToProps)(QueryAutoRefresh);