예제 #1
0
 def setup(self, config, full_sync=False):
     self.storage = StorageFactory.get(config.get('storage'))
     self.services = self.setup_services(config, self.storage)
     self.setup_copydog(config.get('copydog'))
     self.setup_last_time_read(full_sync)
     self.mapper = Mapper(storage=self.storage, services=self.services, config=config)
     self.mapper.save_list_status_mapping()
     self.mapper.save_user_member_mapping()
예제 #2
0
class Watch(object):
    available_services = {
        'redmine': RedmineAdapter,
        'trello': TrelloAdapter
    }

    def __init__(self, config=None, full_sync=None):
        log.info('Copydog is on duty...')
        if config:
            self.setup(config, full_sync)

    def setup(self, config, full_sync=False):
        self.storage = StorageFactory.get(config.get('storage'))
        self.services = self.setup_services(config, self.storage)
        self.setup_copydog(config.get('copydog'))
        self.setup_last_time_read(full_sync)
        self.mapper = Mapper(storage=self.storage, services=self.services, config=config)
        self.mapper.save_list_status_mapping()
        self.mapper.save_user_member_mapping()

    def setup_copydog(self, options=False):
        if not options:
            return
        pandoc.PANDOC_PATH = options.get('pandoc', '/usr/bin/pandoc')
        self.beat_interval = options.get('beat', 60)

    def setup_services(self, config, storage):
        clients_config = config.clients
        services = {}
        for service_name, options in clients_config:
            service_class = self.available_services[service_name]
            services[service_name] = service_class(options, storage)
        return services

    def setup_last_time_read(self, full_sync=False):
        """ Ignoring last time read, when using full_sync,
            If launching for first time, make sure we're monitoring only recent changes.

            TODO: remove hardcoded services
        """
        if full_sync:
            self.storage.reset_last_time_read()
        else:
            if not self.storage.get_last_time_read('redmine'):
                self.storage.mark_read('redmine')
                self.storage.mark_read('trello')

    def run(self):
        """ Run copydog in a loop, starting sync every N seconds (60 is default).
        """
        self.scheduler = sched.scheduler(time.time, time.sleep)
        periodic(self.scheduler, self.beat_interval, self.sync)
        self.scheduler.run()

    def sync(self):
        groups = itertools.groupby(itertools.permutations(self.services, 2), lambda pair:pair[0])
        for service_from_name, services in groups:
            service_from = self.services[service_from_name]
            issues = service_from.read()
            num_issues_read = 0
            services = list(services)
            for issue in issues:
                if self.is_already_synced(issue):
                    continue
                num_issues_read += 1
                service_from.mark_read(issue)
                for service_from_name, service_to_name in services:
                    service_to = self.services[service_to_name]
                    if service_to.writable:
                        service_to.write(issue)
            log.info('Read %s new issues from %s', num_issues_read, service_from)

    def is_already_synced(self, issue):
        """ Check issue needs sync

            Read from API last_updated > read from storage last_updated
            thus preventing clones
        """
        last_time_synced = self.storage.get_last_time_updated(issue.client.service_name, issue)
        log.debug('Comparing %s <= %s (%s)' % (issue.last_updated, last_time_synced,
            (last_time_synced and issue.last_updated <= last_time_synced)))
        return last_time_synced and issue.last_updated <= last_time_synced