mirror of
https://github.com/apache/airflow.git
synced 2026-11-04 07:12:48 +00:00
Fixing the initdb script, adding to docs
This commit is contained in:
1 parent
86238652e5
commit
e3026ffafa
5 files changed
+85
-24
No files matched your search
@@ -2,4 +2,4 @@ Flux
|
||||
====
|
||||
Flux is a system to programmaticaly author, schedule and monitor data pipelines.
|
||||
|
||||
[Documentation](/static/docs/index.html)
|
||||
[Documentation](https://readthedocs.org/dashboard/flux-data-pipelines/)
|
||||
@@ -49,9 +49,12 @@ fine.
|
||||
CREATE USER 'flux'@'localhost' IDENTIFIED BY 'flux';
|
||||
GRANT ALL PRIVILEGES ON flux.* TO 'flux'@'localhost';
|
||||
|
||||
Start the web server
|
||||
Get things started
|
||||
''''''''''''''''''''
|
||||
|
||||
::
|
||||
# Creating the necessary tables in the database
|
||||
flux initdb
|
||||
|
||||
# Start the web server!
|
||||
flux webserver --port 8080
|
||||
+10
-16
@@ -181,15 +181,20 @@ def master(args):
|
||||
def initdb(args):
|
||||
|
||||
if raw_input(
|
||||
"This will empty crush the current DB if it exists. "
|
||||
"This will drop exisiting tables if they exists. "
|
||||
"Proceed? (y/n)").upper() == "Y":
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
from flux.models import *
|
||||
Base = declarative_base()
|
||||
Base.metadata.create_all(settings.engine)
|
||||
|
||||
from flux import models
|
||||
|
||||
logging.info("Dropping tables that exist")
|
||||
models.Base.metadata.drop_all(settings.engine)
|
||||
|
||||
logging.info("Creating all tables")
|
||||
models.Base.metadata.create_all(settings.engine)
|
||||
|
||||
# Creating the local_mysql DB connection
|
||||
session = settings.Session()
|
||||
"""
|
||||
session.query(models.DatabaseConnection).delete()
|
||||
mysqldb = models.DatabaseConnection(
|
||||
db_id='local_mysql', db_type='mysql',
|
||||
@@ -198,17 +203,6 @@ def initdb(args):
|
||||
session.add(mysqldb)
|
||||
session.commit()
|
||||
|
||||
logging.info("Dropping all tables")
|
||||
mysql_hook = MySqlHook(mysql_dbid='local_mysql')
|
||||
mysql_hook.run("DROP TABLE IF EXISTS task;")
|
||||
mysql_hook.run("DROP TABLE IF EXISTS job;")
|
||||
mysql_hook.run("DROP TABLE IF EXISTS task_instance;")
|
||||
mysql_hook.run("DROP TABLE IF EXISTS user;")
|
||||
mysql_hook.run("DROP TABLE IF EXISTS log;")
|
||||
mysql_hook.run("DROP TABLE IF EXISTS dag;")
|
||||
"""
|
||||
session.close()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser()
|
||||
|
||||
+66
-6
@@ -46,6 +46,10 @@ class DagBag(object):
|
||||
self.executor = executor
|
||||
|
||||
def process_file(self, filepath):
|
||||
"""
|
||||
Given a path to a python module, this method imports the module and
|
||||
look for dag objects whithin it.
|
||||
"""
|
||||
mod_name, file_ext = os.path.splitext(os.path.split(filepath)[-1])
|
||||
if file_ext != '.py':
|
||||
return
|
||||
@@ -66,6 +70,10 @@ class DagBag(object):
|
||||
dag.db_merge()
|
||||
|
||||
def collect_dags(self, file_location):
|
||||
"""
|
||||
Given a file path or a folder, this file looks for python modules,
|
||||
imports them and adds them to the dagbag collection.
|
||||
"""
|
||||
if os.path.isfile(file_location):
|
||||
self.process_file(file_location)
|
||||
elif os.path.isdir(file_location):
|
||||
@@ -93,7 +101,8 @@ class DatabaseConnection(Base):
|
||||
"""
|
||||
Placeholder to store information about different database instances
|
||||
connection information. The idea here is that scripts use references to
|
||||
database instances (db_id) when using operators or hooks.
|
||||
database instances (db_id) instead of hard coding hostname, logins and
|
||||
passwords when using operators or hooks.
|
||||
"""
|
||||
__tablename__ = "db_connection"
|
||||
|
||||
@@ -180,6 +189,11 @@ class TaskInstance(Base):
|
||||
ignore_dependencies=False,
|
||||
force=False,
|
||||
pickle=None):
|
||||
"""
|
||||
Returns a command that can be executed anywhere where flux is
|
||||
installed. This command is part of the message sent to executors by
|
||||
the orchestrator.
|
||||
"""
|
||||
iso = self.execution_date.isoformat()
|
||||
mark_success = "--mark_success" if mark_success else ""
|
||||
pickle = "--pickle {0}".format(pickle.id) if pickle else ""
|
||||
@@ -228,7 +242,7 @@ class TaskInstance(Base):
|
||||
|
||||
def error(self, main_session=None):
|
||||
"""
|
||||
Fails the task
|
||||
Forces the task instance's state to FAILED in the database.
|
||||
"""
|
||||
session = settings.Session()
|
||||
logging.error("Recording the task instance as FAILED")
|
||||
@@ -238,6 +252,9 @@ class TaskInstance(Base):
|
||||
session.close()
|
||||
|
||||
def refresh_from_db(self, main_session=None):
|
||||
"""
|
||||
Refreshes the task instance from the database based on the primary key
|
||||
"""
|
||||
session = main_session or settings.Session()
|
||||
TI = TaskInstance
|
||||
ti = session.query(TI).filter(
|
||||
@@ -258,9 +275,18 @@ class TaskInstance(Base):
|
||||
|
||||
@property
|
||||
def key(self):
|
||||
"""
|
||||
Returns a tuple that identifies the task instance uniquely
|
||||
"""
|
||||
return (self.dag_id, self.task_id, self.execution_date)
|
||||
|
||||
def is_runnable(self):
|
||||
"""
|
||||
Returns a boolean on whether the task instance has met all dependencies
|
||||
and is ready to run. It considers the task's state, the state
|
||||
of its dependencies, depends_on_past and makes sure the execution
|
||||
isn't in the future.
|
||||
"""
|
||||
if self.execution_date > datetime.now() - self.task.schedule_interval:
|
||||
return False
|
||||
elif self.state == State.UP_FOR_RETRY and not self.ready_for_retry():
|
||||
@@ -272,7 +298,8 @@ class TaskInstance(Base):
|
||||
|
||||
def are_dependencies_met(self, main_session=None):
|
||||
"""
|
||||
Returns a boolean on whether this task is ready to run.
|
||||
Returns a boolean on whether the upstream tasks are in a SUCCESS state
|
||||
and considers depends_on_past and the previous' run state.
|
||||
"""
|
||||
|
||||
# Using the session if passed as param
|
||||
@@ -310,6 +337,10 @@ class TaskInstance(Base):
|
||||
).format(ti=self)
|
||||
|
||||
def ready_for_retry(self):
|
||||
"""
|
||||
Checks on whether the task instance is in the right state and timeframe
|
||||
to be retried.
|
||||
"""
|
||||
return self.state == State.UP_FOR_RETRY and \
|
||||
self.end_date + self.task.retry_delay < datetime.now()
|
||||
|
||||
@@ -319,6 +350,9 @@ class TaskInstance(Base):
|
||||
force=False,
|
||||
mark_success=False,
|
||||
):
|
||||
"""
|
||||
Runs the task instnace.
|
||||
"""
|
||||
session = settings.Session()
|
||||
self.refresh_from_db(session)
|
||||
iso = datetime.now().isoformat()
|
||||
@@ -412,6 +446,9 @@ class TaskInstance(Base):
|
||||
|
||||
|
||||
class Log(Base):
|
||||
"""
|
||||
Used to actively log events to the database
|
||||
"""
|
||||
|
||||
__tablename__ = "log"
|
||||
|
||||
@@ -433,6 +470,12 @@ class Log(Base):
|
||||
|
||||
|
||||
class BaseJob(Base):
|
||||
"""
|
||||
Abstract class to be derived for jobs. Jobs are processing items with state
|
||||
and duration that aren't task instances. For instance a BackfillJob is
|
||||
a collection of task instance runs, but should have it's own state, start
|
||||
and end time.
|
||||
"""
|
||||
|
||||
__tablename__ = "job"
|
||||
|
||||
@@ -482,12 +525,20 @@ class BaseJob(Base):
|
||||
|
||||
|
||||
class BackfillJob(BaseJob):
|
||||
"""
|
||||
A backfill job consists of a dag or subdag for a specific time range. It
|
||||
triggers a set of task instance runs, in the right order and lasts for
|
||||
as long as it takes for the set of task instance to be completed.
|
||||
"""
|
||||
|
||||
__mapper_args__ = {
|
||||
'polymorphic_identity': 'BackfillJob'
|
||||
}
|
||||
|
||||
def run(self, dag, start_date=None, end_date=None, mark_success=False):
|
||||
"""
|
||||
Runs a dag for a specified date range.
|
||||
"""
|
||||
session = settings.Session()
|
||||
executor = self.executor
|
||||
self.dag = dag
|
||||
@@ -886,6 +937,10 @@ class DAG(Base):
|
||||
self, start_date=None, end_date=None,
|
||||
upstream=False, downstream=False):
|
||||
session = settings.Session()
|
||||
"""
|
||||
Clears a set of task instances associated with the current dag for
|
||||
a specified date range.
|
||||
"""
|
||||
|
||||
TI = TaskInstance
|
||||
tis = session.query(TI).filter(TI.dag_id == self.dag_id)
|
||||
@@ -905,7 +960,11 @@ class DAG(Base):
|
||||
def sub_dag(
|
||||
self, task_regex,
|
||||
include_downstream=False, include_upstream=True):
|
||||
|
||||
"""
|
||||
Returns a subset of the current dag as a deep copy of the current dag
|
||||
based on a regex that should match one or many tasks, and includes
|
||||
upstream and downstream neighboors based on the flag passed.
|
||||
"""
|
||||
dag = copy.deepcopy(self)
|
||||
regex_match = [
|
||||
t for t in dag.tasks if re.findall(task_regex, t.task_id)]
|
||||
@@ -935,6 +994,9 @@ class DAG(Base):
|
||||
return task
|
||||
|
||||
def tree_view(self):
|
||||
"""
|
||||
Shows an ascii tree representation of the DAG
|
||||
"""
|
||||
|
||||
def get_downstream(task, level=0):
|
||||
print (" " * level * 4) + str(task)
|
||||
@@ -968,5 +1030,3 @@ class DAG(Base):
|
||||
job.end_date = datetime.now()
|
||||
session.merge(job)
|
||||
session.commit()
|
||||
|
||||
Base.metadata.create_all(settings.engine)
|
||||
@@ -2,6 +2,10 @@ from flux.models import BaseOperator
|
||||
|
||||
|
||||
class DummyOperator(BaseOperator):
|
||||
"""
|
||||
Operator that does literally nothing. It can be used to group tasks in a
|
||||
dag.
|
||||
"""
|
||||
|
||||
template_fields = tuple()
|
||||
|
||||
|
||||
Reference in new issue
Block a user