Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drop the DbCalcState table #2198

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
aiida/backends/djsite/db/migrations/0014_add_node_uuid_unique_constraint.py|
aiida/backends/djsite/db/migrations/0015_invalidating_node_hash.py|
aiida/backends/djsite/db/migrations/0016_code_sub_class_of_data.py|
aiida/backends/djsite/db/migrations/0017_drop_dbcalcstate.py|
aiida/backends/djsite/db/migrations/__init__.py|
aiida/backends/djsite/db/models.py|
aiida/backends/djsite/db/subtests/djangomigrations.py|
Expand Down Expand Up @@ -69,6 +70,7 @@
aiida/backends/sqlalchemy/migrations/versions/62fe0d36de90_add_node_uuid_unique_constraint.py|
aiida/backends/sqlalchemy/migrations/versions/5d4d844852b6_invalidating_node_hash.py|
aiida/backends/sqlalchemy/migrations/versions/a603da2cc809_code_sub_class_of_data.py|
aiida/backends/sqlalchemy/migrations/versions/162b99bca4a2_drop_dbcalcstate.py|
aiida/backends/sqlalchemy/models/authinfo.py|
aiida/backends/sqlalchemy/models/base.py|
aiida/backends/sqlalchemy/models/comment.py|
Expand Down
4 changes: 2 additions & 2 deletions aiida/backends/djsite/db/migrations/0002_db_state_change.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,11 @@


def fix_calc_states(apps, schema_editor):
from aiida.backends.djsite.db.models import DbCalcState
# from aiida.orm import load_node
from aiida.orm.utils import load_node

# These states should never exist in the database but we'll play it safe
# and deal with them if they do
DbCalcState = apps.get_model('db', 'DbCalcState')
for calc_state in DbCalcState.objects.filter(
state__in=[b'UNDETERMINED', b'NOTFOUND']):
old_state = calc_state.state
Expand All @@ -40,6 +39,7 @@ def fix_calc_states(apps, schema_editor):
"the database. Changed state to FAILED.".format(
old_state, calc_state.dbnode.pk))


class Migration(migrations.Migration):
dependencies = [
('db', '0001_initial'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,22 @@
# For further information on the license, see the LICENSE.txt file #
# For further information please visit http://www.aiida.net #
###########################################################################

from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from __future__ import absolute_import
from aiida.orm.implementation.general.calculation import AbstractCalculation
from aiida.orm.implementation.sqlalchemy.node import Node

from django.db import migrations
from aiida.backends.djsite.db.migrations import upgrade_schema_version

REVISION = '1.0.17'
DOWN_REVISION = '1.0.16'


class Migration(migrations.Migration):

dependencies = [
('db', '0016_code_sub_class_of_data'),
]

class Calculation(AbstractCalculation, Node):
pass
operations = [migrations.DeleteModel(name='DbCalcState',), upgrade_schema_version(REVISION, DOWN_REVISION)]
2 changes: 1 addition & 1 deletion aiida/backends/djsite/db/migrations/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from __future__ import print_function
from __future__ import absolute_import

LATEST_MIGRATION = '0016_code_sub_class_of_data'
LATEST_MIGRATION = '0017_drop_dbcalcstate'


def _update_schema_version(version, apps, schema_editor):
Expand Down
20 changes: 0 additions & 20 deletions aiida/backends/djsite/db/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1263,26 +1263,6 @@ class DbExtra(DbAttributeBaseClass):
pass


class DbCalcState(m.Model):
"""
Store the state of calculations.

The advantage of a table (with uniqueness constraints) is that this
disallows entering twice in the same state (e.g., retrieving twice).
"""
from aiida.common.datastructures import calc_states
# Delete states when deleting the calc, does not make sense to keep them
dbnode = m.ForeignKey(DbNode, on_delete=m.CASCADE,
related_name='dbstates')
state = m.CharField(max_length=25,
choices=tuple((_, _) for _ in calc_states),
db_index=True)
time = m.DateTimeField(default=timezone.now, editable=False)

class Meta:
unique_together = (("dbnode", "state"))


@python_2_unicode_compatible
class DbGroup(m.Model):
"""
Expand Down
69 changes: 0 additions & 69 deletions aiida/backends/djsite/db/subtests/djangomigrations.py

This file was deleted.

2 changes: 1 addition & 1 deletion aiida/backends/djsite/queries.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def query_jobcalculations_by_computer_user_state(
# I assume that calc_states are strings. If this changes in the future,
# update the filter below from dbattributes__tval to the correct field.
from aiida.common.exceptions import InputValidationError
from aiida.orm.implementation.django.calculation.job import JobCalculation
from aiida.orm.implementation.calculation.job import JobCalculation
from aiida.common.datastructures import calc_states
from aiida.backends.djsite.db.models import DbUser

Expand Down
4 changes: 1 addition & 3 deletions aiida/backends/sqlalchemy/migrations/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,7 @@
from aiida.backends.sqlalchemy.models.computer import DbComputer
from aiida.backends.sqlalchemy.models.group import DbGroup
from aiida.backends.sqlalchemy.models.log import DbLog
from aiida.backends.sqlalchemy.models.node import (
DbCalcState, DbComputer,
DbContentError, DbLink, DbNode)
from aiida.backends.sqlalchemy.models.node import DbComputer, DbContentError, DbLink, DbNode
from aiida.backends.sqlalchemy.models.settings import DbSetting
from aiida.backends.sqlalchemy.models.user import DbUser
from aiida.backends.sqlalchemy.models.workflow import (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# -*- coding: utf-8 -*-
###########################################################################
# Copyright (c), The AiiDA team. All rights reserved. #
# This file is part of the AiiDA code. #
# #
# The code is hosted on GitHub at https://github.com/aiidateam/aiida_core #
# For further information on the license, see the LICENSE.txt file #
# For further information please visit http://www.aiida.net #
###########################################################################
"""Drop the DbCalcState table

Revision ID: 162b99bca4a2
Revises: a603da2cc809
Create Date: 2018-11-14 08:37:13.719646

"""
from __future__ import division
from __future__ import print_function
from __future__ import absolute_import
from alembic import op
from sqlalchemy.dialects import postgresql
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = '162b99bca4a2'
down_revision = 'a603da2cc809'
branch_labels = None
depends_on = None


def upgrade():
op.drop_table('db_dbcalcstate')


def downgrade():
op.create_table(
'db_dbcalcstate', sa.Column('id', sa.INTEGER(), nullable=False),
sa.Column('dbnode_id', sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column('state', sa.VARCHAR(length=255), autoincrement=False, nullable=True),
sa.Column('time', postgresql.TIMESTAMP(timezone=True), autoincrement=False, nullable=True),
sa.ForeignKeyConstraint(
['dbnode_id'], [u'db_dbnode.id'],
name=u'db_dbcalcstate_dbnode_id_fkey',
ondelete=u'CASCADE',
initially=u'DEFERRED',
deferrable=True), sa.PrimaryKeyConstraint('id', name=u'db_dbcalcstate_pkey'),
sa.UniqueConstraint('dbnode_id', 'state', name=u'db_dbcalcstate_dbnode_id_state_key'))
98 changes: 0 additions & 98 deletions aiida/backends/sqlalchemy/models/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,36 +34,6 @@
from aiida.backends.sqlalchemy.models.computer import DbComputer


class DbCalcState(Base):
__tablename__ = "db_dbcalcstate"

id = Column(Integer, primary_key=True)

dbnode_id = Column(
Integer,
ForeignKey(
'db_dbnode.id', ondelete="CASCADE",
deferrable=True, initially="DEFERRED"
)
)
dbnode = relationship(
'DbNode', backref=backref('dbstates', passive_deletes=True),
)

# Note: this is suboptimal: calc_states is not sorted
# therefore the order is not the expected one. If we
# were to use the correct order here, we could directly sort
# without specifying a custom order. This is probably faster,
# but requires a schema migration at this point
state = Column(ChoiceType((_, _) for _ in calc_states), index=True)

time = Column(DateTime(timezone=True), default=timezone.now)

__table_args__ = (
UniqueConstraint('dbnode_id', 'state'),
)


class DbNode(Base):
__tablename__ = "db_dbnode"

Expand Down Expand Up @@ -272,74 +242,6 @@ def computer_name(cls):
cls.dbcomputer_id).label(
'computer_name')

@hybrid_property
def state(self):
"""
Return the most recent state from DbCalcState
"""
if not self.id:
return None
all_states = DbCalcState.query.filter(DbCalcState.dbnode_id == self.id).all()
if all_states:
# return max((st.time, st.state) for st in all_states)[1]
return sort_states(((dbcalcstate.state, dbcalcstate.state.value)
for dbcalcstate in all_states),
use_key=True)[0]
else:
return None

@state.expression
def state(cls):
"""
Return the expression to get the 'latest' state from DbCalcState,
to be used in queries, where 'latest' is defined using the state order
defined in _sorted_datastates.
"""
# Sort first the latest states
whens = {
v: idx for idx, v
in enumerate(_sorted_datastates[::-1], start=1)}
custom_sort_order = case(value=DbCalcState.state,
whens=whens,
else_=100) # else: high value to put it at the bottom

# Add numerical state to string, to allow to sort them
states_with_num = select([
DbCalcState.id.label('id'),
DbCalcState.dbnode_id.label('dbnode_id'),
DbCalcState.state.label('state_string'),
custom_sort_order.label('num_state')
]).select_from(DbCalcState).alias()

# Get the most 'recent' state (using the state ordering, and the min function) for
# each calc
calc_state_num = select([
states_with_num.c.dbnode_id.label('dbnode_id'),
func.min(states_with_num.c.num_state).label('recent_state')
]).group_by(states_with_num.c.dbnode_id).alias()

# Join the most-recent-state table with the DbCalcState table
all_states_q = select([
DbCalcState.dbnode_id.label('dbnode_id'),
DbCalcState.state.label('state_string'),
calc_state_num.c.recent_state.label('recent_state'),
custom_sort_order.label('num_state'),
]).select_from( # DbCalcState).alias().join(
join(DbCalcState, calc_state_num, DbCalcState.dbnode_id == calc_state_num.c.dbnode_id)).alias()

# Get the association between each calc and only its corresponding most-recent-state row
subq = select([
all_states_q.c.dbnode_id.label('dbnode_id'),
all_states_q.c.state_string.label('state')
]).select_from(all_states_q).where(all_states_q.c.num_state == all_states_q.c.recent_state).alias()

# Final filtering for the actual query
return select([subq.c.state]). \
where(
subq.c.dbnode_id == cls.id,
). \
label('laststate')


class DbLink(Base):
__tablename__ = "db_dblink"
Expand Down
1 change: 0 additions & 1 deletion aiida/backends/tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
BACKEND_DJANGO: {
'generic': ['aiida.backends.djsite.db.subtests.generic'],
'nodes': ['aiida.backends.djsite.db.subtests.nodes'],
'djangomigrations': ['aiida.backends.djsite.db.subtests.djangomigrations'],
'migrations': ['aiida.backends.djsite.db.subtests.migrations'],
'query': ['aiida.backends.djsite.db.subtests.query'],
},
Expand Down
2 changes: 1 addition & 1 deletion aiida/backends/tests/cmdline/commands/test_calculation.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from aiida.backends.testbase import AiidaTestCase
from aiida.cmdline.commands import cmd_calculation as command
from aiida.common.datastructures import calc_states
from aiida.orm.calculation.job import JobCalculationExitStatus
from aiida.orm.implementation.general.calculation.job import JobCalculationExitStatus
from aiida.work import runners, rmq


Expand Down
Loading