aboutsummaryrefslogtreecommitdiffhomepage
path: root/tensorflow/tensorboard/components/tf_backend/behavior.ts
blob: 4f6af2f3ba37286891c62d4e6ad96cf03754ddc4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/* Copyright 2016 The TensorFlow Authors. All Rights Reserved.

Licensed 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 {getRuns, getTags, TYPES} from './backend';

export const BackendBehavior = {
  properties: {
    /** *** Required properties *** */
    /** Data type. One of Backend.TYPES */
    dataType: {
      type: String,
      observer: '_throwErrorOnUnrecognizedType',
    },

    /** Backend for data loading. */
    backend: {
      type: Object,
    },

    /** Should it automatically load when configured ready? Default true. */
    autoLoad: {
      type: Boolean,
      value: true,
    },

    /** *** Component-provided properties *** */
    /** Every tag available for data type (sorted, dedpulicated) */
    tags: {
      type: Array,
      readOnly: true,
      notify: true,
    },

    /** Every run available for data type (sorted) */
    runs: {
      type: Array,
      readOnly: true,
      notify: true,
    },

    /** Mapping from runs to tags for the data type */
    run2tag: {
      type: Object,
      readOnly: true,
      notify: true,
    },

    /** Promise provider for the data. Useful for passing to subcomponents */
    dataProvider:
        {type: Function, computed: '_getDataProvider(dataType, backend)'},

    /** Has the dashboard loaded yet? */
    loadState: {
      type: String,
      value: 'noload',  // [noload, pending, loaded, failure]
      readOnly: true,
    },

    /**
     * True if dashboard has loaded, and no tags were found.
     * Persists through subsequent reloads (ie. still true while
     * next load is pending) so warning won't flash away every reload
     * when there is no data.
     */
    dataNotFound: {
      type: Boolean,
      value: false,
      readOnly: true,
    }

  },
  observers: ['_do_autoLoad(dataType, backend, autoLoad)'],
  /**
   * Reloading works in two steps:
   * Backend reload, which gets metadata on available runs, tags, etc from
   *   the backend.
   * Frontend reload, which loads new data for each chart or visual display.
   * Backend reload logic is provided by this behaivor. The frontend reload
   *   logic should be provided elsewhere, since it is component-specific.
   * To keep things simple and consistent, we do the backend reload first,
   *   and the frontend reload afterwards.
   */
  reload() {
    return this.backendReload().then((x) => {
      return this.frontendReload();
    });
  },
  /**
   * Load data from backend and then set run2tag, tags, runs, and loadState.
   * Returns a promise that resolves/rejects when data is loaded.
   */
  backendReload() {
    if (this.dataType == null) {
      throw new Error('BackendBehavior: Need a dataType to reload.');
    }
    if (this.backend == null) {
      throw new Error('BackendBehavior: Need a backend to reload.');
    }
    const runsRoute = (this.backend[this.dataType + 'Runs'] ||
                       this.backend[this.dataType + 'Tags'])
                          .bind(this.backend);
    this._setLoadState('pending');
    return runsRoute().then(
        (x) => {
          this._setLoadState('loaded');
          if (_.isEqual(x, this.run2tag)) {
            // If x and run2tag are equal, let's avoid updating everything
            // since that can needlessly trigger run changes, reloads, etc
            return x;
          }
          this._setRun2tag(x);
          const tags = getTags(x);
          this._setDataNotFound(tags.length === 0);
          this._setTags(tags);
          this._setRuns(getRuns(x));
          return x;
        },
        (fail) => {
          this._setLoadState('failure');
          return fail;
        });
  },
  _do_autoLoad(type, backend, autoLoad) {
    if (autoLoad) {
      this.reload();
    }
  },
  _getDataProvider(dataType, backend) {
    return this.backend[this.dataType].bind(this.backend);
  },
  _throwErrorOnUnrecognizedType(dataType) {
    if (TYPES.indexOf(dataType) === -1) {
      throw new Error('BackendBehavior: Unknown dataType ' + dataType);
    }
  },
};