{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from seeq import spy\n",
    "import pandas as pd"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# spy.jobs\n",
    "\n",
    "Commands to schedule a notebook to run in the background.\n",
    "\n",
    "**This feature is only available for scheduling notebooks in Seeq Data Lab. You cannot use SPy to schedule content in Anaconda, AWS SageMaker, or any other Python environment.**\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Scheduling a notebook to run in the background is achieved by adding the following command near the beginning of your notebook:\n",
    "\n",
    "```\n",
    "spy.jobs.schedule('every 6 hours')\n",
    "```\n",
    "\n",
    "This will cause the notebook that contains the command to run every six hours. This background execution is referred to as a _job_.\n",
    "\n",
    "The notebook can do anything you want, and the cell output can be inspected by going into the `_Job Results` folder that is created upon the first execution of the job."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Warning!\n",
    "\n",
    "**Scheduling jobs should be done with great care.** Jobs consume CPU, memory, and disk space resources and can easily cause degraded performance on Seeq Server, Seeq Data Lab or an external system that you may be accessing.\n",
    "\n",
    "If you are scheduling anything to run more frequent than every 15 minutes, you should probably discuss it with your Seeq administrator to make sure it's OK to consume those resources on a continual basis."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Example\n",
    "\n",
    "To try it out, execute the following cell (this cell only!). Within 15 minutes, you will find that there is a `_Job Results` folder with an HTML file in it corresponding to the output of this notebook."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;text-align: left;\">Scheduled the notebook <strong>SPy Documentation/spy.jobs.ipynb</strong> successfully.<br>Current context is <strong>INTERACTIVE</strong>.</div><table><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE;\">Schedule</td><td style=\"background-color: #EEFFEE;\">Scheduled</td><td style=\"background-color: #EEFFEE;\">Next Run</td></tr><tr style=\"background-color: #EEFFEE;\"><td>0</td><td>every 15 minutes</td><td>Every 15 minutes</td><td>2021-01-30 11:30:00 PST</td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Schedule</th>\n",
       "      <th>Scheduled</th>\n",
       "      <th>Next Run</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>every 15 minutes</td>\n",
       "      <td>Every 15 minutes</td>\n",
       "      <td>2021-01-30 11:30:00 PST</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "           Schedule         Scheduled                 Next Run\n",
       "0  every 15 minutes  Every 15 minutes  2021-01-30 11:30:00 PST"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "spy.jobs.schedule('every 15 minutes')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The following line will cause the job to be unscheduled after the first time it runs, which is what we want for the purposes of this tutorial. We don't want to consume resources unnecessarily!\n",
    "\n",
    "You would omit this line in \"real\" scenarios, since you want the job to run more than once."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "spy.jobs.unschedule()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If you would like to schedule multiple jobs and parameterize them, check out the [Parameterized Jobs](Parameterized%20Jobs.ipynb) example."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Below the scheduling command, you can add whatever code you would like. In this example, we will perform a trivial computation and push that into a Seeq Workbook Analysis."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pull_df = spy.pull(spy.search({'Name': 'Area A_Temperature', 'Datasource Name': 'Example Data'}))\n",
    "pull_df['Scheduling Example'] = pull_df['Area A_Temperature'].apply(lambda value: value+10)\n",
    "pull_df.drop(columns=['Area A_Temperature'], inplace=True)\n",
    "spy.push(pull_df)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "When you're working on debugging or improving your notebook, sometimes it's convenient to prevent jobs for the notebook from executing in the background. You can add the `suspend=True` argument to your `spy.jobs.schedule()` command to achieve that, and then you can remove the flag and execute the cell again to restart the job schedule."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Check out the help for the `spy.jobs.schedule()` function for more information:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Help on function schedule in module seeq.spy.jobs._schedule:\n",
      "\n",
      "schedule(schedule_spec: str = None, datalab_notebook_url: str = None, user: str = None, suspend: bool = False, quiet: bool = False, status: seeq.spy._common.Status = None)\n",
      "    Schedules the automatic execution of a Seeq Data Lab notebook.\n",
      "    \n",
      "    The current notebook is scheduled for execution unless datalab_notebook_url\n",
      "    is supplied. Scheduling can be done by user with admin privileges on behalf\n",
      "    of another user.\n",
      "    \n",
      "    Successive calls to 'schedule()' for the same notebook but with different\n",
      "    schedules will update the schedule of that notebook.\n",
      "    \n",
      "    Removing the scheduling is accomplished via unschedule().\n",
      "    \n",
      "    Parameters\n",
      "    ----------\n",
      "    schedule_spec : str\n",
      "        A string that represents the frequency with which the notebook should\n",
      "        execute.\n",
      "    \n",
      "        Examples: 'every 15 minutes'\n",
      "                  'every tuesday and friday at 6am'\n",
      "                  'every fifth of the month'\n",
      "    \n",
      "        The timezone used for scheduling is the one specified in the logged-in\n",
      "        user's profile.\n",
      "    \n",
      "        You can also use Quartz Cron syntax. Use the following site to\n",
      "        construct it:\n",
      "        https://www.freeformatter.com/cron-expression-generator-quartz.html\n",
      "    \n",
      "    datalab_notebook_url : str, default None\n",
      "        A datalab notebook URL. If the value is not specified the currently\n",
      "        running notebook URL is used.\n",
      "    \n",
      "    user : str, default None\n",
      "        Determines the user on whose behalf the notebook is executed. If the\n",
      "        value is not specified the currently logged in user is used. The can be\n",
      "        specified as username or a user's Seeq ID.\n",
      "    \n",
      "    suspend : bool default False\n",
      "        If True, unschedules all jobs for the specified notebook. This is used\n",
      "        in scenarios where you wish to work with a notebook interactively and\n",
      "        temporarily \"pause\" job execution. Remove the argument (or change it\n",
      "        to False) when you are ready to resume job execution.\n",
      "    \n",
      "    quiet : bool\n",
      "        If True, suppresses progress output.\n",
      "    \n",
      "    status : spy.Status, optional\n",
      "        If specified, the supplied Status object will be updated as the command\n",
      "        progresses. It gets filled in with the same information you would see\n",
      "        in Jupyter in the blue/green/red table below your code while the\n",
      "        command is executed. The table itself is accessible as a DataFrame via\n",
      "        the status.df property.\n",
      "    \n",
      "    Returns\n",
      "    -------\n",
      "    pd.DataFrame\n",
      "        The jobs_df with an appended column containing a description of the\n",
      "        schedule\n",
      "\n"
     ]
    }
   ],
   "source": [
    "help(spy.jobs.schedule)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
