def test_start_new_accounts_when_stealing_enabled(db, default_account):
    default_account.sync_host = None
    db.session.commit()
    ss = SyncService(cpu_id=1, total_cpus=2)
    assert ss.accounts_to_start() == [1]
    db.session.expire_all()
    assert default_account.sync_host == platform.node()
def test_concurrent_syncs(db, default_account, config):
    ss1 = SyncService(cpu_id=1, total_cpus=2)
    ss2 = SyncService(cpu_id=1, total_cpus=2)
    ss2.host = 'other-host'
    # Check that only one SyncService instance claims the account.
    assert ss1.accounts_to_start() == [1]
    assert ss2.accounts_to_start() == []
def patched_sync_service(mock_queue_client, host=host, cpu_id=0):
    s = SyncService(process_identifier='{}:{}'.format(host, cpu_id),
                    cpu_id=cpu_id)
    s.queue_client = mock_queue_client
    s.start_sync = mock.Mock(
        side_effect=lambda aid: s.syncing_accounts.add(aid))
    return s
def patched_sync_service(mock_queue_client, host=host, cpu_id=0):
    s = SyncService(process_identifier='{}:{}'.format(host, cpu_id),
                    cpu_id=cpu_id)
    s.queue_client = mock_queue_client
    s.start_sync = mock.Mock(
        side_effect=lambda aid: s.syncing_accounts.add(aid))
    return s
Exemple #5
0
def test_start_new_accounts_when_stealing_enabled(db, default_account):
    default_account.sync_host = None
    db.session.commit()
    ss = SyncService(cpu_id=1, total_cpus=2)
    assert ss.accounts_to_start() == [1]
    db.session.expire_all()
    assert default_account.sync_host == platform.node()
def test_concurrent_syncs(db, default_account, config):
    purge_other_accounts(default_account)
    ss1 = SyncService(cpu_id=default_account.id % 2, total_cpus=2)
    ss2 = SyncService(cpu_id=default_account.id % 2, total_cpus=2)
    ss2.host = "other-host"
    # Check that only one SyncService instance claims the account.
    assert ss1.accounts_to_start() == [default_account.id]
    assert ss2.accounts_to_start() == []
Exemple #7
0
def test_dont_start_new_accounts_when_stealing_disabled(
        db, config, default_account):
    default_account.sync_host = None
    db.session.commit()
    config['SYNC_STEAL_ACCOUNTS'] = False
    ss = SyncService(cpu_id=1, total_cpus=2)
    assert ss.accounts_to_start() == []
    assert default_account.sync_host is None
def test_dont_start_new_accounts_when_stealing_disabled(db, config, default_account):
    purge_other_accounts(default_account)
    default_account.sync_host = None
    db.session.commit()
    config["SYNC_STEAL_ACCOUNTS"] = False
    ss = SyncService(cpu_id=default_account.id % 2, total_cpus=2)
    assert ss.accounts_to_start() == []
    assert default_account.sync_host is None
def patched_sync_service(db, host=host, process_number=0):
    s = SyncService(process_identifier="{}:{}".format(host, process_number), process_number=process_number)

    def start_sync(aid):
        acc = db.session.query(Account).get(aid)
        acc.sync_host = s.process_identifier
        acc.sync_started()
        s.syncing_accounts.add(aid)
        db.session.commit()
        return True

    s.start_sync = mock.Mock(side_effect=start_sync)
    return s
def test_dont_start_disabled_accounts(db, config, default_account):
    purge_other_accounts(default_account)
    config['SYNC_STEAL_ACCOUNTS'] = True
    default_account.sync_host = None
    default_account.disable_sync(reason='testing')
    db.session.commit()
    ss = SyncService(cpu_id=0, total_cpus=1)
    assert ss.accounts_to_start() == []
    assert default_account.sync_host is None
    assert default_account.sync_should_run is False

    default_account.sync_host = platform.node()
    default_account.disable_sync('testing')
    db.session.commit()
    ss = SyncService(cpu_id=0, total_cpus=1)
    assert ss.accounts_to_start() == []
    assert default_account.sync_should_run is False

    # Invalid Credentials
    default_account.mark_invalid()
    default_account.sync_host = None
    db.session.commit()

    # Don't steal invalid accounts
    ss = SyncService(cpu_id=0, total_cpus=1)
    assert ss.accounts_to_start() == []

    # Don't explicitly start invalid accounts
    default_account.sync_host = platform.node()
    db.session.commit()
    ss = SyncService(cpu_id=0, total_cpus=1)
    assert ss.accounts_to_start() == []
def patched_sync_service(db, mock_queue_client, host=host, cpu_id=0):
    s = SyncService(process_identifier='{}:{}'.format(host, cpu_id),
                    cpu_id=cpu_id)
    s.queue_client = mock_queue_client

    def start_sync(aid):
        acc = db.session.query(Account).get(aid)
        acc.sync_host = s.process_identifier
        acc.sync_started()
        s.syncing_accounts.add(aid)
        db.session.commit()

    s.start_sync = mock.Mock(side_effect=start_sync)
    return s
Exemple #12
0
def patched_sync_service(db, mock_queue_client, host=host, process_number=0):
    s = SyncService(process_identifier='{}:{}'.format(host, process_number),
                    process_number=process_number)
    s.queue_client = mock_queue_client

    def start_sync(aid):
        acc = db.session.query(Account).get(aid)
        acc.sync_host = s.process_identifier
        acc.sync_started()
        s.syncing_accounts.add(aid)
        db.session.commit()

    s.start_sync = mock.Mock(side_effect=start_sync)
    return s
Exemple #13
0
def test_concurrent_syncs(db, default_account, config):
    ss1 = SyncService(cpu_id=1, total_cpus=2)
    ss2 = SyncService(cpu_id=1, total_cpus=2)
    ss2.host = 'other-host'
    # Check that only one SyncService instance claims the account.
    assert ss1.accounts_to_start() == [1]
    assert ss2.accounts_to_start() == []
def test_sync_transitions(db, default_account, config):
    purge_other_accounts(default_account)
    ss = SyncService(cpu_id=default_account.id % 2, total_cpus=2)
    default_account.enable_sync()
    db.session.commit()
    assert ss.accounts_to_start() == [default_account.id]

    default_account.disable_sync("manual")
    db.session.commit()
    assert ss.accounts_to_start() == []
    assert default_account.sync_should_run is False
    assert default_account._sync_status["sync_disabled_reason"] == "manual"

    default_account.mark_invalid()
    db.session.commit()
    assert ss.accounts_to_start() == []
    assert default_account.sync_state == "invalid"
    assert default_account._sync_status["sync_disabled_reason"] == "invalid credentials"
    assert default_account.sync_should_run is False
def test_sync_transitions(db, default_account, config):
    ss = SyncService(cpu_id=1, total_cpus=2)
    default_account.enable_sync()
    db.session.commit()
    assert ss.accounts_to_start() == [1]

    default_account.disable_sync('manual')
    db.session.commit()
    assert ss.accounts_to_start() == []
    assert default_account.sync_should_run is False
    assert default_account._sync_status['sync_disabled_reason'] == 'manual'

    default_account.mark_invalid()
    db.session.commit()
    assert ss.accounts_to_start() == []
    assert default_account.sync_state == 'invalid'
    assert default_account._sync_status['sync_disabled_reason'] == \
        'invalid credentials'
    assert default_account.sync_should_run is False
Exemple #16
0
def test_sync_transitions(db, default_account, config):
    ss = SyncService(cpu_id=1, total_cpus=2)
    default_account.enable_sync()
    db.session.commit()
    assert ss.accounts_to_start() == [1]

    default_account.disable_sync('manual')
    db.session.commit()
    assert ss.accounts_to_start() == []
    assert default_account.sync_should_run is False
    assert default_account._sync_status['sync_disabled_reason'] == 'manual'

    default_account.mark_invalid()
    db.session.commit()
    assert ss.accounts_to_start() == []
    assert default_account.sync_state == 'invalid'
    assert default_account._sync_status['sync_disabled_reason'] == \
        'invalid credentials'
    assert default_account.sync_should_run is False
def test_stealing_limited_by_host(db, config):
    host = platform.node()
    config['DATABASE_HOSTS'][0]['SHARDS'][0]['SYNC_HOSTS'] = [host]
    config['DATABASE_HOSTS'][0]['SHARDS'][1]['SYNC_HOSTS'] = ['otherhost']
    purge_other_accounts()
    ss = SyncService(cpu_id=0, total_cpus=1)
    for key in (0, 1):
        with session_scope_by_shard_id(key) as db_session:
            acc = Account()
            acc.namespace = Namespace()
            db_session.add(acc)
            db_session.commit()

    ss.accounts_to_start()
    with session_scope_by_shard_id(0) as db_session:
        acc = db_session.query(Account).first()
        assert acc.sync_host == host
    with session_scope_by_shard_id(1) as db_session:
        acc = db_session.query(Account).first()
        assert acc.sync_host is None
def test_stealing_limited_by_host(db, config):
    host = platform.node()
    config['DATABASE_HOSTS'][0]['SHARDS'][0]['SYNC_HOSTS'] = [host]
    config['DATABASE_HOSTS'][0]['SHARDS'][1]['SYNC_HOSTS'] = ['otherhost']
    purge_other_accounts()
    ss = SyncService(cpu_id=0, total_cpus=1)
    for key in (0, 1):
        with session_scope_by_shard_id(key) as db_session:
            acc = Account()
            acc.namespace = Namespace()
            db_session.add(acc)
            db_session.commit()

    ss.accounts_to_start()
    with session_scope_by_shard_id(0) as db_session:
        acc = db_session.query(Account).first()
        assert acc.sync_host == host
    with session_scope_by_shard_id(1) as db_session:
        acc = db_session.query(Account).first()
        assert acc.sync_host is None
Exemple #19
0
def test_accounts_started_on_all_shards(db, default_account, config):
    config['SYNC_STEAL_ACCOUNTS'] = True
    purge_other_accounts(default_account)
    default_account.sync_host = None
    db.session.commit()
    ss = SyncService(cpu_id=0, total_cpus=1)
    ss.host = 'localhost'
    account_ids = {default_account.id}
    for key in (0, 1):
        with session_scope_by_shard_id(key) as db_session:
            acc = Account()
            acc.namespace = Namespace()
            db_session.add(acc)
            db_session.commit()
            account_ids.add(acc.id)

    assert len(account_ids) == 3
    assert set(ss.accounts_to_start()) == account_ids
    for id_ in account_ids:
        with session_scope(id_) as db_session:
            acc = db_session.query(Account).get(id_)
            assert acc.sync_host == 'localhost'
def test_accounts_started_on_all_shards(db, default_account, config):
    config['SYNC_STEAL_ACCOUNTS'] = True
    purge_other_accounts(default_account)
    default_account.sync_host = None
    db.session.commit()
    ss = SyncService(cpu_id=0, total_cpus=1)
    ss.host = 'localhost'
    account_ids = {default_account.id}
    for key in (0, 1):
        with session_scope_by_shard_id(key) as db_session:
            acc = Account()
            acc.namespace = Namespace()
            db_session.add(acc)
            db_session.commit()
            account_ids.add(acc.id)

    assert len(account_ids) == 3
    assert set(ss.accounts_to_start()) == account_ids
    for id_ in account_ids:
        with session_scope(id_) as db_session:
            acc = db_session.query(Account).get(id_)
            assert acc.sync_host == 'localhost'
def test_start_already_assigned_accounts(db, default_account):
    purge_other_accounts(default_account)
    default_account.sync_host = platform.node()
    ss = SyncService(cpu_id=default_account.id % 2, total_cpus=2)
    assert ss.accounts_to_start() == [default_account.id]
def test_start_already_assigned_accounts(db, default_account):
    default_account.sync_host = platform.node()
    ss = SyncService(cpu_id=1, total_cpus=2)
    assert ss.accounts_to_start() == [1]
def test_sync_start(db, default_account, config):

    # Make sure having fqdn set locally gets assigned to us
    ss = SyncService(cpu_id=0, total_cpus=1)
    assert ss._get_local_accounts() == [1]

    # Not from other cpus
    ss = SyncService(cpu_id=1, total_cpus=1)
    assert ss._get_local_accounts() == []

    # Different host
    default_account.sync_host = "some-random-host"
    db.session.commit()
    ss = SyncService(cpu_id=0, total_cpus=1)
    assert ss._get_local_accounts() == []

    # Explicit
    default_account.sync_host = platform.node()
    db.session.commit()
    assert ss._get_local_accounts() == [1]

    default_account.sync_host = None
    db.session.commit()

    # No host, work stealing enabled
    config['SYNC_STEAL_ACCOUNTS'] = True
    ss = SyncService(cpu_id=0, total_cpus=1)
    assert ss._get_local_accounts() == [1]

    # No host, no work stealing disabled
    config['SYNC_STEAL_ACCOUNTS'] = False
    ss = SyncService(cpu_id=0, total_cpus=1)
    assert ss._get_local_accounts() == []

    default_account.sync_state = 'stopped'

    # Stopped
    default_account.sync_host = None
    db.session.commit()

    # Don't steal stopped accounts
    config['SYNC_STEAL_ACCOUNTS'] = True
    ss = SyncService(cpu_id=0, total_cpus=1)
    assert ss._get_local_accounts() == []

    # Don't explicitly start stopped accounts
    default_account.sync_host = platform.node()
    db.session.commit()
    ss = SyncService(cpu_id=0, total_cpus=1)
    assert ss._get_local_accounts() == []

    # Invalid Credentials
    default_account.sync_state = 'invalid'
    db.session.commit()

    # Don't steal invalid accounts
    config['SYNC_STEAL_ACCOUNTS'] = True
    ss = SyncService(cpu_id=0, total_cpus=1)
    assert ss._get_local_accounts() == []

    # Don't explicitly start invalid accounts
    default_account.sync_host = platform.node()
    db.session.commit()
    ss = SyncService(cpu_id=0, total_cpus=1)
    assert ss._get_local_accounts() == []
Exemple #24
0
def test_dont_start_disabled_accounts(db, config, default_account):
    purge_other_accounts(default_account)
    config['SYNC_STEAL_ACCOUNTS'] = True
    default_account.sync_host = None
    default_account.disable_sync(reason='testing')
    db.session.commit()
    ss = SyncService(cpu_id=0, total_cpus=1)
    assert ss.accounts_to_start() == []
    assert default_account.sync_host is None
    assert default_account.sync_should_run is False

    default_account.sync_host = platform.node()
    default_account.disable_sync('testing')
    db.session.commit()
    ss = SyncService(cpu_id=0, total_cpus=1)
    assert ss.accounts_to_start() == []
    assert default_account.sync_should_run is False

    # Invalid Credentials
    default_account.mark_invalid()
    default_account.sync_host = None
    db.session.commit()

    # Don't steal invalid accounts
    ss = SyncService(cpu_id=0, total_cpus=1)
    assert ss.accounts_to_start() == []

    # Don't explicitly start invalid accounts
    default_account.sync_host = platform.node()
    db.session.commit()
    ss = SyncService(cpu_id=0, total_cpus=1)
    assert ss.accounts_to_start() == []
Exemple #25
0
def test_dont_start_accounts_on_other_host(db, default_account):
    purge_other_accounts(default_account)
    default_account.sync_host = 'other-host'
    db.session.commit()
    ss = SyncService(cpu_id=1, total_cpus=2)
    assert ss.accounts_to_start() == []
Exemple #26
0
def test_dont_start_accounts_for_other_cpus(db, default_account):
    purge_other_accounts(default_account)
    default_account.sync_host = platform.node()
    ss = SyncService(cpu_id=default_account.id + 1, total_cpus=2**22)
    assert ss.accounts_to_start() == []
Exemple #27
0
def test_start_already_assigned_accounts(db, default_account):
    purge_other_accounts(default_account)
    default_account.sync_host = platform.node()
    ss = SyncService(cpu_id=default_account.id % 2, total_cpus=2)
    assert ss.accounts_to_start() == [default_account.id]
Exemple #28
0
def test_start_already_assigned_accounts(db, default_account):
    default_account.sync_host = platform.node()
    ss = SyncService(cpu_id=1, total_cpus=2)
    assert ss.accounts_to_start() == [1]
Exemple #29
0
def main(prod, enable_tracer, enable_profiler, config, process_num,
         exit_after):
    """ Launch the Nylas sync service. """
    level = os.environ.get("LOGLEVEL", inbox_config.get("LOGLEVEL"))
    configure_logging(log_level=level)
    reconfigure_logging()

    maybe_enable_rollbar()

    if config is not None:
        from inbox.util.startup import load_overrides

        config_path = os.path.abspath(config)
        load_overrides(config_path)

    if not prod:
        preflight()

    total_processes = int(os.environ.get("MAILSYNC_PROCESSES", 1))

    setproctitle.setproctitle("sync-engine-{}".format(process_num))

    log = get_logger()
    log.info(
        "start",
        components=["mail sync", "contact sync", "calendar sync"],
        host=platform.node(),
        process_num=process_num,
        total_processes=total_processes,
        recursion_limit=sys.getrecursionlimit(),
    )

    print(banner, file=sys.stderr)
    print(file=sys.stderr)
    print("Python", sys.version, file=sys.stderr)

    if enable_profiler:
        inbox_config["DEBUG_PROFILING_ON"] = True

    port = 16384 + process_num
    enable_profiler_api = inbox_config.get("DEBUG_PROFILING_ON")

    process_identifier = "{}:{}".format(platform.node(), process_num)

    if exit_after:
        exit_after = exit_after.split(":")
        exit_after_min, exit_after_max = int(exit_after[0]), int(exit_after[1])
    else:
        exit_after_min, exit_after_max = None, None

    sync_service = SyncService(
        process_identifier,
        process_num,
        exit_after_min=exit_after_min,
        exit_after_max=exit_after_max,
    )
    signal.signal(signal.SIGTERM, sync_service.stop)
    signal.signal(signal.SIGINT, sync_service.stop)
    http_frontend = SyncHTTPFrontend(sync_service, port, enable_tracer,
                                     enable_profiler_api)
    sync_service.register_pending_avgs_provider(http_frontend)
    http_frontend.start()

    sync_service.run()

    print("\033[94mNylas Sync Engine exiting...\033[0m", file=sys.stderr)
def test_dont_start_accounts_on_other_host(db, default_account):
    purge_other_accounts(default_account)
    default_account.sync_host = 'other-host'
    db.session.commit()
    ss = SyncService(cpu_id=1, total_cpus=2)
    assert ss.accounts_to_start() == []
def test_dont_start_accounts_for_other_cpus(db, default_account):
    purge_other_accounts(default_account)
    default_account.sync_host = platform.node()
    ss = SyncService(cpu_id=default_account.id + 1, total_cpus=2**22)
    assert ss.accounts_to_start() == []