def print_stats(self):
     stats = UnfinishedSubmissionStub.objects.all().values('domain')\
         .annotate(count=Count('domain')).order_by('count')
     writer = SimpleTableWriter(self.stdout, TableRowFormatter([50, 10]))
     writer.write_table(['Domain', '# Forms'], [
         (stat['domain'], stat['count']) for stat in stats
     ])
    def migrate_domain(self, domain):
        if should_use_sql_backend(domain):
            self.stderr.write("{} already on the SQL backend".format(domain))
            return True, None

        if couch_sql_migration_in_progress(domain, include_dry_runs=True):
            self.stderr.write(
                "{} migration is already in progress".format(domain))
            return False, "in progress"

        set_couch_sql_migration_started(domain)

        do_couch_to_sql_migration(domain, with_progress=False, debug=False)

        stats = self.get_diff_stats(domain)
        if stats:
            self.stderr.write(
                "Migration has diffs, aborting for domain {}".format(domain))
            self.abort(domain)
            writer = SimpleTableWriter(self.stdout,
                                       TableRowFormatter([50, 10, 10, 10, 10]))
            writer.write_table([
                'Doc Type', '# Couch', '# SQL', '# Diffs', '# Docs with Diffs'
            ], [(doc_type, ) + stat for doc_type, stat in stats.items()])
            return False, "has diffs"

        assert couch_sql_migration_in_progress(domain)
        set_couch_sql_migration_complete(domain)
        self.stdout.write(shell_green("Domain migrated: {}".format(domain)))
        return True, None
示例#3
0
    def migrate_domain(self, domain):
        if should_use_sql_backend(domain):
            log.error("{} already on the SQL backend\n".format(domain))
            return True, None

        if couch_sql_migration_in_progress(domain, include_dry_runs=True):
            log.error("{} migration is already in progress\n".format(domain))
            return False, "in progress"

        set_couch_sql_migration_started(domain)

        do_couch_to_sql_migration(domain, with_progress=False, debug=False)

        stats = self.get_diff_stats(domain)
        if stats:
            lines = ["Migration has diffs: {}".format(domain)]

            class stream:
                write = lines.append

            writer = SimpleTableWriter(stream, TableRowFormatter([30, 10, 10, 10, 10]))
            writer.write_table(
                ['Doc Type', '# Couch', '# SQL', '# Diffs', '# Docs with Diffs'],
                [(doc_type,) + stat for doc_type, stat in stats.items()],
            )
            log.error("\n".join(lines))
            self.abort(domain)
            return False, "has diffs"

        assert couch_sql_migration_in_progress(domain)
        set_couch_sql_migration_complete(domain)
        log.info("Domain migrated: {}\n".format(domain))
        return True, None
    def handle(self, domain, doc_type, **options):
        csv = options.get('csv')

        handlers = {
            'CommCareCase': _compare_cases,
            'CommCareCase-Deleted': _compare_cases,
            'CommCareUser': _compare_users,
            'CommCareUser-Deleted': _compare_users,
            'WebUser': _compare_users,
        }
        handlers.update(
            {doc_type: _compare_xforms
             for doc_type in doc_types()})
        try:
            primary_only, es_only = handlers[doc_type](domain, doc_type)
        except KeyError:
            raise CommandError('Unsupported doc type. Use on of: {}'.format(
                ', '.join(handlers)))

        if csv:
            row_formatter = CSVRowFormatter()
        else:
            row_formatter = TableRowFormatter([50, 50])

        writer = SimpleTableWriter(self.stdout, row_formatter)
        writer.write_table(['Only in Primary', 'Only in ES'],
                           izip_longest(primary_only, es_only, fillvalue=''))
示例#5
0
    def handle(self, domain, **options):
        csv = options.get('csv')

        couch_counts = map_counter_doc_types(_get_couchdb_counts(domain))
        sql_counts = map_counter_doc_types(_get_sql_counts(domain))
        es_counts = map_counter_doc_types(get_es_counts_by_doc_type(domain))
        all_doc_types = set(couch_counts) | set(sql_counts) | set(es_counts)

        output_rows = []
        for doc_type in sorted(all_doc_types, key=lambda d: d.lower()):
            couch = couch_counts.get(doc_type, '')
            sql = sql_counts.get(doc_type, '')
            es = es_counts.get(doc_type, '')
            output_rows.append((doc_type, couch, sql, es))

        if csv:
            row_formatter = CSVRowFormatter()
        else:
            row_formatter = TableRowFormatter(
                [50, 20, 20, 20],
                _get_row_color
            )

        SimpleTableWriter(self.stdout, row_formatter).write_table(
            ['Doc Type', 'Couch', 'SQL', 'ES'], output_rows
        )
示例#6
0
    def migrate_domain(self, domain):
        if should_use_sql_backend(domain):
            self.stderr.write("{} already on the SQL backend".format(domain))
            return

        set_couch_sql_migration_started(domain)

        with SignalHandlerContext([signal.SIGTERM, signal.SIGINT],
                                  _get_sigterm_handler(domain)):
            do_couch_to_sql_migration(domain, with_progress=False, debug=False)

        stats = self.get_diff_stats(domain)
        if stats:
            self.stderr.write(
                "Migration has diffs, aborting for domain {}".format(domain))
            self.abort(domain)
            writer = SimpleTableWriter(self.stdout,
                                       TableRowFormatter([50, 10, 10, 10, 10]))
            writer.write_table([
                'Doc Type', '# Couch', '# SQL', '# Diffs', '# Docs with Diffs'
            ], [(doc_type, ) + stat for doc_type, stat in stats.items()])
        else:
            assert couch_sql_migration_in_progress(domain)
            set_couch_sql_migration_complete(domain)
            self.stdout.write(shell_green(
                "Domain migrated: {}".format(domain)))
    def _print_table(self, headers, rows):
        if self.csv:
            row_formatter = CSVRowFormatter()
        else:
            row_formatter = TableRowFormatter([20] * len(headers), )

        SimpleTableWriter(self.stdout,
                          row_formatter).write_table(headers, rows)
        self.stdout.write('')
示例#8
0
    def handle(self, domain, doc_type, **options):
        csv = options.get('csv')
        startdate = options.get('start')
        enddate = options.get('end')

        form_doc_types = doc_types()

        if startdate or enddate:
            if doc_type in CASE_DOC_TYPES or doc_type in form_doc_types:
                if not should_use_sql_backend(domain):
                    raise CommandError(
                        "Date filtering not supported for Couch domains")

        if startdate and enddate and enddate <= startdate:
            raise CommandError("enddate must be after startdate")

        handlers = {
            'CommCareCase': compare_cases,
            'CommCareCase-Deleted': compare_cases,
            'CommCareUser': _compare_users,
            'CommCareUser-Deleted': _compare_users,
            'WebUser': _compare_users,
        }
        handlers.update(
            {doc_type: compare_xforms
             for doc_type in form_doc_types})
        try:
            primary_count, es_count, primary_only, es_only = handlers[
                doc_type](domain, doc_type, startdate, enddate)
        except KeyError:
            raise CommandError('Unsupported doc type. Use on of: {}'.format(
                ', '.join(handlers)))

        if csv:
            row_formatter = CSVRowFormatter()
        else:
            row_formatter = TableRowFormatter([50, 50])

        date_range_output = ''
        if startdate or enddate:
            end = (enddate or datetime.utcnow().date()).strftime(DATE_FORMAT)
            start = startdate.strftime(DATE_FORMAT)
            date_range_output = ' (Between {} and {})'.format(start, end)

        print("\nDoc ID analysis for {}{}\n".format(doc_type,
                                                    date_range_output))

        print("Primary Count: {}".format(primary_count))
        print("ES Count: {}\n".format(es_count))

        writer = SimpleTableWriter(self.stdout, row_formatter)
        writer.write_table(['Only in Primary', 'Only in ES'],
                           zip_longest(primary_only, es_only, fillvalue=''))
    def handle(self, **options):
        csv_mode = options['csv']

        form_info = _get_counts(FormReindexAccessor())
        case_info = _get_counts(CaseReindexAccessor())

        if csv_mode:
            row_formatter = CSVRowFormatter()
        else:
            row_formatter = TableRowFormatter([20, 20, 10])

        _write_info('FORMS', form_info, row_formatter, self.stdout)
        _write_info('CASES', case_info, row_formatter, self.stdout)
示例#10
0
def format_diff_stats(stats, header=None):
    lines = []
    if stats:
        if header:
            lines.append(header)

        class stream:
            write = lines.append

        writer = SimpleTableWriter(stream, TableRowFormatter([30, 10, 10, 10]))
        writer.write_table(
            ['Doc Type', '# Couch', '# SQL', '# Docs with Diffs'],
            [(doc_type,) + stat for doc_type, stat in stats.items()],
        )
    return "\n".join(lines)
示例#11
0
def format_diff_stats(stats, header=None):
    lines = []
    if stats:
        if header:
            lines.append(header)

        class stream:
            write = lines.append

        writer = SimpleTableWriter(stream, TableRowFormatter([30, 7, 7, 7, 7]))
        writer.write_table(
            ['Doc Type', 'Docs', 'Diffs', "Missing", "Changes"],
            [(doc_type, ) + stat.columns for doc_type, stat in stats.items()],
        )
    return "\n".join(lines)
示例#12
0
    def handle(self, domains, **options):
        csv = options.get('csv')

        if csv:
            row_formatter = CSVRowFormatter()
        else:
            dom_len = max(len(domain) for domain in domains) + 2
            row_formatter = TableRowFormatter([dom_len, 7, 50, 15, 15],
                                              _get_row_color)

        writer = SimpleTableWriter(self.stdout, row_formatter)
        writer.write_headers(
            ['Domain', 'Backend', 'Doc Type', 'Primary', 'ES'])
        for domain in domains:
            rows = get_doc_counts_for_domain(domain)
            writer.write_rows(((domain, 'sql') + row for row in rows))
    def handle(self, pillow_name, process_count, **options):
        all_pillows = get_all_pillow_instances()
        pillows = [
            pillow for pillow in all_pillows if pillow.pillow_id == pillow_name
        ]
        if not pillows:
            all_names = '\n\t'.join(
                [pillow.pillow_id for pillow in all_pillows])
            raise CommandError(
                f'No pillow found: {pillow_name}.\n\t{all_names}')

        pillow = pillows[0]
        change_feed = pillow.get_change_feed()
        if not isinstance(change_feed, KafkaChangeFeed):
            raise CommandError(f"Pillow '{pillow_name}' is not a Kafka pillow")

        topic_partitions = []
        for topic in change_feed.topics:
            for partition in change_feed.consumer.partitions_for_topic(topic):
                topic_partitions.append(TopicPartition(topic, partition))

        topic_partitions.sort()
        process_assignments = [
            topic_partitions[num::process_count]
            for num in range(process_count)
        ]

        if options['csv']:
            row_formatter = CSVRowFormatter()
        else:
            row_formatter = TableRowFormatter([len(pillow_name) + 4, 10])

        writer = SimpleTableWriter(self.stdout, row_formatter)
        writer.write_table(['Pillow Process', 'Kafka Topics'], [[
            f'{pillow_name}:{process_num}', ', '.join(
                [f'{tp.topic}-{tp.partition}' for tp in assignments])
        ] for process_num, assignments in enumerate(process_assignments)])