diff --git a/bin/version b/bin/version index b7ed9ca7c7c81c742a672298b109dba04e62e68a..57e96205b733c17a5281b644c5816374ccf06a8f 100755 --- a/bin/version +++ b/bin/version @@ -1,6 +1,6 @@ #!/usr/bin/env bash -VERSION="v0.26.0.RC2" +VERSION="v0.26.1" # dynamically pull more interesting stuff from latest git commit HASH=$(git show-ref --head --hash=7 head) # first 7 letters of hash should be enough; that's what GitHub uses diff --git a/frontend/src/metabase/xray/components/PreviewBanner.jsx b/frontend/src/metabase/xray/components/PreviewBanner.jsx new file mode 100644 index 0000000000000000000000000000000000000000..7a19820bcf8f2268af2a94076f8adfb92315e926 --- /dev/null +++ b/frontend/src/metabase/xray/components/PreviewBanner.jsx @@ -0,0 +1,12 @@ +import React from 'react' +import Icon from 'metabase/components/Icon' + +const SURVEY_LINK = 'https://docs.google.com/forms/d/e/1FAIpQLSc92WzF76ViiT8l4646lvFSWejNUhh4lhCSMXdZECILVwJG2A/viewform?usp=sf_link' + +const PreviewBanner = () => + <div className="full py2 flex align-center justify-center full md-py3 text-centered text-slate text-paragraph bg-white border-bottom"> + <Icon name='beaker' size={28} className="mr1 text-brand" style={{ marginTop: -5 }} /> + <span>Welcome to the x-ray preview! We'd love <a className="link" href={SURVEY_LINK} target="_blank">your feedback.</a></span> + </div> + +export default PreviewBanner diff --git a/frontend/src/metabase/xray/components/XRayLayout.jsx b/frontend/src/metabase/xray/components/XRayLayout.jsx index 58c0dd6243f009b5544b67939ff775584ab1c54e..9f0d7122e9037cd5cf949d53bb64224c75e7f5e7 100644 --- a/frontend/src/metabase/xray/components/XRayLayout.jsx +++ b/frontend/src/metabase/xray/components/XRayLayout.jsx @@ -1,10 +1,14 @@ import React from 'react' import { withBackground } from 'metabase/hoc/Background' +import PreviewBanner from 'metabase/xray/components/PreviewBanner' // A small wrapper to get consistent page structure export const XRayPageWrapper = withBackground('bg-slate-extra-light')(({ children }) => - <div className="XRayPageWrapper wrapper pb4 full-height"> - { children } + <div className="full-height full"> + <PreviewBanner /> + <div className="XRayPageWrapper wrapper pb4 full-height"> + { children } + </div> </div> ) diff --git a/resources/migrations/000_migrations.yaml b/resources/migrations/000_migrations.yaml index 679fa64323d72eb150e64a77996922766f1be739..ed1e8eeedc471dce3fc72754f89c4d9e10aff6b0 100644 --- a/resources/migrations/000_migrations.yaml +++ b/resources/migrations/000_migrations.yaml @@ -3829,87 +3829,17 @@ databaseChangeLog: baseTableName: raw_table constraintName: fk_rawtable_ref_database remarks: 'This FK prevents deleting databases even though RAW_TABLE is no longer used. The table is still around to support downgrades, but the FK reference is no longer needed.' +# Changeset 65 was accidentally released in 0.26.0.RC2. The changeset has been removed from the migrations list so that +# users that haven't ran the migration (i.e. they didn't run 0.26.0.RC2) won't waste time running it just to have it +# reversed. For 0.26.0.RC2 users, the below changeset will remove those tables if they are present - changeSet: - id: 65 - author: sbelak + id: 66 + author: senior comment: 'Added 0.26.0' + validCheckSum: '7:e494c2c90fe5c377526da7a6e5ad63a2' + validCheckSum: '7:76d06b44a544105c2a613603b8bdf25f' changes: - - createTable: - tableName: computation_job - remarks: 'Stores submitted async computation jobs.' - columns: - - column: - name: id - type: int - autoIncrement: true - constraints: - primaryKey: true - nullable: false - - column: - constraints: - deferrable: false - foreignKeyName: fk_computation_job_ref_user_id - initiallyDeferred: false - references: core_user(id) - name: creator_id - type: int - - column: - name: created_at - type: DATETIME - constraints: - nullable: false - - column: - name: updated_at - type: DATETIME - constraints: - nullable: false - - column: - name: type - type: varchar(254) - constraints: - nullable: false - - column: - name: status - type: varchar(254) - constraints: - nullable: false - - createTable: - tableName: computation_job_result - remarks: 'Stores results of async computation jobs.' - columns: - - column: - name: id - type: int - autoIncrement: true - constraints: - primaryKey: true - nullable: false - - column: - constraints: - deferrable: false - foreignKeyName: fk_computation_result_ref_job_id - initiallyDeferred: false - nullable: false - references: computation_job(id) - name: job_id - type: int - - column: - name: created_at - type: DATETIME - constraints: - nullable: false - - column: - name: updated_at - type: DATETIME - constraints: - nullable: false - - column: - name: permanence - type: varchar(254) - constraints: - nullable: false - - column: - name: payload - type: text - constraints: - nullable: false \ No newline at end of file + - sql: + sql: drop table if exists computation_job_result cascade + - sql: + sql: drop table if exists computation_job cascade diff --git a/src/metabase/api/x_ray.clj b/src/metabase/api/x_ray.clj index ddde0670554c875a0179342f6fcfedbaba588728..dfd7c11e93612fba2d13baa1aaac1383637e5bb1 100644 --- a/src/metabase/api/x_ray.clj +++ b/src/metabase/api/x_ray.clj @@ -2,12 +2,10 @@ (:require [compojure.core :refer [GET PUT]] [metabase.api.common :as api] [metabase.feature-extraction - [async :as async] [core :as fe] [costs :as costs]] [metabase.models [card :refer [Card]] - [computation-job :refer [ComputationJob]] [field :refer [Field]] [metric :refer [Metric]] [segment :refer [Segment]] @@ -58,26 +56,6 @@ max_computation_cost)}) fe/x-ray)) -(api/defendpoint GET "/async/table/:id" - "Get x-ray for a `Tield` with ID." - [id max_query_cost max_computation_cost] - {max_query_cost MaxQueryCost - max_computation_cost MaxComputationCost} - (api/check-403 (costs/enable-xrays)) - (let [table (api/read-check Table id)] - {:job-id (async/compute - #(->> table - (fe/extract-features {:max-cost (max-cost max_query_cost - max_computation_cost)}) - fe/x-ray))})) - -(api/defendpoint GET "/async/:id" - "Get x-ray for a `Tield` with ID." - [id] - (->> id - (api/read-check ComputationJob) - async/result)) - (api/defendpoint GET "/segment/:id" "Get x-ray for a `Segment` with ID." [id max_query_cost max_computation_cost] diff --git a/src/metabase/cmd/load_from_h2.clj b/src/metabase/cmd/load_from_h2.clj index fd16c8b653c6597da63090a646d8752d6009b33b..c232068fe9ef386af399850954765f11063e2465 100644 --- a/src/metabase/cmd/load_from_h2.clj +++ b/src/metabase/cmd/load_from_h2.clj @@ -29,8 +29,6 @@ [card-label :refer [CardLabel]] [collection :refer [Collection]] [collection-revision :refer [CollectionRevision]] - [computation-job :refer [ComputationJob]] - [computation-job-result :refer [ComputationJobResult]] [dashboard :refer [Dashboard]] [dashboard-card :refer [DashboardCard]] [dashboard-card-series :refer [DashboardCardSeries]] @@ -100,8 +98,6 @@ CollectionRevision DashboardFavorite Dimension - ComputationJob - ComputationJobResult ;; migrate the list of finished DataMigrations as the very last thing (all models to copy over should be listed above this line) DataMigrations]) diff --git a/src/metabase/feature_extraction/async.clj b/src/metabase/feature_extraction/async.clj deleted file mode 100644 index fe0338a92a3905206a2265374f6c2d1cc545e116..0000000000000000000000000000000000000000 --- a/src/metabase/feature_extraction/async.clj +++ /dev/null @@ -1,70 +0,0 @@ -(ns metabase.feature-extraction.async - (:require [metabase.api.common :as api] - [metabase.models - [computation-job :refer [ComputationJob]] - [computation-job-result :refer [ComputationJobResult]]] - [toucan.db :as db])) - -(defonce ^:private running-jobs (atom {})) - -(def ^{:arglists '([job])} done? - "Is the computation job done?" - (comp some? #{:done :error} :status)) - -(def ^{:arglists '([job])} running? - "Is the computation job still running?" - (comp some? #{:running} :status)) - -(defn- save-result - [{:keys [id]} payload] - (db/transaction - (db/insert! ComputationJobResult - :job_id id - :permanence :temporary - :payload payload) - (db/update! ComputationJob id :status :done)) - (swap! running-jobs dissoc id)) - -(defn- save-error - [{:keys [id]} error] - (db/transaction - (db/insert! ComputationJobResult - :job_id id - :permanence :temporary - :payload (Throwable->map error)) - (db/update! ComputationJob id :status :error)) - (swap! running-jobs dissoc id)) - -(defn cancel - "Cancel computation job (if still running)." - [{:keys [id] :as job}] - (when (running? job) - (future-cancel (@running-jobs id)) - (swap! running-jobs dissoc id) - (db/update! ComputationJob id :status :canceled))) - -(defn compute - "Compute closure `f` asynchronously. Returns id of the associated computation - job." - [f] - (let [job (db/insert! ComputationJob - :creator_id api/*current-user-id* - :status :running - :type :simple-job) - id (:id job)] - (swap! running-jobs assoc id (future - (try - (save-result job (f)) - (catch Exception e - (save-error job e))))) - id)) - -(defn result - "Get result of an asynchronous computation job." - [job] - (if (done? job) - (if-let [result (db/select-one ComputationJobResult :job_id (:id job))] - {:status (:status job) - :result (:payload result)} - {:status :result-not-available}) - {:status (:status job)})) diff --git a/src/metabase/models/computation_job.clj b/src/metabase/models/computation_job.clj deleted file mode 100644 index c3728ff9ef902dff71217e992839d0fb06905740..0000000000000000000000000000000000000000 --- a/src/metabase/models/computation_job.clj +++ /dev/null @@ -1,22 +0,0 @@ -(ns metabase.models.computation-job - (:require [metabase.api.common :as api] - [metabase.models.interface :as i] - [metabase.util :as u] - [toucan.models :as models])) - -(models/defmodel ComputationJob :computation_job) - -(defn- creator? - [{:keys [creator_id]}] - (= creator_id api/*current-user-id*)) - -(u/strict-extend (class ComputationJob) - models/IModel - (merge models/IModelDefaults - {:types (constantly {:status :keyword - :type :keyword}) - :properties (constantly {:timestamped? true})}) - i/IObjectPermissions - (merge i/IObjectPermissionsDefaults - {:can-read? creator? - :can-write? creator?})) diff --git a/src/metabase/models/computation_job_result.clj b/src/metabase/models/computation_job_result.clj deleted file mode 100644 index d1397726a6946164b7aa1a8c41d24f2fa9f39082..0000000000000000000000000000000000000000 --- a/src/metabase/models/computation_job_result.clj +++ /dev/null @@ -1,13 +0,0 @@ -(ns metabase.models.computation-job-result - (:require [metabase.models.interface :as i] - [metabase.util :as u] - [toucan.models :as models])) - -(models/defmodel ComputationJobResult :computation_job_result) - -(u/strict-extend (class ComputationJobResult) - models/IModel - (merge models/IModelDefaults - {:types (constantly {:permanence :keyword - :payload :json}) - :properties (constantly {:timestamped? true})})) diff --git a/src/metabase/task/cleanup_temporary_computation_job_results.clj b/src/metabase/task/cleanup_temporary_computation_job_results.clj deleted file mode 100644 index 0e76c7a2ea05b395ee15641508da5ae136b37807..0000000000000000000000000000000000000000 --- a/src/metabase/task/cleanup_temporary_computation_job_results.clj +++ /dev/null @@ -1,45 +0,0 @@ -(ns metabase.task.cleanup-temporary-computation-job-results - "Cleanup of old async computation results." - (:require [clj-time.core :as t] - [clojurewerkz.quartzite - [jobs :as jobs] - [triggers :as triggers]] - [clojurewerkz.quartzite.schedule.daily-interval :as interval] - [metabase.task :as task] - [toucan.db :as db])) - -(def ^:private temporary-result-lifetime (t/days 3)) - -(defn- cleanup-temporary-results! - [] - (db/delete! 'ComputationJobResult - :created_at [:< (-> (t/now) - (t/minus temporary-result-lifetime) - str)])) - -(def ^:private ^:const cleanup-job-key "metabase.task.cleanup-temporary-computation-job-results.job") -(def ^:private ^:const cleanup-trigger-key "metabase.task.cleanup-temporary-computation-job-results.trigger") - -(jobs/defjob Cleanup - [ctx] - (cleanup-temporary-results!)) - -(defonce ^:private cleanup-job (atom nil)) -(defonce ^:private cleanup-trigger (atom nil)) - -(defn task-init - "Automatically called during startup; start the job for sending pulses." - [] - (reset! cleanup-job (jobs/build - (jobs/of-type Cleanup) - (jobs/with-identity (jobs/key cleanup-job-key)))) - (reset! cleanup-trigger (triggers/build - (triggers/with-identity - (triggers/key cleanup-trigger-key)) - (triggers/start-now) - (triggers/with-schedule - ;; once per day at 3AM - (interval/schedule - (interval/starting-daily-at - (interval/time-of-day 03 00 00)))))) - (task/schedule-task! @cleanup-job @cleanup-trigger)) diff --git a/test/metabase/feature_extraction/async_test.clj b/test/metabase/feature_extraction/async_test.clj deleted file mode 100644 index 661625689fac5ebb5ce579a8e82cde4d8beff267..0000000000000000000000000000000000000000 --- a/test/metabase/feature_extraction/async_test.clj +++ /dev/null @@ -1,31 +0,0 @@ -(ns metabase.feature-extraction.async-test - (:require [expectations :refer :all] - [metabase.feature-extraction.async :refer :all] - [metabase.models.computation-job :refer [ComputationJob]])) - -(expect - true - (let [job-id (compute (constantly 1))] - (Thread/sleep 100) - (done? (ComputationJob job-id)))) - -(expect - true - (let [job-id (compute #(do (Thread/sleep 10000) nil))] - (Thread/sleep 100) - (running? (ComputationJob job-id)))) - -(expect - [true false false] - (let [job-id (compute #(do (Thread/sleep 100000) nil))] - (Thread/sleep 100) - (let [r? (running? (ComputationJob job-id))] - (cancel (ComputationJob job-id)) - [r? (done? (ComputationJob job-id)) (running? (ComputationJob job-id))]))) - -(expect - {:status :done - :result 1} - (let [job-id (compute (constantly 1))] - (Thread/sleep 100) - (result (ComputationJob job-id))))