-
Notifications
You must be signed in to change notification settings - Fork 4
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
Report model and DataStore failure modes #268
Changes from all commits
3939bfd
b286fbb
9016133
060ea82
7cd3ef0
71101d5
aead6eb
42cb674
a7128dc
dce797f
c269863
a22a712
d51031d
83bd122
49b5135
c767028
2ac7ee7
7c607a2
8e63a0b
679db26
78b484a
709af1b
1580c26
8178176
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
name: Run Model Tests 2 | ||
|
||
on: | ||
push: | ||
branches: | ||
- main | ||
pull_request: | ||
workflow_dispatch: | ||
|
||
jobs: | ||
tests: | ||
name: run tests in docker image | ||
runs-on: ubuntu-latest | ||
env: | ||
REGISTRY: ghcr.io | ||
COMPOSE_FILE: tests/docker-compose.yaml | ||
|
||
steps: | ||
- name: Dump docker logs on failure | ||
if: failure() | ||
uses: jwalton/gh-docker-logs@v2 | ||
|
||
- name: checkout code | ||
uses: actions/checkout@v3 | ||
with: | ||
submodules: recursive | ||
|
||
- name: log into github container registry | ||
uses: docker/login-action@v2 | ||
with: | ||
registry: ghcr.io | ||
username: ${{ github.actor }} | ||
password: ${{ secrets.GITHUB_TOKEN }} | ||
|
||
- name: setup docker buildx | ||
uses: docker/setup-buildx-action@v2 | ||
with: | ||
driver: docker-container | ||
|
||
- name: bake | ||
uses: docker/[email protected] | ||
with: | ||
workdir: tests | ||
load: true | ||
files: docker-compose.yaml | ||
set: | | ||
seechange_postgres.tags=ghcr.io/${{ github.repository_owner }}/seechange-postgres | ||
seechange_postgres.cache-from=type=gha,scope=cached-seechange-postgres | ||
seechange_postgres.cache-to=type=gha,scope=cached-seechange-postgres,mode=max | ||
setuptables.tags=ghcr.io/${{ github.repository_owner }}/runtests | ||
setuptables.cache-from=type=gha,scope=cached-seechange | ||
setuptables.cache-to=type=gha,scope=cached-seechange,mode=max | ||
runtests.tags=ghcr.io/${{ github.repository_owner }}/runtests | ||
runtests.cache-from=type=gha,scope=cached-seechange | ||
runtests.cache-to=type=gha,scope=cached-seechange,mode=max | ||
shell.tags=ghcr.io/${{ github.repository_owner }}/runtests | ||
shell.cache-from=type=gha,scope=cached-seechange | ||
shell.cache-to=type=gha,scope=cached-seechange,mode=max | ||
|
||
- name: run test | ||
run: | | ||
shopt -s nullglob | ||
TEST_SUBFOLDER=$(ls tests/models/test_{m..z}*.py) docker compose run runtests |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
"""add report model | ||
|
||
Revision ID: 485334f16c23 | ||
Revises: 573289f12368 | ||
Create Date: 2024-05-15 12:10:56.118620 | ||
|
||
""" | ||
from alembic import op | ||
import sqlalchemy as sa | ||
from sqlalchemy.dialects import postgresql | ||
|
||
# revision identifiers, used by Alembic. | ||
revision = '485334f16c23' | ||
down_revision = 'ec64a8fd8cf3' | ||
branch_labels = None | ||
depends_on = None | ||
|
||
|
||
def upgrade() -> None: | ||
# ### commands auto generated by Alembic - please adjust! ### | ||
op.create_table('reports', | ||
sa.Column('exposure_id', sa.BigInteger(), nullable=False), | ||
sa.Column('section_id', sa.Text(), nullable=False), | ||
sa.Column('start_time', sa.DateTime(), nullable=False), | ||
sa.Column('finish_time', sa.DateTime(), nullable=True), | ||
sa.Column('success', sa.Boolean(), nullable=False), | ||
sa.Column('num_prev_reports', sa.Integer(), nullable=False), | ||
sa.Column('worker_id', sa.Text(), nullable=True), | ||
sa.Column('node_id', sa.Text(), nullable=True), | ||
sa.Column('cluster_id', sa.Text(), nullable=True), | ||
sa.Column('error_step', sa.Text(), nullable=True), | ||
sa.Column('error_type', sa.Text(), nullable=True), | ||
sa.Column('error_message', sa.Text(), nullable=True), | ||
sa.Column('warnings', sa.Text(), nullable=True), | ||
sa.Column('process_memory', postgresql.JSONB(astext_type=sa.Text()), nullable=False), | ||
sa.Column('process_runtime', postgresql.JSONB(astext_type=sa.Text()), nullable=False), | ||
sa.Column('progress_steps_bitflag', sa.BIGINT(), nullable=False), | ||
sa.Column('products_exist_bitflag', sa.BIGINT(), nullable=False), | ||
sa.Column('products_committed_bitflag', sa.BIGINT(), nullable=False), | ||
sa.Column('provenance_id', sa.String(), nullable=False), | ||
sa.Column('created_at', sa.DateTime(), nullable=False), | ||
sa.Column('modified', sa.DateTime(), nullable=False), | ||
sa.Column('id', sa.BigInteger(), autoincrement=True, nullable=False), | ||
sa.ForeignKeyConstraint(['exposure_id'], ['exposures.id'], name='reports_exposure_id_fkey', ondelete='CASCADE'), | ||
sa.ForeignKeyConstraint(['provenance_id'], ['provenances.id'], name='images_provenance_id_fkey', ondelete='CASCADE'), | ||
sa.PrimaryKeyConstraint('id') | ||
) | ||
op.create_index(op.f('ix_reports_created_at'), 'reports', ['created_at'], unique=False) | ||
op.create_index(op.f('ix_reports_exposure_id'), 'reports', ['exposure_id'], unique=False) | ||
op.create_index(op.f('ix_reports_finish_time'), 'reports', ['finish_time'], unique=False) | ||
op.create_index(op.f('ix_reports_id'), 'reports', ['id'], unique=False) | ||
op.create_index(op.f('ix_reports_products_committed_bitflag'), 'reports', ['products_committed_bitflag'], unique=False) | ||
op.create_index(op.f('ix_reports_products_exist_bitflag'), 'reports', ['products_exist_bitflag'], unique=False) | ||
op.create_index(op.f('ix_reports_progress_steps_bitflag'), 'reports', ['progress_steps_bitflag'], unique=False) | ||
op.create_index(op.f('ix_reports_provenance_id'), 'reports', ['provenance_id'], unique=False) | ||
op.create_index(op.f('ix_reports_section_id'), 'reports', ['section_id'], unique=False) | ||
op.create_index(op.f('ix_reports_start_time'), 'reports', ['start_time'], unique=False) | ||
op.create_index(op.f('ix_reports_success'), 'reports', ['success'], unique=False) | ||
# ### end Alembic commands ### | ||
|
||
|
||
def downgrade() -> None: | ||
# ### commands auto generated by Alembic - please adjust! ### | ||
op.drop_index(op.f('ix_reports_success'), table_name='reports') | ||
op.drop_index(op.f('ix_reports_start_time'), table_name='reports') | ||
op.drop_index(op.f('ix_reports_section_id'), table_name='reports') | ||
op.drop_index(op.f('ix_reports_provenance_id'), table_name='reports') | ||
op.drop_index(op.f('ix_reports_progress_steps_bitflag'), table_name='reports') | ||
op.drop_index(op.f('ix_reports_products_exist_bitflag'), table_name='reports') | ||
op.drop_index(op.f('ix_reports_products_committed_bitflag'), table_name='reports') | ||
op.drop_index(op.f('ix_reports_id'), table_name='reports') | ||
op.drop_index(op.f('ix_reports_finish_time'), table_name='reports') | ||
op.drop_index(op.f('ix_reports_exposure_id'), table_name='reports') | ||
op.drop_index(op.f('ix_reports_created_at'), table_name='reports') | ||
op.drop_table('reports') | ||
# ### end Alembic commands ### |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
"""reference instrument | ||
|
||
Revision ID: 9a4097979249 | ||
Revises: 485334f16c23 | ||
Create Date: 2024-05-22 11:22:20.322800 | ||
|
||
""" | ||
from alembic import op | ||
import sqlalchemy as sa | ||
|
||
|
||
# revision identifiers, used by Alembic. | ||
revision = '9a4097979249' | ||
down_revision = '485334f16c23' | ||
branch_labels = None | ||
depends_on = None | ||
|
||
|
||
def upgrade() -> None: | ||
# ### commands auto generated by Alembic - please adjust! ### | ||
op.add_column('refs', sa.Column('instrument', sa.Text(), nullable=False)) | ||
op.create_index(op.f('ix_refs_instrument'), 'refs', ['instrument'], unique=False) | ||
# ### end Alembic commands ### | ||
|
||
|
||
def downgrade() -> None: | ||
# ### commands auto generated by Alembic - please adjust! ### | ||
op.drop_index(op.f('ix_refs_instrument'), table_name='refs') | ||
op.drop_column('refs', 'instrument') | ||
# ### end Alembic commands ### |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -320,7 +320,7 @@ def string_to_bitflag(value, dictionary): | |
original_keyword = keyword | ||
keyword = EnumConverter.c(keyword) | ||
if keyword not in dictionary: | ||
raise ValueError(f'Keyword "{original_keyword}" not recognized in dictionary') | ||
raise ValueError(f'Keyword "{original_keyword.strip()}" not recognized in dictionary') | ||
output += 2 ** dictionary[keyword] | ||
return output | ||
|
||
|
@@ -409,3 +409,36 @@ class BitFlagConverter( EnumConverter ): | |
_allowed_values = flag_image_bits | ||
_dict_filtered = None | ||
_dict_inverse = None | ||
|
||
|
||
# the list of possible processing steps from a section of an exposure up to measurments, r/b scores, and report | ||
process_steps_dict = { | ||
1: 'preprocessing', # creates an Image from a section of the Exposure | ||
2: 'extraction', # creates a SourceList from an Image, and a PSF | ||
3: 'astro_cal', # creates a WorldCoordinates from a SourceList | ||
4: 'photo_cal', # creates a ZeroPoint from a WorldCoordinates | ||
5: 'subtraction', # creates a subtraction Image | ||
6: 'detection', # creates a SourceList from a subtraction Image | ||
7: 'cutting', # creates Cutouts from a subtraction Image | ||
8: 'measuring', # creates Measurements from Cutouts | ||
# TODO: add R/B scores and maybe an extra step for finalizing a report | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That extra step in the TODO would also include alert production. (My plan is not to save the full alert text, because we can reconstruct them from what's already in the database. What's more, we'll probably have something like kowalski running which will itself be saving all the alert text.) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (I view alerts as transitory things (as the name suggests), but I have heard a lot of people talk about alerts as if they are a database.) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah we've had this discussion lately. I think users expect to be able to search through alerts on a database, it is just not clear who will be managing it. I don't think it will cost us much to have an alerts database since we already keep all the data on the objects and measurements, and the alerts will just point to those objects. |
||
} | ||
process_steps_inverse = {EnumConverter.c(v): k for k, v in process_steps_dict.items()} | ||
|
||
|
||
# the list of objects that could be loaded to a datastore after running the pipeline | ||
pipeline_products_dict = { | ||
1: 'image', | ||
2: 'sources', | ||
3: 'psf', | ||
# 4: 'background', # not yet implemented | ||
5: 'wcs', | ||
6: 'zp', | ||
7: 'sub_image', | ||
8: 'detections', | ||
9: 'cutouts', | ||
10: 'measurements', | ||
# 11: 'rb_scores', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should ref_image be in here too? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think so. I was thinking about this list as a progress bar that fills up with things made by the pipeline. The reference would be a fixture that is needed before you even start. |
||
} | ||
|
||
pipeline_products_inverse = {EnumConverter.c(v): k for k, v in pipeline_products_dict.items()} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the error, perhaps we don't want to strip the spaces, just in case it's spurious leading/trailing spaces that are the problem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah that's what I was thinking but we also remove all spaces (leading or otherwise) in the
convert
method. So this is actually going to lead you down the wrong path if you leave the spaces (as it did for me).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see the
.strip()
inconvert
. (I looked for it before making this comment.) What am I missing?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a
replace(' ', '')
command in thec
function.