# Path: yawn/task/models.py
# class Template(models.Model):
#     workflow = models.ForeignKey('Workflow', models.PROTECT, editable=False, null=True)
#     queue = models.ForeignKey(Queue, models.PROTECT)
#     name = models.TextField()
# 
#     command = models.TextField()
#     max_retries = models.IntegerField(default=0)
#     timeout = models.IntegerField(null=True)  # seconds
# 
#     # self-reference for upstream tasks
#     upstream = models.ManyToManyField(
#         'Template', related_name='downstream', symmetrical=False, blank=True)
# 
#     class Meta:
#         unique_together = ('workflow', 'name')
# 
#     def __str__(self):
#         return self.name
# 
#     def save(self, *args, **kwargs):
#         # can't set the default above because the value isn't serializable for migrations
#         if not self.queue_id:
#             self.queue = Queue.get_default_queue()
#         super().save(*args, **kwargs)
# 
# Path: yawn/worker/models.py
# class Worker(models.Model):
#     """Information about current and past workers"""
#     #
#     # NOTE: consider instead taking an advisory lock for each worker,
#     # and using it to check if a worker is still connected.
#     # See `pg_try_advisory_lock` and `select * from pg_locks where locktype = 'advisory'`
#     # That would give more immediate feedback, but its not clear we need to be faster.
#     #
#     ACTIVE = 'active'
#     EXITED = 'exited'
#     LOST = 'lost'
#     STATUS_CHOICES = [(x, x) for x in (ACTIVE, EXITED, LOST)]
# 
#     name = models.TextField(blank=False)
#     status = models.TextField(choices=STATUS_CHOICES, default=ACTIVE)
#     start_timestamp = models.DateTimeField(default=functions.Now)
#     last_heartbeat = models.DateTimeField(default=functions.Now)
# 
#     @staticmethod
#     def find_lost(timeout):
#         from yawn.task.models import Execution
# 
#         # Make a sparse index so looking up active workers is fast:
#         # CREATE INDEX yawn_worker_active ON yawn_worker (status) WHERE status = 'active'
#         lost = Worker.objects.filter(
#             status=Worker.ACTIVE, last_heartbeat__lt=functions.Now() - timedelta(seconds=timeout)
#         )
#         for worker in lost:
#             logger.warning('Marking %r as lost', worker)
#             worker.status = Worker.LOST
#             worker.save()
# 
#             executions = worker.execution_set.filter(status=Execution.RUNNING)
# 
#             for execution in executions:
#                 logger.warning('Marking %r as lost', execution)
#                 execution.mark_finished(lost=True)
# 
#     def __str__(self):
#         return self.name
# 
# class Queue(models.Model):
#     """Arbitrary tag defining where tasks run."""
# 
#     name = models.TextField(unique=True)
# 
#     _default = None
# 
#     def __str__(self):
#         return self.name
# 
#     @classmethod
#     def get_default_queue(cls):
#         if not cls._default:
#             cls._default = Queue.objects.get_or_create(name='default')[0]
#         return cls._default
# 
# class Message(models.Model):
#     """The order of tasks waiting to be processed, like messages on a queue"""
# 
#     # I hope we never get to 9 Quintillion (9,223,372,036,854,775,807) messages
#     id = models.BigAutoField(primary_key=True)
# 
#     queue = models.ForeignKey(Queue, models.PROTECT)
#     task = models.ForeignKey('Task', models.PROTECT)
# 
# Path: yawn/workflow/models.py
# class WorkflowName(models.Model):
#     name = models.TextField(unique=True)
#     current_version = models.OneToOneField('Workflow', on_delete=models.CASCADE,
#                                            null=True, related_name='is_current')
# 
#     def new_version(self, **kwargs):
#         """Create a new version of a workflow"""
#         version = 0
#         if self.current_version_id:
#             version = self.current_version.version
# 
#             # disable the past schedule
#             self.current_version.schedule_active = False
#             self.current_version.save()
# 
#         workflow = Workflow.objects.create(name=self, version=version + 1, **kwargs)
#         self.current_version = workflow
#         self.save()
#         return workflow


import pytest
from yawn.task.models import Template
from yawn.worker.models import Worker, Queue, Message
from yawn.workflow.models import WorkflowName



def test_get_workers(client):
    worker = Worker.objects.create(name='worker1')
    response = client.get('/api/workers/')
    assert response.status_code == 200
    workers = response.data['results']
    assert len(workers) == 1
    assert workers[0]['name'] == worker.name
    assert workers[0]['status'] == worker.status


@pytest.fixture()
def queue():
    queue = Queue.objects.create(name='queue1')

    # need all this for a task...
    name = WorkflowName.objects.create(name='workflow1')
    workflow = name.new_version()
    Template.objects.create(workflow=workflow, name='task1', command=[''])
    run = workflow.submit_run()
    task = run.task_set.first()

    # create some messages
    Message.objects.create(task=task, queue=queue)
    Message.objects.create(task=task, queue=queue)

# Path: yawn/task/models.py
# class Template(models.Model):
#     workflow = models.ForeignKey('Workflow', models.PROTECT, editable=False, null=True)
#     queue = models.ForeignKey(Queue, models.PROTECT)
#     name = models.TextField()
# 
#     command = models.TextField()
#     max_retries = models.IntegerField(default=0)
#     timeout = models.IntegerField(null=True)  # seconds
# 
#     # self-reference for upstream tasks
#     upstream = models.ManyToManyField(
#         'Template', related_name='downstream', symmetrical=False, blank=True)
# 
#     class Meta:
#         unique_together = ('workflow', 'name')
# 
#     def __str__(self):
#         return self.name
# 
#     def save(self, *args, **kwargs):
#         # can't set the default above because the value isn't serializable for migrations
#         if not self.queue_id:
#             self.queue = Queue.get_default_queue()
#         super().save(*args, **kwargs)
# 
# Path: yawn/worker/models.py
# class Worker(models.Model):
#     """Information about current and past workers"""
#     #
#     # NOTE: consider instead taking an advisory lock for each worker,
#     # and using it to check if a worker is still connected.
#     # See `pg_try_advisory_lock` and `select * from pg_locks where locktype = 'advisory'`
#     # That would give more immediate feedback, but its not clear we need to be faster.
#     #
#     ACTIVE = 'active'
#     EXITED = 'exited'
#     LOST = 'lost'
#     STATUS_CHOICES = [(x, x) for x in (ACTIVE, EXITED, LOST)]
# 
#     name = models.TextField(blank=False)
#     status = models.TextField(choices=STATUS_CHOICES, default=ACTIVE)
#     start_timestamp = models.DateTimeField(default=functions.Now)
#     last_heartbeat = models.DateTimeField(default=functions.Now)
# 
#     @staticmethod
#     def find_lost(timeout):
#         from yawn.task.models import Execution
# 
#         # Make a sparse index so looking up active workers is fast:
#         # CREATE INDEX yawn_worker_active ON yawn_worker (status) WHERE status = 'active'
#         lost = Worker.objects.filter(
#             status=Worker.ACTIVE, last_heartbeat__lt=functions.Now() - timedelta(seconds=timeout)
#         )
#         for worker in lost:
#             logger.warning('Marking %r as lost', worker)
#             worker.status = Worker.LOST
#             worker.save()
# 
#             executions = worker.execution_set.filter(status=Execution.RUNNING)
# 
#             for execution in executions:
#                 logger.warning('Marking %r as lost', execution)
#                 execution.mark_finished(lost=True)
# 
#     def __str__(self):
#         return self.name
# 
# class Queue(models.Model):
#     """Arbitrary tag defining where tasks run."""
# 
#     name = models.TextField(unique=True)
# 
#     _default = None
# 
#     def __str__(self):
#         return self.name
# 
#     @classmethod
#     def get_default_queue(cls):
#         if not cls._default:
#             cls._default = Queue.objects.get_or_create(name='default')[0]
#         return cls._default
# 
# class Message(models.Model):
#     """The order of tasks waiting to be processed, like messages on a queue"""
# 
#     # I hope we never get to 9 Quintillion (9,223,372,036,854,775,807) messages
#     id = models.BigAutoField(primary_key=True)
# 
#     queue = models.ForeignKey(Queue, models.PROTECT)
#     task = models.ForeignKey('Task', models.PROTECT)
# 
# Path: yawn/workflow/models.py
# class WorkflowName(models.Model):
#     name = models.TextField(unique=True)
#     current_version = models.OneToOneField('Workflow', on_delete=models.CASCADE,
#                                            null=True, related_name='is_current')
# 
#     def new_version(self, **kwargs):
#         """Create a new version of a workflow"""
#         version = 0
#         if self.current_version_id:
#             version = self.current_version.version
# 
#             # disable the past schedule
#             self.current_version.schedule_active = False
#             self.current_version.save()
# 
#         workflow = Workflow.objects.create(name=self, version=version + 1, **kwargs)
#         self.current_version = workflow
#         self.save()
#         return workflow


# Path: yawn/worker/tests/test_views.py
import pytest
from yawn.task.models import Template
from yawn.worker.models import Worker, Queue, Message
from yawn.workflow.models import WorkflowName




def test_get_workers(client):
    worker = Worker.objects.create(name='worker1')
    response = client.get('/api/workers/')
    assert response.status_code == 200
    workers = response.data['results']
    assert len(workers) == 1
    assert workers[0]['name'] == worker.name
    assert workers[0]['status'] == worker.status


@pytest.fixture()
def queue():
    queue = Queue.objects.create(name='queue1')

    # need all this for a task...
    name = WorkflowName.objects.create(name='workflow1')
    workflow = name.new_version()
    Template.objects.create(workflow=workflow, name='task1', command=[''])
    run = workflow.submit_run()
    task = run.task_set.first()

    # create some messages
    Message.objects.create(task=task, queue=queue)
    Message.objects.create(task=task, queue=queue)

    Message.objects.create(task=task, queue=Queue.get_default_queue())