Home | History | Annotate | Download | only in model
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package androidx.work.impl.model;
     18 
     19 import static android.arch.persistence.room.OnConflictStrategy.IGNORE;
     20 
     21 import static androidx.work.impl.model.WorkTypeConverters.StateIds.COMPLETED_STATES;
     22 
     23 import android.arch.lifecycle.LiveData;
     24 import android.arch.persistence.room.Dao;
     25 import android.arch.persistence.room.Insert;
     26 import android.arch.persistence.room.Query;
     27 import android.arch.persistence.room.Transaction;
     28 import android.support.annotation.NonNull;
     29 
     30 import androidx.work.Data;
     31 import androidx.work.State;
     32 
     33 import java.util.List;
     34 
     35 /**
     36  * The Data Access Object for {@link WorkSpec}s.
     37  */
     38 @Dao
     39 public interface WorkSpecDao {
     40 
     41     /**
     42      * Attempts to insert a {@link WorkSpec} into the database.
     43      *
     44      * @param workSpec The WorkSpec to insert.
     45      */
     46     @Insert(onConflict = IGNORE)
     47     void insertWorkSpec(WorkSpec workSpec);
     48 
     49     /**
     50      * Deletes {@link WorkSpec}s from the database.
     51      *
     52      * @param id The WorkSpec id to delete.
     53      */
     54     @Query("DELETE FROM workspec WHERE id=:id")
     55     void delete(String id);
     56 
     57     /**
     58      * @param id The identifier
     59      * @return The WorkSpec associated with that id
     60      */
     61     @Query("SELECT * FROM workspec WHERE id=:id")
     62     WorkSpec getWorkSpec(String id);
     63 
     64     /**
     65      * Retrieves {@link WorkSpec}s with the identifiers.
     66      *
     67      * @param ids The identifiers of desired {@link WorkSpec}s
     68      * @return The {@link WorkSpec}s with the requested IDs
     69      */
     70     @Query("SELECT * FROM workspec WHERE id IN (:ids)")
     71     WorkSpec[] getWorkSpecs(List<String> ids);
     72 
     73     /**
     74      * Retrieves {@link WorkSpec}s labelled with a given name.
     75      *
     76      * @param name The work graph name
     77      * @return The {@link WorkSpec}s labelled with the given name
     78      */
     79     @Query("SELECT id, state FROM workspec WHERE id IN "
     80             + "(SELECT work_spec_id FROM workname WHERE name=:name)")
     81     List<WorkSpec.IdAndState> getWorkSpecIdAndStatesForName(String name);
     82 
     83     /**
     84      * @return All WorkSpec ids in the database.
     85      */
     86     @Query("SELECT id FROM workspec")
     87     List<String> getAllWorkSpecIds();
     88 
     89     /**
     90      * Updates the state of at least one {@link WorkSpec} by ID.
     91      *
     92      * @param state The new state
     93      * @param ids The IDs for the {@link WorkSpec}s to update
     94      * @return The number of rows that were updated
     95      */
     96     @Query("UPDATE workspec SET state=:state WHERE id IN (:ids)")
     97     int setState(State state, String... ids);
     98 
     99     /**
    100      * Updates the output of a {@link WorkSpec}.
    101      *
    102      * @param id The {@link WorkSpec} identifier to update
    103      * @param output The {@link Data} to set as the output
    104      */
    105     @Query("UPDATE workspec SET output=:output WHERE id=:id")
    106     void setOutput(String id, Data output);
    107 
    108     /**
    109      * Updates the period start time of a {@link WorkSpec}.
    110      *
    111      * @param id The {@link WorkSpec} identifier to update
    112      * @param periodStartTime The time when the period started.
    113      */
    114     @Query("UPDATE workspec SET period_start_time=:periodStartTime WHERE id=:id")
    115     void setPeriodStartTime(String id, long periodStartTime);
    116 
    117     /**
    118      * Increment run attempt count of a {@link WorkSpec}.
    119      *
    120      * @param id The identifier for the {@link WorkSpec}
    121      * @return The number of rows that were updated (should be 0 or 1)
    122      */
    123     @Query("UPDATE workspec SET run_attempt_count=run_attempt_count+1 WHERE id=:id")
    124     int incrementWorkSpecRunAttemptCount(String id);
    125 
    126     /**
    127      * Reset run attempt count of a {@link WorkSpec}.
    128      *
    129      * @param id The identifier for the {@link WorkSpec}
    130      * @return The number of rows that were updated (should be 0 or 1)
    131      */
    132     @Query("UPDATE workspec SET run_attempt_count=0 WHERE id=:id")
    133     int resetWorkSpecRunAttemptCount(String id);
    134 
    135     /**
    136      * Retrieves the state of a {@link WorkSpec}.
    137      *
    138      * @param id The identifier for the {@link WorkSpec}
    139      * @return The state of the {@link WorkSpec}
    140      */
    141     @Query("SELECT state FROM workspec WHERE id=:id")
    142     State getState(String id);
    143 
    144     /**
    145      * For a {@link WorkSpec} identifier, retrieves its {@link WorkSpec.WorkStatusPojo}.
    146      *
    147      * @param id The identifier of the {@link WorkSpec}
    148      * @return A list of {@link WorkSpec.WorkStatusPojo}
    149      */
    150     @Transaction
    151     @Query("SELECT id, state, output FROM workspec WHERE id=:id")
    152     WorkSpec.WorkStatusPojo getWorkStatusPojoForId(String id);
    153 
    154     /**
    155      * For a list of {@link WorkSpec} identifiers, retrieves a {@link List} of their
    156      * {@link WorkSpec.WorkStatusPojo}.
    157      *
    158      * @param ids The identifier of the {@link WorkSpec}s
    159      * @return A {@link List} of {@link WorkSpec.WorkStatusPojo}
    160      */
    161     @Transaction
    162     @Query("SELECT id, state, output FROM workspec WHERE id IN (:ids)")
    163     List<WorkSpec.WorkStatusPojo> getWorkStatusPojoForIds(List<String> ids);
    164 
    165     /**
    166      * For a list of {@link WorkSpec} identifiers, retrieves a {@link LiveData} list of their
    167      * {@link WorkSpec.WorkStatusPojo}.
    168      *
    169      * @param ids The identifier of the {@link WorkSpec}s
    170      * @return A {@link LiveData} list of {@link WorkSpec.WorkStatusPojo}
    171      */
    172     @Transaction
    173     @Query("SELECT id, state, output FROM workspec WHERE id IN (:ids)")
    174     LiveData<List<WorkSpec.WorkStatusPojo>> getWorkStatusPojoLiveDataForIds(List<String> ids);
    175 
    176     /**
    177      * Retrieves a list of {@link WorkSpec.WorkStatusPojo} for all work with a given tag.
    178      *
    179      * @param tag The tag for the {@link WorkSpec}s
    180      * @return A list of {@link WorkSpec.WorkStatusPojo}
    181      */
    182     @Transaction
    183     @Query("SELECT id, state, output FROM workspec WHERE id IN "
    184             + "(SELECT work_spec_id FROM worktag WHERE tag=:tag)")
    185     List<WorkSpec.WorkStatusPojo> getWorkStatusPojoForTag(String tag);
    186 
    187     /**
    188      * Retrieves a {@link LiveData} list of {@link WorkSpec.WorkStatusPojo} for all work with a
    189      * given tag.
    190      *
    191      * @param tag The tag for the {@link WorkSpec}s
    192      * @return A {@link LiveData} list of {@link WorkSpec.WorkStatusPojo}
    193      */
    194     @Transaction
    195     @Query("SELECT id, state, output FROM workspec WHERE id IN "
    196             + "(SELECT work_spec_id FROM worktag WHERE tag=:tag)")
    197     LiveData<List<WorkSpec.WorkStatusPojo>> getWorkStatusPojoLiveDataForTag(String tag);
    198 
    199     /**
    200      * Retrieves a list of {@link WorkSpec.WorkStatusPojo} for all work with a given name.
    201      *
    202      * @param name The name of the {@link WorkSpec}s
    203      * @return A list of {@link WorkSpec.WorkStatusPojo}
    204      */
    205     @Transaction
    206     @Query("SELECT id, state, output FROM workspec WHERE id IN "
    207             + "(SELECT work_spec_id FROM workname WHERE name=:name)")
    208     List<WorkSpec.WorkStatusPojo> getWorkStatusPojoForName(String name);
    209 
    210     /**
    211      * Retrieves a {@link LiveData} list of {@link WorkSpec.WorkStatusPojo} for all work with a
    212      * given name.
    213      *
    214      * @param name The name for the {@link WorkSpec}s
    215      * @return A {@link LiveData} list of {@link WorkSpec.WorkStatusPojo}
    216      */
    217     @Transaction
    218     @Query("SELECT id, state, output FROM workspec WHERE id IN "
    219             + "(SELECT work_spec_id FROM workname WHERE name=:name)")
    220     LiveData<List<WorkSpec.WorkStatusPojo>> getWorkStatusPojoLiveDataForName(String name);
    221 
    222     /**
    223      * Gets all inputs coming from prerequisites for a particular {@link WorkSpec}.  These are
    224      * {@link Data} set via {@code Worker#setOutputData()}.
    225      *
    226      * @param id The {@link WorkSpec} identifier
    227      * @return A list of all inputs coming from prerequisites for {@code id}
    228      */
    229     @Query("SELECT output FROM workspec WHERE id IN "
    230             + "(SELECT prerequisite_id FROM dependency WHERE work_spec_id=:id)")
    231     List<Data> getInputsFromPrerequisites(String id);
    232 
    233     /**
    234      * Retrieves work ids for unfinished work with a given tag.
    235      *
    236      * @param tag The tag used to identify the work
    237      * @return A list of work ids
    238      */
    239     @Query("SELECT id FROM workspec WHERE state NOT IN " + COMPLETED_STATES
    240             + " AND id IN (SELECT work_spec_id FROM worktag WHERE tag=:tag)")
    241     List<String> getUnfinishedWorkWithTag(@NonNull String tag);
    242 
    243     /**
    244      * Retrieves work ids for unfinished work with a given name.
    245      *
    246      * @param name THe tag used to identify the work
    247      * @return A list of work ids
    248      */
    249     @Query("SELECT id FROM workspec WHERE state NOT IN " + COMPLETED_STATES
    250             + " AND id IN (SELECT work_spec_id FROM workname WHERE name=:name)")
    251     List<String> getUnfinishedWorkWithName(@NonNull String name);
    252 
    253     /**
    254      * Retrieves work ids for all unfinished work.
    255      *
    256      * @return A list of work ids
    257      */
    258     @Query("SELECT id FROM workspec WHERE state NOT IN " + COMPLETED_STATES)
    259     List<String> getAllUnfinishedWork();
    260 
    261     /**
    262      * Marks a {@link WorkSpec} as scheduled.
    263      *
    264      * @param id        The identifier for the {@link WorkSpec}
    265      * @param startTime The time at which the {@link WorkSpec} was scheduled.
    266      * @return The number of rows that were updated (should be 0 or 1)
    267      */
    268     @Query("UPDATE workspec SET schedule_requested_at=:startTime WHERE id=:id")
    269     int markWorkSpecScheduled(@NonNull String id, long startTime);
    270 
    271     /**
    272      * Resets the scheduled state on the {@link WorkSpec}s that are not in a a completed state.
    273      * @return The number of rows that were updated
    274      */
    275     @Query("UPDATE workspec SET schedule_requested_at=" + WorkSpec.SCHEDULE_NOT_REQUESTED_YET
    276             + " WHERE state NOT IN " + COMPLETED_STATES)
    277     int resetScheduledState();
    278 
    279     /**
    280      * @return The List of {@link WorkSpec}s that are eligible to be scheduled.
    281      */
    282     @Query("SELECT * from workspec WHERE "
    283             + "state=" + WorkTypeConverters.StateIds.ENQUEUED
    284             // We only want WorkSpecs which have not been previously scheduled.
    285             + " AND schedule_requested_at=" + WorkSpec.SCHEDULE_NOT_REQUESTED_YET
    286             + " LIMIT "
    287                 + "(SELECT :schedulerLimit" + "-COUNT(*) FROM workspec WHERE"
    288                     + " schedule_requested_at<>" + WorkSpec.SCHEDULE_NOT_REQUESTED_YET
    289                     + " AND state NOT IN " + COMPLETED_STATES
    290                 + ")"
    291     )
    292     List<WorkSpec> getEligibleWorkForScheduling(int schedulerLimit);
    293 
    294     /**
    295      * Immediately prunes eligible work from the database meeting the following criteria:
    296      * - Is finished (succeeded, failed, or cancelled)
    297      * - Has zero unfinished dependents
    298      */
    299     @Query("DELETE FROM workspec WHERE "
    300             + "state IN " + COMPLETED_STATES
    301             + " AND (SELECT COUNT(*)=0 FROM dependency WHERE "
    302             + "    prerequisite_id=id AND "
    303             + "    work_spec_id NOT IN "
    304             + "        (SELECT id FROM workspec WHERE state IN " + COMPLETED_STATES + "))")
    305     void pruneFinishedWorkWithZeroDependentsIgnoringKeepForAtLeast();
    306 }
    307