Фоновые задачи на Механизме Приложения

Вы можете использовать агрегацию:

select book,
       (case when min(genre) = max(genre) then max(genre)
             else 'mixed genres'
        end) as genre
from t
group by book;

Вы также можете перечислить все жанры:

select book, group_concat(genre) as genre
from t
group by book;
5
задан Ryan A. 5 April 2018 в 17:34
поделиться

3 ответа

И ближайшая версия времени выполнения будет иметь некоторый периодический механизм выполнения a'la кроном. См. это сообщение на группе AppEngine.

Так, все части SDK, кажется, работают, но мое тестирование указывает, что это еще не работает на рабочих серверах - я настроил "каждый 1 минуты" крон, который регистрируется, когда это работает, и это еще не назвали

Трудно для высказывания, когда это будет доступно, хотя...

2
ответ дан 18 December 2019 в 07:32
поделиться

GAE является очень полезным инструментом для создания масштабируемых веб-приложений. Немногие ограничения, на которые многие указывают, не являются никакой поддержкой фоновых задач, отсутствия периодических задач и строгого предела на то, сколько времени каждый Запрос HTTP берет, если запрос превышает то ограничение по времени, операция завершается, который делает задачи потребления времени выполнения невозможными.

Как выполнить фоновую задачу?
В GAE код выполнен только, когда существует Запрос HTTP. Существует строгое ограничение по времени (я думаю 10secs) на том, сколько времени код может взять. Таким образом, при отсутствии запросов, затем кодируют, не выполняется. Одна из предложенной работы вокруг была использованием внешнее поле для отправления запросов непрерывно, так добрый из создания фоновой задачи. Но для этого нам нужны внешнее поле и теперь мы зависящий от еще одного элемента. Другая альтернатива отправляла 302 ответа перенаправления так, чтобы клиент снова послал запрос, это также делает нас зависящими от внешнего элемента, который является клиентом. Что, если то внешнее поле является самим GAE? Все, кто использовал функциональный язык, который не поддерживает конструкцию цикличного выполнения на языке, знают об альтернативе, т.е. рекурсия является заменой для цикличного выполнения. Таким образом, что, если мы завершаемся, часть вычисления и HTTP Входит в тот же URL с очень коротким временем, говорят 1 секунду? Это создает цикл (рекурсия) на коде php, работающем на апаче.

<?php
$i = 0;
if(isset($_REQUEST["i"])){
        $i= $_REQUEST["i"];
    sleep(1);
}
$ch = curl_init("http://localhost".$_SERVER["PHP_SELF"]."?i=".($i+1));
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_TIMEOUT, 1);
curl_exec($ch);
print "hello world\n";
?>

Некоторые, как это не работает над GAE. Таким образом, что, если мы, HTTP Входит в некоторый другой URL, говорят, что url2, который HTTP Входит в первый URL? Это, кажется, работает в GAE. Код для этого похож на это.

class FirstUrl(webapp.RequestHandler):
    def get(self):
        self.response.out.write("ok")
        time.sleep(2)
        urlfetch.fetch("http://"+self.request.headers["HOST"]+'/url2')

class SecondUrl(webapp.RequestHandler):
    def get(self):
        self.response.out.write("ok")
        time.sleep(2)
        urlfetch.fetch("http://"+self.request.headers["HOST"]+'/url1')

application = webapp.WSGIApplication([('/url1', FirstUrl), ('/url2', SecondUrl)])
def main():
    run_wsgi_app(application)
if __name__ == "__main__":
    main()

Так как мы узнали способ выполнить фоновую задачу, позволяет абстракциям сборки для периодической задачи (таймер) и конструкция цикличного выполнения, которая охватывает через многие Запросы HTTP (foreach).

Таймер
Теперь создание таймера является прямым. Основная идея состоит в том, чтобы иметь список таймеров и интервала, в котором каждого нужно назвать. После того как мы достигаем того вызова интервала функция обратного вызова. Мы будем использовать кэш-память для ведения списка таймера. Для обнаружения, когда назвать обратный вызов мы снабдим ключ в кэш-памяти интервалом как время истечения срока. Мы периодически (говорят 5secs), проверка, если тот ключ присутствует, если не существующий затем называют обратный вызов и снова устанавливают тот ключ с интервалом.

def timer(func, interval):
    timerlist = memcache.get('timer')
    if(None == timerlist):
        timerlist = []
    timerlist.append({'func':func, 'interval':interval})
    memcache.set('timer-'+func, '1', interval)
    memcache.set('timer', timerlist)

def checktimers():
    timerlist = memcache.get('timer')
    if(None == timerlist):
        return False
    for current in timerlist:
        if(None == memcache.get('timer-'+current['func'])):
            #reset interval
            memcache.set('timer-'+current['func'], '1', current['interval'])
            #invoke callback function
            try:
                eval(current['func']+'()')
            except:
                pass
            return True
    return False

Foreach
Это необходимо, когда мы хотим сделать долго, берущее вычисление говорит, что выполнение некоторой операции на 1 000 строк базы данных или выбирает 1 000 URL и т.д. Основная идея состоит в том, чтобы вести список обратных вызовов, и аргументы в кэш-памяти и каждый раз вызывают обратный вызов с аргументом.

def foreach(func, args):
    looplist = memcache.get('foreach')
    if(None == looplist):
        looplist = []
    looplist.append({'func':func, 'args':args})
    memcache.set('foreach', looplist)

def checkloops():
    looplist = memcache.get('foreach')
    if(None == looplist):
        return False
    if((len(looplist) > 0) and (len(looplist[0]['args']) > 0)):
        arg = looplist[0]['args'].pop(0)
        func = looplist[0]['func']
        if(len(looplist[0]['args']) == 0):
            looplist.pop(0)
        if((len(looplist) > 0) and (len(looplist[0]['args']) > 0)):
            memcache.set('foreach', looplist)
        else:
            memcache.delete('foreach')
        try:
            eval(func+'('+repr(arg)+')')
        except:
            pass
        return True
    else:
        return False

# instead of
# foreach index in range(0, 1000):
#   someoperaton(index)
# we will say
# foreach('someoperaton', range(0, 1000))

Теперь создание программы, которая выбирает список URL всех час, является прямым. Вот код.

def getone(url):
    try:
        result = urlfetch.fetch(url)
        if(result.status_code == 200):
            memcache.set(url, '1', 60*60)
            #process result.content
    except :
        pass

def getallurl():
    #list of urls to be fetched
    urllist = ['http://www.google.com/', 'http://www.cnn.com/', 'http://www.yahoo.com', 'http://news.google.com']
    fetchlist = []
    for url in urllist:
        if (memcache.get(url) is None):
            fetchlist.append(url)
    #this is equivalent to
    #for url in fetchlist: getone(url)
    if(len(fetchlist) > 0):
        foreach('getone', fetchlist)

#register the timer callback
timer('getallurl', 3*60)

полным кодом является здесь http://groups.google.com/group/httpmr-discuss/t/1648611a54c01aa, я выполнял этот код appengine в течение нескольких дней без большой проблемы.

Предупреждение: Мы делаем интенсивное использование urlfetch. Предел ни на какие из urlfetch в день 160000. Так бойтесь достигать того предела.

5
ответ дан 18 December 2019 в 07:32
поделиться

Вы можете использовать API очереди задач Python .

12
ответ дан 18 December 2019 в 07:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: