Skip to content
Snippets Groups Projects
tasks_queue.py 4.36 KiB
Newer Older
  • Learn to ignore specific revisions
  • # ##### BEGIN GPL LICENSE BLOCK #####
    #
    #  This program is free software; you can redistribute it and/or
    #  modify it under the terms of the GNU General Public License
    #  as published by the Free Software Foundation; either version 2
    #  of the License, or (at your option) any later version.
    #
    #  This program is distributed in the hope that it will be useful,
    #  but WITHOUT ANY WARRANTY; without even the implied warranty of
    #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    #  GNU General Public License for more details.
    #
    #  You should have received a copy of the GNU General Public License
    #  along with this program; if not, write to the Free Software Foundation,
    #  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
    #
    # ##### END GPL LICENSE BLOCK #####
    
    
    
    Vilém Duha's avatar
    Vilém Duha committed
    from blenderkit import utils
    
    from bpy.app.handlers import persistent
    
    import logging
    bk_logger = logging.getLogger('blenderkit')
    
    @persistent
    def scene_load(context):
    
        user_preferences = bpy.context.preferences.addons['blenderkit'].preferences
        if user_preferences.use_timers:
            if not (bpy.app.timers.is_registered(queue_worker)):
                bpy.app.timers.register(queue_worker)
    
    Vilem Duha's avatar
    Vilem Duha committed
    def get_queue():
    
        # we pick just a random one of blender types, to try to get a persistent queue
        t = bpy.types.Scene
    
        if not hasattr(t, 'task_queue'):
            t.task_queue = queue.Queue()
        return t.task_queue
    
    Vilem Duha's avatar
    Vilem Duha committed
    
    
        def __init__(self, command = '', arguments = (), wait = 0, only_last = False, fake_context = False, fake_context_area = 'VIEW_3D'):
    
            self.command = command
            self.arguments = arguments
            self.wait = wait
    
            self.only_last = only_last
    
            self.fake_context = fake_context
    
            self.fake_context_area = fake_context_area
    
    def add_task(task, wait = 0, only_last = False, fake_context = False, fake_context_area = 'VIEW_3D'):
    
    Vilem Duha's avatar
    Vilem Duha committed
        q = get_queue()
    
        taskob = task_object(task[0],task[1], wait = wait, only_last = only_last, fake_context = fake_context, fake_context_area = fake_context_area)
    
    def queue_worker():
    
        #bk_logger.debug('timer queue worker')
    
    Vilem Duha's avatar
    Vilem Duha committed
        q = get_queue()
    
    
        back_to_queue = [] #delayed events
    
        stashed = {}
        # first round we get all tasks that are supposed to be stashed and run only once (only_last option)
        # stashing finds tasks with the property only_last and same command and executes only the last one.
        while not q.empty():
    
    Vilém Duha's avatar
    Vilém Duha committed
            # print('queue while 1')
    
    
            task = q.get()
            if task.only_last:
    
    Vilém Duha's avatar
    Vilém Duha committed
                #this now makes the keys not only by task, but also first argument.
                # by now stashing is only used for ratings, where the first argument is url.
                # This enables fast rating of multiple assets while allowing larger delay for uploading of ratings.
                # this avoids a duplicate request error on the server
                stashed[str(task.command)+str(task.arguments[0])] = task
    
            else:
                back_to_queue.append(task)
    
    Vilém Duha's avatar
    Vilém Duha committed
        if len(stashed.keys())>1:
    
            bk_logger.debug('task queue stashed task:' +str(stashed))
    
        #return tasks to que except for stashed
        for task in back_to_queue:
            q.put(task)
        #return stashed tasks to queue
        for k in stashed.keys():
            q.put(stashed[k])
        #second round, execute or put back waiting tasks.
        back_to_queue = []
    
    Vilem Duha's avatar
    Vilem Duha committed
        while not q.empty():
    
            # print('window manager', bpy.context.window_manager)
    
    Vilem Duha's avatar
    Vilem Duha committed
            task = q.get()
    
    
            if task.wait>0:
                task.wait-=time_step
                back_to_queue.append(task)
            else:
    
                bk_logger.debug('task queue task:'+ str( task.command) +str( task.arguments))
    
                    if task.fake_context:
    
                        fc = utils.get_fake_context(bpy.context, area_type = task.fake_context_area)
    
                        task.command(fc,*task.arguments)
                    else:
                        task.command(*task.arguments)
    
                    bk_logger.error('task queue failed task:'+ str(task.command)+str(task.arguments)+ str(e))
                    # bk_logger.exception('Got exception on main handler')
                    # raise
    
    Vilém Duha's avatar
    Vilém Duha committed
            # print('queue while 2')
    
        for task in back_to_queue:
            q.put(task)
    
    Vilem Duha's avatar
    Vilem Duha committed
    
    
        bpy.app.handlers.load_post.append(scene_load)
    
    
        bpy.app.handlers.load_post.remove(scene_load)