[1][y18.svg] [2]Hacker News [3]new | [4]past | [5]comments | [6]ask | [7]show | [8]jobs | [9]submit [10]login

[11]Why do we need Flask, Celery, and Redis? (2019) ([12]ljvmiranda921.github.io) 345 points by [13]feross [14]on April 18, 2020 | [15]hide | [16]past | [17]favorite | [18]181 comments [s.gif]

[19]sandGorgon [20]on April 18, 2020 | [21]next [22][–] I see a lot of comments that are talking about how python does not have a go-like concurrency story.

Fyi - python ASGI frameworks like fastapi/Starlette are the same developer experience as go. They also compete on techempower benchmarks. Also used in production by Uber, Microsoft,etc.

A queue based system is used for a very different tradeoff of persistence vs concurrency. It's similar to saying that the usecase for Kafka doesn't exist because go can do concurrency.

Running "python -m asyncio" launches a natively async REPL. [23]https://www.integralist.co.uk/posts/python-asyncio/#running-...

Go play with it ;)

[s.gif]

[24]pinkbeanz [25]on April 18, 2020 | [26]parent | [27]next [28][–] I think a hard part with lots of these “what do I use x for” examples is it starts with the tool and the discusses the problem that it solves. I find it more helpful to start with a problem, and discuss the various tools that address it, in different ways.

Forget email, say you have a app that scans links in comments for maliciousness. You rely on an internal api for checking against a known blacklist, which follows shortened links first, and an external api from a third party. You want the comment to appear to submit instantly to the poster but are comfortable waiting for it to appear for everyone else. What are your options?

You could certainly use message queues and workers. If you’re cloud native maybe you leverage lambdas. Maybe you spin up an independent service that does the processing and inserting into the database in the background, and all you need to do is send a simple HTTP request on an internal network.

Your solution depends on your throughout requirements, the size of your team and their engineering capabilities, what existing solutions you have in place. Everything has its pros and cons. Pretending that celery/redis is useless and would be solved if everyone just used Java ignores the fact that celery and redis are widely popular and drive many successful applications and use cases.

[s.gif]

[29]lmeyerov [30]on April 18, 2020 | [31]root | [32]parent | [33]next [34][–] We've been experimenting with nice compromises for using pydata on-the-fly compute with caching. Basic tension is indiv requests get blocked by their blocking APIs, while caches (eg, IP-pinned) are best when same-python-app-thread.

Right now, we do hypercorn multiproc -> per-proc quart/asyncio/aiohttp IP-pinned event loop -> Apache arrow in-app cache -> on-gpu rapids.ai cache.

But not happy w event loop due to pandas/rapids blocking if heavy datasets by concurrent users. (Taking us back to celery, redis, etc, which we don't want due to extra data movement..) Maybe we can get immutable arrow buffs shared across python proc threads..

Ideas welcome!

[s.gif]

[35]stavros [36]on April 18, 2020 | [37]root | [38]parent | [39]prev | [40]next [41][–] While I agree with the rest of your comment, the sentence "if you’re cloud native maybe you leverage lambdas" made me irrationally angry.

[s.gif]

[42]CalRobert [43]on April 18, 2020 | [44]root | [45]parent | [46]next [47][–] Can you explain why? I use lambdas often and they seem to solve the problems they're meant for well.

[s.gif]

[48]stavros [49]on April 18, 2020 | [50]root | [51]parent | [52]next [53][–] It wasn't the lambdas, it was the combination of "cloud-native", which is a very salesmany term, and "leverage", which is my pet hate word. It's exactly as useful as "use", only much more pretentious. I'm just easily triggered with language :P

More off-topic (or, rather, on-topic), I find lambdas great for things like a static website that needs a few functions. I especially like how Netlify uses them, they seem to fit that purpose exactly.

[s.gif]

[54]normalnorm [55]on April 19, 2020 | [56]root | [57]parent | [58]next [59][–] > I'm just easily triggered with language :P

Me too! It makes me irrationally angry when people regurgitate linguistic clichés. I was already mad with:

"python does not have a go-like concurrency story"

when it would be enough (and 1000x less cringe) to say:

"python does not have go-like concurrency"

I think these mindless clichés make language really ugly and dysfunctional, and even worse they are thought-stoppers, because they make the reader/listener feel like something smart is being said, because they recognize the "in-group" lingo. In my experience, people get really offended when you point this out. It's kind of an HN taboo to discuss this. Which is also interesting in itself.

Going forward we should pay more attention to our communication use cases. Btw: I wonder if we can stack several of these clichés. For example: "leverage" + "use case" = "leverage case".

[s.gif]

[60]stavros [61]on April 19, 2020 | [62]root | [63]parent | [64]next [65][–] I agree, I think Orwell's "Politics and the English Language" is spot on here. I try to use simpler language whenever possible, I agree that people think that using longer words makes them sound smart but is just worse for communication.

I've found it's a taboo to discuss anything even slightly personal. People are averse to feeling bad, so criticism needs to be extremely subtle in order to not offend.

> Btw: I wonder if we can stack several of these clichés. For example: "leverage" + "use case" = "leverage case".

I hate you for even thinking of this.

[s.gif]

[66]rumanator [67]on April 19, 2020 | [68]root | [69]parent | [70]next [71][–] > I've found it's a taboo to discuss anything even slightly personal. People are averse to feeling bad, so criticism needs to be extremely subtle in order to not offend.

The personal association you made between "discussing anything even slightly personal" and "criticism needs to be extremely subtled" makes it sound that your problem isn't language or Orwellian discourse but the way you subconsciously link discussing personal matters with harshly criticising those you speak with for no good reason.

If your personal conversations boil down to appease your own personal need to criticise others then I'm sorry to break it to you but your problem isn't language.

[s.gif]

[72]stavros [73]on April 19, 2020 | [74]root | [75]parent | [76]next [77][–] You just misconstrued my saying "personal" and clearly meaning "personal criticism" as meaning personal things in general and then criticized me on that straw man. I don't hold that opinion at all.

You also went to "Orwellian discourse", which has a specific meaning, from a text by Orwell I mentioned. It seems to me like you got personally offended, interpreted my comment in the most uncharitable way, and chose to lash out at me instead, and I'm not sure why. I wasn't even talking about anyone specifically.

[s.gif]

[78]rumanator [79]on April 19, 2020 | [80]root | [81]parent | [82]next [83][–] You were the one associating discussing remotely personal stuff with criticising others, and if that was not bad enough your personal take was that you felt the need to keep criticising others but resorting to subtlety just to keep shoveling criticism without sparking the reactions you're getting for doing the thing you want to do to others.

I repeat, your problem is not language. Your problem is that you manifest a need to criticize others. That problem is all on you.

[s.gif]

[84]heyoni [85]on April 20, 2020 | [86]root | [87]parent | [88]next [89][–] That is such quite a stretch of the imagination and I sure didn’t read it that way. I may be wrong but here’s one fun example from this comment section that I wanted to “respond” to and demand some clarification on.

[90]https://news.ycombinator.com/item?id=22911497

PS: I work with like 65-70% of that stack daily

[s.gif]

[91]stavros [92]on April 19, 2020 | [93]root | [94]parent | [95]prev | [96]next [97][–] Ah, okay. If I had said "any remotely personal criticism", like I meant, you'd have an entirely different conclusion, but I guess that doesn't matter when you just want to jump to conclusions.

This shows from the fact that you're saying "criticize" like it's a bad thing.

[s.gif]

[98]BiteCode_dev [99]on April 18, 2020 | [100]parent | [101]prev | [102]next [103][–] Besides, serious projects in Go do use additional tools for creating task queues because they need to handle various stages of persistence, error handling, serialization, workflow, etc. Which are not stuff you want to write by hand yourself.

If you don't need all that, then it's not a problem in Python either. You don't even need asyncio, you can just use a ThreadPool or a ProcessPool, dump stuff with pickle/shelve/sqlite3 and be on your way.

[s.gif]

[104]arp242 [105]on April 18, 2020 | [106]parent | [107]prev | [108]next [109][–] I was using gevent in Python about 10 years ago, and from memory, it's roughly similar to goroutines. It's not exactly the same of course, but just like goroutines it's pretty easy to just spawn a few jobs off, wait for them to finish, and get the results.

It's not in the standard library, and there are probably other options too now (not a heavy Python user any more), but Python has had easy parallelism for at least a decade (probably longer).

[s.gif]

[110]slashdev [111]on April 18, 2020 | [112]root | [113]parent | [114]next [115][–] Gevent is like goroutines with GOMAXPROCS=1. Which is to say not nearly as useful. It gives you concurrency without parrallelism, because Python never did shake the GIL. Which goes to show some technical debt will haunt you forever.

[s.gif]

[116]sandGorgon [117]on April 18, 2020 | [118]root | [119]parent | [120]next [121][–] Funny you mention the GIL - this is being done as part of PEP 554 which was slated to release in python 3.9 (in alpha).

And it's showing great promise ...while it could be delayed.

[122]https://www.mail-archive.com/python-dev@python.org/msg108063...

2021 is probable going to be the "Gone Gil" moment !

[s.gif]

[123]amelius [124]on April 18, 2020 | [125]root | [126]parent | [127]next [128][–] Why don't they use/fork the GoLang runtime?

[s.gif]

[129]YawningAngel [130]on April 18, 2020 | [131]root | [132]parent | [133]next [134][–] There are a few reasons: 1. This would definitely break the CPython API, which is not an option for mainstream Python. 2. The Golang runtime isn't really well-understood as a backend for languages that aren't Golang, although I acknowledge that there's no reason in principle why you couldn't compile $LANGUAGE to Golang.

[s.gif]

[135]antoinealb [136]on April 18, 2020 | [137]root | [138]parent | [139]prev | [140]next [141][–] To nuance your comment, you can still get some form of parallelism, "just not" thread parallelism in Python. You can still spawn multiple handler process, or have threaded code in a C extension.

[s.gif]

[142]slashdev [143]on April 18, 2020 | [144]root | [145]parent | [146]next [147][–] Yes, you can use multiple processes to get the parallelism. But that's quite limiting compared with goroutines. Passing data back and forth is hard, and you can petty much forget about shared data structures. Memory usage is also much higher.

[s.gif]

[148]zepto [149]on April 18, 2020 | [150]root | [151]parent | [152]prev | [153]next [154][–] It’s arguable whether either of those are ‘in python’.

[s.gif]

[155]quacker [156]on April 18, 2020 | [157]root | [158]parent | [159]next [160][–] The multiprocessing module in the standard library is absolutely a Python-native way to do parallelism:

with Pool(5) as p: print(p.map(f, [1, 2, 3]))

This runs f(1), f(2), and f(3) in parallel, using a pool of five processes.

[161]https://docs.python.org/3.6/library/multiprocessing.html

[s.gif]

[162]goostavos [163]on April 18, 2020 | [164]root | [165]parent | [166]next [167][–] Whoa! It never occurred to me that `Pool` could be used with context manager. I've always typed out `.close()` manually like a sucker.

[s.gif]

[168]kbutler [169]on April 18, 2020 | [170]root | [171]parent | [172]prev | [173]next [174][–] [175]https://docs.python.org/2/library/multiprocessing.html

Python standard library since 2.6. Pretty much the definition of "in python".

[s.gif]

[176]quacker [177]on April 18, 2020 | [178]root | [179]parent | [180]prev | [181]next [182][–] > Gevent is like goroutines with GOMAXPROCS=1.

On its own, yes. For webapps, you can easily combine it with a multi-process WSGI server (like gunicorn or similar).

[s.gif]

[183]throwaway894345 [184]on April 18, 2020 | [185]root | [186]parent | [187]next [188][–] Running four processes with GOMAXPROCS=1 is strictly worse than 1 process with GOMAXPROCS=4. The difference is coarse-vs-fine grained parallelism. Notably, a WSGI+gevent system doesn't allow you to do parallelism within a request, not to mention configuring these WSGI implementations (especially for production) is a bunch of extra headache for which there is no analogy in Go.

[s.gif]

[189]marcosdumay [190]on April 18, 2020 | [191]root | [192]parent | [193]prev | [194]next [195][–] The GIL is not a total ban on thread parallelism. It's a significant obstacle, but not a complete stop.

Besides, Go has its own set of problems with parallelism. None of those are best in class.

[s.gif]

[196]throwaway894345 [197]on April 18, 2020 | [198]root | [199]parent | [200]next [201][–] This comment makes it sound like Go and Python are pretty much in the same class because neither is perfect. I invite anyone who thinks this way to write considerable (shared-memory) parallel code in both languages and see which they prefer.

As for Go's "set of problems with parallelism", they're pretty much just that sharing memory is hard to do correctly without giving up performance. No languages do this well; Rust and Haskell make it appear easier by making single-threaded code more difficult to write--requiring you to adhere to invariants like functional purity or borrowing. If you're writing Python, you very likely have values that are incompatible with these invariants (you want to onboard new developers quickly and you want your developers to write code quickly and you're willing to trade off on correctness to do so).

Go is absolutely best-in-class if you have typical Python values.

[s.gif]

[202]dnautics [203]on April 19, 2020 | [204]root | [205]parent | [206]next [207][–] Why bother writing shared-memory parallel code if it makes your life so hard? Most of the time you're i/o bound, or network bound, or storage bound. Being compute bound is exceptionally rare these days.

[s.gif]

[208]throwaway894345 [209]on April 19, 2020 | [210]root | [211]parent | [212]next [213][–] I do it when I have to do it. Most things are I/O bound, but sometimes things are compute bound. And since Python is about two orders of magnitude slower than Go (and Python also makes it much harder to optimize straight-line execution because it lacks semantics for expressing memory layout), you tend to need parallelism more often than you would in a fast language. Sometimes you can leverage pandas or write a small chunk in C, but very often those options aren’t available, and naively throwing c at the problem can make your performance worse.

[s.gif]

[214]marcosdumay [215]on April 18, 2020 | [216]root | [217]parent | [218]prev | [219]next [220][–] > Go is absolutely best-in-class if you have typical Python values.

"Best in class" is not a relative term. Neither Go nor Python are appropriate choices for highly parallel intercomunicating code. Yes, Python is more limited than Go here, but hardly makes a difference when you avoid it.

Haskell and Rust do make it easier, by forcing developers to organize their code in a completely different way. Erlang does the same, with a different kind of organization. None of those languages are more difficult to program in, but yes, they are hard to learn.

[s.gif]

[221]jatone [222]on April 19, 2020 | [223]root | [224]parent | [225]next [226][–] > Neither Go nor Python are appropriate choices for highly parallel intercomunicating code.

thats an extraordinary claim which needs evidence.

[s.gif]

[227]marcosdumay [228]on April 19, 2020 | [229]root | [230]parent | [231]next [232][–] Extraordinary?

Name any single Go feature aimed at helping parallel computing.

[s.gif]

[233]meowface [234]on April 18, 2020 | [235]root | [236]parent | [237]prev | [238]next [239][–] I still use and greatly prefer gevent to this day. They are indeed quite similar to goroutines. Asyncio is a different model, and more irritating for me to work with. (I'm sure this isn't the case for everyone. I'm just more productive with gevent, personally.)

Performance is pretty close for both. I was disappointed to not see Python get an official green thread implementation. The counter-argument I commonly see cited is [240]https://glyph.twistedmatrix.com/2014/02/unyielding.html. I personally don't find it to be a very convincing argument.

[s.gif]

[241]sandGorgon [242]on April 18, 2020 | [243]root | [244]parent | [245]next [246][–] What's missing in asyncio when compared to gevent ?

The coroutine and queue model is the same right ?

Cool thing in 3.8:

Running python -m asyncio launches a natively async REPL.

[s.gif]

[247]meowface [248]on April 18, 2020 | [249]root | [250]parent | [251]next [252][–] They're just completely different models. gevent is green threads, asyncio is explicit coroutines. In gevent, you don't use an "async" or "await" syntax. You just spawn greenlets (green threads), which run in the background, and if you want, you can have them block until they return a result. And they're efficient, so you can spawn thousands without a problem.

[s.gif]

[253]quacker [254]on April 18, 2020 | [255]root | [256]parent | [257]next [258][–] I always considered "green threads" and "coroutines" to be the same thing? Are they not?

[s.gif]

[259]zenhack [260]on April 19, 2020 | [261]root | [262]parent | [263]next [264][–] The difference is that with coroutines, yielding is explicit. Tight-looping will hog the CPU, and a blocking call will block other coroutines too. Typically "green threads" are semantically just threads but cheaper. They're scheduled independently, so there's no risk of them hogging the CPU, and you can use synchronous apis. The one downside is that you need explicit synchronization between them, whereas with coroutines you can mutate shared data structures and not worry about race conditions as long as you don't yield in between.

[s.gif]

[265]infinite8s [266]on April 18, 2020 | [267]root | [268]parent | [269]prev | [270]next [271][–] They are both built on the same technology in the CPython runtime.

[s.gif]

[272]sateesh [273]on April 18, 2020 | [274]root | [275]parent | [276]prev | [277]next [278][–] If you have a significant python code base that is not async, then all of that need to be ported to support async model where as with gevent I can do monkey patching and move to concurrency model. If I am starting a fresh project with python and need concurrency, yes "async" is a better choice, but if you already have some code base then moving to async is a fair amount of work.

[s.gif]

[279]throwaway894345 [280]on April 18, 2020 | [281]root | [282]parent | [283]prev | [284]next [285][–] With asyncio, your whole app falls over if you accidentally call a library function that makes a sync API call under the covers. gevent (as I understand it; haven't actually used it) will patch all sync APIs and make them async. Also, if you do `aiohttp.get("www.example.com/foo.json").json()", you get a TypeError because coroutine has no method '.json()' (you forgot `await`) unless you're using Mypy.

[s.gif]

[286]meowface [287]on April 20, 2020 | [288]root | [289]parent | [290]next [291][–] Yep, that about sums it up. gevent can't monkeypatch synchronous code that's implemented in non-Python native modules, but I think pretty much all native Python libraries struggle with those sorts of things, and asyncio of course also can't deal with it.

The vast majority of the time, gevent's monkeypatching works without any issues. With asyncio, you basically have to rewrite everything from the ground up to always use the new async APIs, and you can't interact with libraries that do sync I/O.

[s.gif]

[292]throwaway894345 [293]on April 18, 2020 | [294]parent | [295]prev | [296]next [297][–] > Fyi - python ASGI frameworks like fastapi/Starlette are the same developer experience as go.

Can you provide some context for this statement? I've used Python asyncio extensively in Fargate (no ASGI frontend), and the developer experience is far from Go; however, I don't see how an ASGI framework can fix this. It seems like it offers the same general course-grained parallelism that you get from a containerized environment like Fargate except that Fargate abstracts over a cluster while ASGI frameworks presumably just abstract over a handful of CPUs.

For example, we have a large data structure that we have to load and process for each request. We want to parallelize the processing of that structure, but the costs to pickle it for a multiprocessing approach are much too large. We've considered the memory mapped file approach, but it has its own issues. We're also looking at stateful-server solutions, like Dask, but now we're talking about running infrastructure. In Go, we could just fork a few goroutines and be on our way.

[s.gif]

[298]sandGorgon [299]on April 18, 2020 | [300]root | [301]parent | [302]next [303][–] you should ask this exact same question here - [304]https://github.com/tiangolo/fastapi/

i dont claim to have expertise in your business domain, but you should get the answer here.

[s.gif]

[305]solidasparagus [306]on April 19, 2020 | [307]parent | [308]prev | [309]next [310][–] The difference is that it doesn't play well with large parts of the existing Python ecosystem. Concurrency is a pain if you are writing a library or trying to integrate with existing code. Python async is powerful, but:

(1) it's undersupported (e.g. you can in theory download s3 files using async botocore, but in practice it is hard to use because of strict botocore version dependencies)

(2) it isn't natural - once you're in the event loop it makes sense, but using an event loop alongside normal python code is confusing at best.

(3) it got introduced too late. The best async primitives are only available in pretty recent versions of python3.

The difference with go is that it go has these primitives built in from the beginning and using them doesn't introduce interoperability problems.

[s.gif]

[311]jatone [312]on April 19, 2020 | [313]root | [314]parent | [315]next [316][–] and on top of it go is performant enough that 90% of the time you don't need them to begin with.

[s.gif]

[317]hackworks [318]on April 19, 2020 | [319]root | [320]parent | [321]next [322][–] Most common use case for concurrency is for IO intensive workloads. When it comes down to IO, programming language hardly matters.

If you have CPU intensive workload, an optimizing compiler can help. Well, for that you have C or other languages with more mature and aggressive compilers.

[s.gif]

[323]zaro [324]on April 19, 2020 | [325]parent | [326]prev | [327]next [328][–] I've played with the concurrency in Python, and it's simply not worth it. Much better to use Node.js or Go where the async story is not an afterthought.

Of course if you are stuck with Python it's better than nothing.

[s.gif]

[329]jakearmitage [330]on April 18, 2020 | [331]parent | [332]prev | [333]next [334][–] > same developer experience as go

You can't say that when Python shoves Pip/Poetry/VirtualEnv/Black/Flake and what not into people. In contrast, Go has built-in package management and gofmt. Python is essentially gate-keeping new devs.

[s.gif]

[335]sandGorgon [336]on April 18, 2020 | [337]root | [338]parent | [339]next [340][–] Go has had an equally bad packaging experience.

Kubernetes - which is one of the biggest projects built in go - has been struggling with dependency and package management.

Here's the CTO of Rancher commenting on his struggles

[341]https://twitter.com/ibuildthecloud/status/118752909888666419...

[342]https://twitter.com/ibuildthecloud/status/118753821015230873...

This is not trivial stuff..and it shouldn't be trivialised into a go vs python flamewar. Because it can't be.

[s.gif]

[343]throwaway894345 [344]on April 18, 2020 | [345]root | [346]parent | [347]next [348][–] I've used Python and Go extensively. Go's packaging story has a few rough edges, but Python's is an impenetrable maze of competing tools that each purport to address others' major hidden pitfalls.

To work with Python packages, you have to pick the right subset of these technologies to work with, and you'll probably have to change course several times because all of them have major hidden pitfalls:

* wheels

* eggs

* pex

* shiv

* setuptools

* sdist

* bdist

* virtualenv

* pipenv

* pyenv

* sys.path

* pyproject.toml

* pip

* pipfile

* poetry

* twine

* anaconda

To work with Go:

* Publish package (including documentation): git tag $VERSION && git push $VERSION

* Add a dependency: add the import declaration in your file and `go build`

* Distribution: Build a static binary for every target platform and send it to whomever. No need to have a special runtime (or version thereof) installed nor any kind of virtual environment nor any particular set of dependencies.

[s.gif]

[349]ForHackernews [350]on April 18, 2020 | [351]root | [352]parent | [353]next [354][–] Yeah, until github is unreachable and the entire Go universe grinds to an immediate halt because nothing will build.

Python packaging is a mess, but Go doesn't even bother. "Just download from some VCS we'll pretend is 100% reliable and compile from source" is not a packaging solution.

[s.gif]

[355]kelnos [356]on April 18, 2020 | [357]root | [358]parent | [359]next [360][–] How is that any different than the entire Python universe grinding to an immediate halt if there's an issue with pypi.python.org? (Hint: it's not.)

You can certainly debate the difference in uptime between specific services; I don't know either way, but if you told my that PyPi had higher uptime than GitHub, I'd believe you... but that's kinda missing the point. If you depend on an online service to host your release artifacts, if and when that service goes down, it's gonna hurt.

Meanwhile, Python's packaging wars continue to rage on. Go's is simple: a release is a tag in a VCS repository. I'm sure there are issues with that as well, but that should come as no surprise, considering there are issues with literally every packaging solution. At any rate, there's little moral difference between downloading a tarball (or a wheel, or... whatever), vs. pulling a tag from a git repo. It requires equal levels of trust to believe that no one has tampered with prior releases in both cases.

I'd like to also point out that I don't have a dog in this race. I've done a little Go here and there, but frankly I don't like the ergonomics of the language too much, so I stay away from it. I've done (and continue to do) a decent amount of Python. I like the language, but tend to prefer strongly-typed, functional languages, and languages with performant runtimes, so I tend to only use it for smaller projects.

[s.gif]

[361]ForHackernews [362]on April 19, 2020 | [363]root | [364]parent | [365]next [366][–] You can trivially run your own local PyPI mirror or install packages directly from some other source (e.g. S3 bucket, LAN storage). Is there a way to do that for Go? If so, I've never seen it done.

[s.gif]

[367]morelisp [368]on April 19, 2020 | [369]root | [370]parent | [371]next [372][–] It's possibly as of the proxy in Go 1.13, but this was not well-documented, suffers from competing implementations, and introduced in a way that probably broke more builds than it helped.

[s.gif]

[373]jatone [374]on April 19, 2020 | [375]root | [376]parent | [377]prev | [378]next [379][–] yes you just vendor your dependencies.

go has support for a proxy system, tooling is still immature though.

[s.gif]

[380]throwaway894345 [381]on April 19, 2020 | [382]root | [383]parent | [384]prev | [385]next [386][–] I’ll take “doesn’t even try, but just works” all day every day. What is Github’s downtime for cloning in the last year, and how does it compare to Pypi? And if you’re really worried, why not use a caching proxy just like you do with Pypi? In my experience (using Python since 2008 and Go since 2012), Go package management has far fewer problems.

[s.gif]

[387]petre [388]on April 19, 2020 | [389]root | [390]parent | [391]next [392][–] I can't build lego from source due to a failed dependency. The docs don't help either, they're plain wrong. To make matters worse, Go pulls the latest dev version so good luck trying to build a stable binary of some complex package. I've opened an issue which was promptly closed and I was told to "just download the binary dist, source builds are for devs". To add insult to injury, each project is built in its own usually broken way. Out if date software? Good luck. Sorry, but I've had overall better experiences installing random Python programs with pip or building D libs with dub. Pulling half of Github rarely qualifies as "package management". It only encourages a giant mess, which is precisely what software development has been lately. Go is probably worse than npm in this respect.

[s.gif]

[393]jatone [394]on April 19, 2020 | [395]root | [396]parent | [397]next [398][–] no have no idea what you're talking about. these problems don't exist anymore since godep and now go modules which is builtin to standard go tooling.

[s.gif]

[399]jatone [400]on April 19, 2020 | [401]root | [402]parent | [403]prev | [404]next [405][–] > Yeah, until github is unreachable and the entire Go universe grinds to an immediate halt because nothing will build.

that's what vendoring is for and the proxy cache. this problem hasn't existed since like go 1.8 and is completely resolved in go1.14.

[s.gif]

[406]joshuamorton [407]on April 19, 2020 | [408]root | [409]parent | [410]prev | [411]next [412][–] You're combining multiple problems: maintaining a package for redistribution, and using packages. For the second, the much more common case, 2/3 of the things on your list are irrelevant.

[s.gif]

[413]throwaway894345 [414]on April 19, 2020 | [415]root | [416]parent | [417]next [418][–] For either case, Python’s story is more complex than Go’s.

[s.gif]

[419]morelisp [420]on April 18, 2020 | [421]root | [422]parent | [423]prev | [424]next [425][–] Go may be unique in being the only ecosystem built after Python that can't claim it avoided Python's packaging disasters.

[s.gif]

[426]throwaway894345 [427]on April 18, 2020 | [428]root | [429]parent | [430]next [431][–] How do you figure? Go's packaging is wayyyy better than Python's. I've done considerable work with each and while Go's ecosystem has warts here and there, it's far from disastrous. I can't say that about Python.

If nothing else, Go lets you distribute a static binary with everything built in, including the runtime. Python's closest analog is PEX files, but these don't include the runtime and often require you to have the right `.so` files installed on your system, and they also don't work with libraries that assume they are unpacked to the system packages directory or similar. In general, it also takes much longer to build a PEX file than to compile a Go project. Unfortunately, PEX files aren't even very common in the Python ecosystem.

[s.gif]

[432]morelisp [433]on April 18, 2020 | [434]root | [435]parent | [436]next [437][–] In the context of

> Pip/Poetry/VirtualEnv

"packaging" refers to the way the language manages dependencies during the build and import process, not how you distribute programs you have built.

Python has a deservedly poor reputation here, having churned through dozen major overlapping different-but-not-really tools in my decade and a half using it. And even the most recent one is only about a year into wide adoption, so I wouldn't count on this being over.

Go tried to ignore modules entirely, using the incredibly idiosyncratic GOPATH approach, got (I think) four major competing implementations within half as long, finally started converging, then Google blew a huge amount of political capital countermanding the community's decision. My experience with Go modules has been mostly positive, but there's no really major new idea in it that needed a decade to stew nor the amount of emotional energy. (MVS is nice but an incremental improvement over lockfiles, especially as go.sum ends up morally a lockfile anyway.)

[s.gif]

[438]dnautics [439]on April 19, 2020 | [440]root | [441]parent | [442]next [443][–] I'm slowly deprecating a python system at work and replacing it with elixir. We don't use containerization or anything, and installing the python system is a nightmare. You have to set up virtualenvs, not to mention celery and rabbit, and god help you if you're trying to operate it and you forget something or another.

With elixir, you run "mix release" and the release pipeline is set up to automatically gzip the release (it's one line of code to include that). Shoot the gzip over (actually I upload to s3 and redownload), unzip, and the entire environment, the dependencies, the vm, literally everything comes over. The only thing I have to do is sudo setcap cap_net_bind=+ep on the vm binary inside the distribution because linux is weird and, as they say, "it just works".

[s.gif]

[444]throwaway894345 [445]on April 19, 2020 | [446]root | [447]parent | [448]prev | [449]next [450][–] I fully agree with this assessment, but I don’t see how this puts Python’s story on par with Go’s. While GOPATH was certainly idiosyncratic, it generally just worked for me. While go modules aren’t perfect and the history was frustrating, they generally work fine for me. Python feels like an uphill battle by comparison.

[s.gif]

[451]morelisp [452]on April 19, 2020 | [453]root | [454]parent | [455]next [456][–] If Go sticks with modules and doesn't keep making significant changes (e.g. the proxy introduced 1.13 was not handled well), then it will be better than Python.

But if Python finally "picks" poetry, sticks with it for a few years and incrementally fixes problems rather than rolling out yet another new tool, that will also be better.

You can only identify the end of the churn for either retroactively. Python just looks worse right now because it's been around longer.

[s.gif]

[457]jatone [458]on April 19, 2020 | [459]root | [460]parent | [461]next [462][–] difference here is track record.

go: tends to wait and implement something once the problem is understood. took 2 years after go maintainers decided to solve the dependency issues. and as of the latest release its finally been labelled production ready.

and honestly the proxy issues were not real. go modules was still optional. you could just turn it off.

python is how old now? couple decades? and it has only gotten worse over time.

[s.gif]

[463]morelisp [464]on April 19, 2020 | [465]root | [466]parent | [467]next [468][–] Another thing Python and Go unfortunately have in common is a community (not necessarily core developers) with knee-jerk reactions to any criticism.

> go: tends to wait and implement something once the problem is understood.

Go's modules provide no additional "understanding" over any of the other Bundler-derived solutions in the world. MVS was the primary innovation, but wanting checksum validation means I have to track all the same data anyway.

> took 2 years after go maintainers decided to solve the dependency issues

This is revisionist history. There were other official "solutions" before ("you don't need it", "vgo is good enough", and "we'll follow community decisions"). If this one sticks, it's fine. But you can't say it's good now just because it's the one we have now - it's good now if it's the one we still manage to have in five years.

Go's track record is not "good" (in that regard I think only Cargo qualifies). At best it's "mercifully short."

> and honestly the proxy issues were not real.

Documentation was poor, the needed flags changed shortly before release, the design risks information leaks, and the entire system should not have been on by default for at least one more minor version.

> python is how old now? couple decades? and it has only gotten worse over time.

Yeah, that's exactly why I said "Python just looks worse right now because it's been around longer." It hasn't gotten worse though, it just also hasn't stopped churning. And if Go doesn't stop churning, in 10 years it will look the same.

The age argument works both ways - multiple major versions of Python predate Bundler. Go has no excuse for taking so long to reinvent "Bundler with incidentals", just like every other language.

[s.gif]

[469]takeda [470]on April 18, 2020 | [471]root | [472]parent | [473]prev | [474]next [475][–] I believe Python suffers from no leadership in that space (everyone creates their own packaging, every tutorial advocates something different, many tutorials are outright wrong).

There was also a bad decision of using Python code for installation (setup.py) instead of a declarative language.

Most of that issues are actually fixed in setuptools if you put all settings in setup.cfg and just call empty setup() in setup.py.

Like here: [476]https://github.com/takeda/example_python_project/blob/master...

[s.gif]

[477]mdtusz [478]on April 18, 2020 | [479]root | [480]parent | [481]prev | [482]next [483][–] Cargo works pretty well too.

[s.gif]

[484]takeda [485]on April 18, 2020 | [486]root | [487]parent | [488]next [489][–] Cargo is not from Go

[s.gif]

[490]jessaustin [491]on April 18, 2020 | [492]root | [493]parent | [494]next [495][–] As a name for a package manager, "cargo" certainly appears more suitable for "go" than for "rust".

[s.gif]

[496]waterside81 [497]on April 18, 2020 | [498]prev | [499]next [500][–] What's interesting is that McDonald's wait times have actually gone up since they moved to kiosk ordering, mobile app ordering, Uber eats etc. They've increased their ability to take orders, but haven't been able to keep up on the supply side. The old way was almost better in that it introduced a natural bottleneck so while it took longer to place your order, once you did, the queue in front of you was shorter.

[501]https://www.businessinsider.com/mcdonalds-spending-millions-...

[s.gif]

[502]skrebbel [503]on April 18, 2020 | [504]parent | [505]next [506][–] This is intentional. In fact, I've seen many McDonald'ses that were redecorated such that you can't see the screen with the queued/ready orders from where the kiosks are. This way, you're not discouraged from ordering if you feel like the wait will be too long.

This is also why McDonald's introduced table service, which is only in restaurants that have a layout where it's impossible to hide how many people are waiting. It costs manpower to deliver food to tables, but the additional orders are worth it.

McD's don't mind if you have to wait, they mind if you leave before you order. "Busy-looking queue" is a much more frequent problem than "totally-packed-restaurant".

Source: I like hamburgers + I geek out over stuff like this. I.e., Just Guessing.

[s.gif]

[507]smacktoward [508]on April 18, 2020 | [509]root | [510]parent | [511]next [512][–] I wonder how much of the delay is due to their recent decision to offer breakfast items all day. Many franchisees were complaining at the time about how doing so would reduce throughput, as it expanded greatly the list of possible items a customer could order and necessitated pulling people away to staff tasks that were only required for breakfast, like cooking eggs.

[s.gif]

[513]toyg [514]on April 18, 2020 | [515]root | [516]parent | [517]next [518][–] A lot of these measures have come to markets where breakfast is still not served all day (e.g. UK, last I checked).

My reasoning is that they are just trying as hard as they can to decouple order-taking from order-preparing and distributing, taking their clue from Starbucks. Volume of this or that is not really an issue: with the exception of chips, these days they hardly prepare anything at all before it’s been ordered, so it doesn’t really matter whether they make a burger or a muffin.

[s.gif]

[519]arrty88 [520]on April 18, 2020 | [521]root | [522]parent | [523]prev | [524]next [525][–] Yet we are willing to wait for chipotle, five guys, shake shack for 20 min m

[s.gif]

[526]darkerside [527]on April 18, 2020 | [528]root | [529]parent | [530]next [531][–] ?

Chipotle is about as fast as it gets

[s.gif]

[532]dillonmckay [533]on April 18, 2020 | [534]root | [535]parent | [536]next [537][–] Not when the person in front of you is getting 6 different orders.

[s.gif]

[538]loblollyboy [539]on April 18, 2020 | [540]root | [541]parent | [542]prev | [543]next [544][–] Do you not have tastebuds?

[s.gif]

[545]jiofih [546]on April 18, 2020 | [547]root | [548]parent | [549]next [550][–] Do you? Those are some of the best dirty burgers you can have on this planet.

[s.gif]

[551]sli [552]on April 18, 2020 | [553]root | [554]parent | [555]next [556][–] They've gotten horrendously expensive in the fast few years, though. That's my only real issue. My order has gone from $10 to $17 since they opened in my town, so I just don't go anymore.

[s.gif]

[557]rhizome [558]on April 18, 2020 | [559]root | [560]parent | [561]prev | [562]next [563][–] I was talking about this just last night. Five Guys is absolutely the worst of the mid-priced hamburger chains, and even their fries are almost as bad as In-N-Out's, which is like making a car whose steering wheel flies off while you're driving.

[s.gif]

[564]jessaustin [565]on April 18, 2020 | [566]root | [567]parent | [568]next [569][–] In-n-out fries must be eaten while they're hot. In that state they are delicious. The precipitous decline in quality upon cooling occurs because they are made by frying potato pieces rather than by assembling various starches in a laboratory.

[s.gif]

[570]freehunter [571]on April 18, 2020 | [572]root | [573]parent | [574]prev | [575]next [576][–] I think my tastebuds must be off because I feel the same way. There's always a huge line at Five Guys and people rave about it but whenever I eat there I feel like I need a straw for my fries because they're just drowning in grease.

I get that people like it and I'm certainly not going to discourage anyone from doing what they enjoy, but I also feel like social media has turned certain fast food chains into memes where you can't merely just be satisfied with something, you either need to looooovveeeee iiiitttt or demand it be "canceled". There's no middle ground.

[s.gif]

[577]AlphaSite [578]on April 19, 2020 | [579]root | [580]parent | [581]next [582][–] The fries are fairly mediocre, but their burgers are pretty fantastic, espesicslky if you’re a fan of animal style.

[s.gif]

[583]seized [584]on April 18, 2020 | [585]root | [586]parent | [587]prev | [588]next [589][–] Saying Five Guys is the worst in a thread that features McDonalds... Five Guys is gourmet compared to McDonalds.

[s.gif]

[590]rhizome [591]on April 20, 2020 | [592]root | [593]parent | [594]next [595][–] That's why I distinguished McD's out of the comparison with "mid-priced."

[s.gif]

[596]agumonkey [597]on April 18, 2020 | [598]root | [599]parent | [600]prev | [601]next [602][–] Well someone tell McDonald's some people are not going there anymore. The few I do I use McDrive because the wait is predictable and shorter.

If I had the money I'd spent it to open a good old McDonald's I'm sure more people would come.

[s.gif]

[603]cle [604]on April 18, 2020 | [605]parent | [606]prev | [607]next [608][–] It’s called backpressure and it’s one of the tradeoffs that should be considered when thinking about adopting async work queues. There is no natural backpressure mechanism so it takes a lot more work to ensure you either reject new work after hitting a limit, or scale your workers so you can keep up with the queue backlog. Queues seem great, until they’re not, and then you enter a much more complicated world.

[s.gif]

[609]agumonkey [610]on April 18, 2020 | [611]parent | [612]prev | [613]next [614][–] It's so sadly true that you can realize it without even looking.

The kiosk system is human-less thinking, we're not machines operating with pure logistics in mind. We like to have responsibilities in a way. When I'm talking to a cashier, he/she feels a duty to do something from A to B. With decoupled ordering.. nobody knows who I am, nobody really cares (McDonalds doesn't pay nor train for welcoming and service mindset). I'm just a thing carrying a ticket.

I've seen things so absurd, people walking around not knowing who to talk to, where to go, what to assume; both customers or employees. It was a surrealist comical situation.

Also my average time to serve for 1 hamburger with no other customer around is 7min. (5-15). Talk about fast food :)

Another point, I don't mean to make people work more, but I even prefer busy waiting lines with hectic kitchen action. That's what McDonalds were, high throughput grill. It felt something.. now it's all dull and clinic.

Oh and lastly .. the kiosk are fugly. They break the room space, break the flow of people, are way too big for their purpose (100$ a stupid tiny 80s monochrome terminal, would do better :p)

ps: This decoupling idea was tried at a company I worked for. Exact same principle (which I also gave some credit at first), split everything in small chunks so people can go faster.. it all went worse because nobody took responsibility for anything since a single task was now a dozen tiny bits done by a dozen people not really knowing what their bit was for. They just passed the products from hand to hand, not being able to track who or what was wrong until the last guy received all the shit because he's the one to show the result to the managers :)

[s.gif]

[615]satvikpendem [616]on April 18, 2020 | [617]root | [618]parent | [619]next [620][–] That may be true for you, but I like the flow of the kiosks, where I can take my time and not be rushed, and I don't have to interact with someone just to take an order. I'm not sure why it has to be a process that requires a human at all, just to be a cashier.

[s.gif]

[621]toyg [622]on April 18, 2020 | [623]root | [624]parent | [625]next [626][–] They also work extremely well in busy tourist hotspots and big cities, where people might struggle to communicate and slow down operations pretty dramatically.

[s.gif]

[627]marktangotango [628]on April 18, 2020 | [629]root | [630]parent | [631]prev | [632]next [633][–] I feel even more rushed when people are in line behind me waiting for me to figure out the ui a cashier knows by heart. I’m not sure why it has to a process that requires a kiosk at all, just to be a cashier.

[s.gif]

[634]m463 [635]on April 18, 2020 | [636]root | [637]parent | [638]prev | [639]next [640][–] social distancing may skew everything towards kiosks.

[s.gif]

[641]bigyikes [642]on April 18, 2020 | [643]root | [644]parent | [645]next [646][–] If I’m worried about catching or spreading the virus, wouldn’t the kiosks be worse? Dozens of people touching the same surface with their bare hands seems more dangerous to me than telling my order to someone over a short distance, especially if masks are involved.

[s.gif]

[647]m463 [648]on April 18, 2020 | [649]root | [650]parent | [651]next [652][–] A full answer might depend on whether you are a customer or a cashier.

[s.gif]

[653]agumonkey [654]on April 18, 2020 | [655]root | [656]parent | [657]prev | [658]next [659][–] That is true. We might end up living in biohazard like cities from now one :)

[s.gif]

[660]nebulous1 [661]on April 18, 2020 | [662]parent | [663]prev | [664]next [665][–] That seems to be looking at "speaker to order window" instead of "arrival to order window" times. This seems odd to me, as personally I would want to minimize the latter not the former.

[s.gif]

[666]spamizbad [667]on April 18, 2020 | [668]parent | [669]prev | [670]next [671][–] I can't speak to the apps, but there's a foodcourt in my building with a kiosked McDonalds. Based on my observations, ordering with it is a slow, time consuming process. It's way faster to just say "I'll have a 5 with a coke". Most people in a hurry opt to stand in line with a cashier, which has a line that moves much faster.

[s.gif]

[672]rootusrootus [673]on April 18, 2020 | [674]root | [675]parent | [676]next [677][–] Totally agree, I loathe the kiosks, it is an incredibly slow way to order food. Perhaps they need to implement a voice assistant so you can just ask for a 5 with a coke.

[s.gif]

[678]DeonPenny [679]on April 18, 2020 | [680]parent | [681]prev | [682]next [683][–] That seems like a good problem cause before they had issues with demand. I think based on McDonald history of optimization they feel like they can solve that supply side issue more easily than the demand side one they were contending with

[s.gif]

[684]punnerud [685]on April 18, 2020 | [686]parent | [687]prev | [688]next [689][–] Could it be that the reduced stress on the buyers result in reduced speed on the staff?

[s.gif]

[690]xenonite [691]on April 18, 2020 | [692]parent | [693]prev | [694]next [695][–] Moreover, one could just look at the shelf of already prepared burgers and buy one of them. So quick!

[s.gif]

[696]formercoder [697]on April 18, 2020 | [698]parent | [699]prev | [700]next [701][–] Wouldn’t that be working as intended? More revenue

[s.gif]

[702]1337shadow [703]on April 18, 2020 | [704]prev | [705]next [706][–] Actually with uWSGI, be in on Flask, Django or else: I don't need neither Celery nor Redis. uWSGI has a built-in celery-ish spooler, cron-ish task scheduler, memcache-ish key-value store, along with plenty of other toys that I love from the deepest of my heart ... And I've been in this (great) situation for years, not planning to move out to more complicated stacks. I would highly recommend uWSGI over of Celery and Redis, which I used in the past, prior to doing it all in uWSGI, unless you have a really good reason which I'm eager to read about. And now that uWSGI supports a lot of languages, even if I have some PHP or whatever to deploy I'll go for uWSGI, one of the most beautiful piece of software I have the chance to use.

[s.gif]

[707]d33 [708]on April 18, 2020 | [709]parent | [710]next [711][–] Could you elaborate, e.g. link to documentation, subprojects or example code? I'd love to get rid of Celery because of how difficult it is for me to tweak it for good performance.

[s.gif]

[712]darkerside [713]on April 18, 2020 | [714]root | [715]parent | [716]next [717][–] Would love to see more detail as well because I'm a bit skeptical. From uWSGI documentation, it looks like to coordinate cron across anything more than a single server setup, you'd need to configure a Legion, which means you're then integrating uWSGI's orchestration framework with whatever you're already using (k8, ECS, etc).

I like minimalism, but sometimes batteries are included for a reason.

[s.gif]

[718]GlennS [719]on April 19, 2020 | [720]root | [721]parent | [722]next [723][–] I suspect they are using a single server. I found uwsgi's mules and cache2 very useful in that situation.

If someone finds that Redis and Celery are more complication than they need for a given task, then I think they're probably not using an orchestration framework.

[s.gif]

[724]GlennS [725]on April 19, 2020 | [726]root | [727]parent | [728]prev | [729]next [730][–] This is what I have used in the past. I think they're very convenient if you are just running one instance of uwsgi and want to share some state quickly without going through a persistent database.

If you're worrying about tweaking Celery for performance, then I suspect your uses may be a bit more complex than uwsgi's mules are designed for though.

[731]https://uwsgi-docs.readthedocs.io/en/latest/Caching.html [732]https://uwsgi-docs.readthedocs.io/en/latest/Mules.html

The cache is a simple key-value store. Works well. I later swapped it out for Redis, because I needed to shared my cache between multiple machines. Switching to Redis was a very quick and easy replacement, so you don't need to worry about lock in.

I used mules in a couple of ways. I had some background task mules which mostly just ran in a loop with a `sleep()` call. An example is deleting old records from a database once a day. Another example is listening to an Amazon SQS queue for files being uploaded to an S3 bucket.

I also had some mules which were triggered by web requests. These are normally what you would use "farms" for. The web request sends a farm message, and a mule picks it up and acts on it. For example, I used this for sending webhook callbacks in response to certain web requests.

You could probably also combine this with uwsgi's async mode. That would be useful if you needed a web request to wait for a long running task to finish before sending a response back. I handled that kind of situation with the aforementioned webhook callbacks instead.

A sibling comment has mentioned Legion. I've never used that, so can't comment on whether or not the caching and messaging works together with that.

[s.gif]

[733]dzonga [734]on April 18, 2020 | [735]root | [736]parent | [737]prev | [738]next [739][–] you can also use dramatiq

[s.gif]

[740]k_bx [741]on April 18, 2020 | [742]parent | [743]prev | [744]next [745][–] How does it work on more than one server? (which is how I hope you deploy all your production apps)

[s.gif]

[746]radus [747]on April 18, 2020 | [748]root | [749]parent | [750]next [751][–] The need for multiple servers kinda depends on the application, no? I'm interested in the single server story.. many of my apps are internal and used by 50 people at most.

[s.gif]

[752]k_bx [753]on April 18, 2020 | [754]root | [755]parent | [756]next [757][–] Yeah, but just in terms of redeploy without a downtime, secureness if new version won’t start properly, and redundancy when one server is down because of an OS error while you were asleep. Not about number of clients at all.

[s.gif]

[758]ljvmiranda [759]on April 18, 2020 | [760]prev | [761]next [762][–] Hi, author here! Pleasantly surprised I saw this on HN, thanks for posting feross! Sorry for the Mcdonalds analogy, it's just that it's really near our office and I got that insight while ordering McNuggets! Didn't expect it will cause some divide

Agree, Mcdonalds has definitely upped their ordering game recently. Thank you and I appreciate all the helpful comments!

[s.gif]

[763]throwaway888abc [764]on April 18, 2020 | [765]parent | [766]next [767][–] Hey, Nice article format for actual humans with easy to digest flow. Will share with devs. Great work! Thanks

[s.gif]

[768]andybak [769]on April 18, 2020 | [770]prev | [771]next [772][–] I wish there was a paragraph up the top that made two points:

1. Quite often you don't (I've built dozens of websites without needing Celery)

2. Even if you think you do there's often a much simpler solution that is enough for most needs (Use cron, spawn a process etc)

Celery is a big, heavy lump of code to add to most websites and it increased the deployment complexity.

[s.gif]

[773]danpalmer [774]on April 18, 2020 | [775]parent | [776]next [777][–] It’s worth scoping out what your site will need to do up front to some extent. Spending a couple of days setting up a basic background processing system (whether that’s celery, rq, or a home grown system) makes it easy to make great engineering decisions later down the line.

Questions like: should I send this email in-line in the web request? Get a very easy answer: no, just stick do it later. Sure, sending an email is probably fine to do in-line for now, but months in you may realise that things are slow, that you’re sending emails and rolling back transactions later, or committing the transaction but losing the email that needed to be sent, or all manner of other annoying edge cases. Queues don’t solve everything, but they can be an ok answer to a lot of stuff for a long time.

For basic sites, yeah maybe not necessary, but a reliable background processing system has always been a significant accelerator in my projects.

[s.gif]

[778]1337shadow [779]on April 18, 2020 | [780]root | [781]parent | [782]next [783][–] Same in my experience: emails should always be sent in a background process. Luckily for me, using uWSGI to deploy anything in any languages: it builds in a nice little spooler that's going to let me spool emails without adding a single new software to my stack: not even having to start another process.

[s.gif]

[784]raverbashing [785]on April 18, 2020 | [786]parent | [787]prev | [788]next [789][–] Completely agree

Several developers like to overengineer and "go for celery" (also applies to other technologies with other uses) even for small things.

You don't need Celery to run a batch job every day for example. Or to even do some parallel processing.

"Oh but python multithreading sucks" do you know when it does not suck? When your thread is waiting on something else. Also there's the multiprocessing module with a lot of "batteries included" for basic use cases.

Not to mention (my biggest pet-peeve of Celery) is that it "forces" you to work with a task queue model. Not a data queue model. Sure, it helps a lot when you need that, but sometimes you just need a queue.

[s.gif]

[790]mattbillenstein [791]on April 18, 2020 | [792]parent | [793]prev | [794]next [795][–] I prefer rq - Celery is too complex imho.

[s.gif]

[796]ptype [797]on April 18, 2020 | [798]root | [799]parent | [800]next [801][–] Also worth checking out nameko, I’ve had good experiences with it

[s.gif]

[802]cepp [803]on April 18, 2020 | [804]root | [805]parent | [806]next [807][–] Huey is also worth a shot.

[s.gif]

[808]mattbillenstein [809]on April 19, 2020 | [810]root | [811]parent | [812]next [813][–] I like it - uses redis as a broker - supports crontab style periodic tasks.

I've usually had to build a small python cron runner using croniter in previous systems - which I think is a pretty clean solution - it just deferred tasks to rq workers. But having direct support in the lib might be nice.

[s.gif]

[814]mattbillenstein [815]on April 19, 2020 | [816]root | [817]parent | [818]prev | [819]next [820][–] * depends on rabbitmq

[s.gif]

[821]procinct [822]on April 18, 2020 | [823]prev | [824]next [825][–] One aspect of this set up I’ve never been able to understand is how the application then gets the result from the worker? If it’s polling for status from the backend doesn’t that defeat the purpose of having a worker to begin with? Or does this set up only work for tasks that don’t need to have the backend notified about the result so the front end can just poll for the result via the application?

[s.gif]

[826]adamcharnock [827]on April 18, 2020 | [828]parent | [829]next [830][–] You’re spot on really. Having the front end wait for a background task to complete broadly defeats the purpose. There are some caveats though: if you’re using an async/threaded web server then it may not matter that you have a pending request hanging around as your web server is free to continue serving other requests. It also may be that you need to run the task on specialist hardware for some reason.

Really though, I think a lot of people use celery for offloading things like email sending and API calls which, IMHO, isn’t really worth the complexity (especially as SMTP is basically a queue anyway). Of course, YMMV depending on your use case.

However, I find it is often more worthwhile for:

1. Tasks which take a long time to run

2. Tasks which need to happen on a schedule, rather than in response to a user request.

There is an option 3 too, which is for inter-software communication. Eg events or RPCs, but I found Celery to be very much a square-peg-round-hole for this, which is why I developed Lightbus ([831]http://lightbus.org). Lightbus also supports background tasks and scheduled tasks. /plug

[s.gif]

[832]doliveira [833]on April 18, 2020 | [834]root | [835]parent | [836]next [837][–] It's not just about the time the operation takes, it's about reliability. Even if sending an email synchronously doesn't usually take more than a few milliseconds, you still need to handle cases like servers failing in the middle of the request, temporary upstream unavailability, some expired API, account limits reached, etc...

Honestly, I think that mostly anything that doesn't depend directly in the current state of your infrastructure should be done asynchronously. I've had a lot of issues with systems that start up doing everything synchronously: you'll probably need to refactor it to be asynchronous in emergency mode during a crisis.

[s.gif]

[838]marcosdumay [839]on April 18, 2020 | [840]root | [841]parent | [842]next [843][–] For email, that's why you set a relay within your control, that will accept messages without a fuss and send them around following SMTP conventions.

But anyway, how is your application supposed to respond after any of those failures? Is it just supposed to ignore the failure and thread on like if nothing happened, leaving your users on the dark? Is it supposed to reliably log every task so that it can retry anything that fails and in the worst case feed failures into some monitoring system/process? Or is it supposed to inform the user of any success or failure before the user can move on?

Queue software is only a good match for the first. For the second you will need to roll your own interface with the monitoring system anyway, so it's much easier to roll your own queues and get control of everything. The third one is best done synchronous, it doesn't matter the nature of the process or how long it takes. But funny thing is, I have never seen the first situation on the wild.

[s.gif]

[844]WJW [845]on April 18, 2020 | [846]parent | [847]prev | [848]next [849][–] If you really need the answer immediately to show to a user on a page, background workers (usually) don't help. However, there are a bunch of situations where there is no feedback to the user other than "we received your request in good order and will see that it's done".

For example, sending a mail can take a while because mailservers have queues and whatnot. If you send a mail after signing up a user for them to verify their email, you don't have to wait until the mail is "really" sent before letting them know that their signup has been processed. You can tell a background worker to send the mail and return to the user much faster. For another example, in a previous job I worked for a big file sharing service. If user wanted their files deleted that caused all sorts of calls to AWS to actually delete the files, which could take a while. However, from the user perspective it was pretty fast because all we had to do was set the file in the database to "delete in progress" state and tell a background worker to delete the files. Then we could show the user that their files were being deleted within a couple dozen milliseconds instead of having to wait for all the AWS calls to complete.

[s.gif]

[850]1337shadow [851]on April 18, 2020 | [852]root | [853]parent | [854]next [855][–] Not to mention the case where the mailserver is down or denies service, which will also happen at some point even if you have HA mailserver: be it with AWS emails, mailjet and whatnot. One day it'll fail everyone. Then, what's it going to be ? Return an HTTP 500 to the user rolling back the transaction ? Spooling emails removes that failure spot at all.

[s.gif]

[856]notyourday [857]on April 18, 2020 | [858]parent | [859]prev | [860]next [861][–] In my experience a lot of applications with workers that require a result to be furnished to a client are incorrectly engineered.

The correct pattern should be a client submits a request to get something done to a thin layer, receives a ticket that allows it to claim the result and goes away to either check for the result via polling for the ticket or receives a call back.

[s.gif]

[862]masklinn [863]on April 18, 2020 | [864]parent | [865]prev | [866]next [867][–] I would agree, generally a task queue makes sense for jobs which are not needed to respond to a query (e.g. generating reports or sending emails or whatever), otherwise you're just adding delays in the response chain.

Although this delay chain might be considered worth it you don't want to scale the frontend to multiple workers for some reason e.g. single-threaded evented runtime, or GIL runtime (python, ocaml), or if you want to avoid CPU-hard tasks being executed on your frontends.

In that case, it might be valuable to transform CPU waits into IO waits by moving the CPU work to a jobs queue, possibly running its workers on a different set of machines entirely.

[s.gif]

[868]jb3689 [869]on April 18, 2020 | [870]parent | [871]prev | [872]next [873][–] > If it’s polling for status from the backend doesn’t that defeat the purpose of having a worker to begin with?

It depends. If you needed a coordination layer or you needed to isolate certain types of traffic then it makes more sense. I assume your alternative here is "why not just have a new client tier doing work" which is a reasonable architecture too

> One aspect of this set up I’ve never been able to understand is how the application then gets the result from the worker?

Often they don't in these architectures. I found it a little strange that a job queue was being used to serve (what seems like) synchronous traffic. Usually I see job queues in the wild used for async/send-and-forget workloads

Personally I would rather chain multiple synchronous service calls if I needed a synchronous workflow. It's just simpler to me to stick web workers behind a load balancer and scale that. This is less elegant when things take a very long time though or are prone to retries. Either the client or server needs to be responsible for queuing/message persistence/retries - with services the client does it, with job queues the server does it

[s.gif]

[874]leowoo91 [875]on April 18, 2020 | [876]parent | [877]prev | [878]next [879][–] In case of a polling requirement from user perspective (e.g. waiting for a notification) it's true it doesn't matter. However, it allows application to respond to 'other' users. Whole point is to serve multiple users at the same time.

[s.gif]

[880]procinct [881]on April 18, 2020 | [882]root | [883]parent | [884]next [885][–] What I mean is that if your backend is polling for a task to finish, that is also taking away time from other users. For some tasks that won’t matter because the backend won’t need to be aware of the outcome of the task but there could be some longer jobs that the backend needs to be aware of the outcome right away. You could get it so the polling is done on the front end and then passes the outcome to the backend but that obviously isn’t a good idea because then the backend is trusting outcome data from the front end.

[s.gif]

[886]leowoo91 [887]on April 19, 2020 | [888]root | [889]parent | [890]next [891][–] I see your concern is focused on polling case (e.g a chat room). As goes with the McDonalds example, a single cashier can reply the question "is my order ready?" rapidly. While it takes seconds in real world, a client polling request would take milliseconds to complete, so it can still serve hundreds of clients in a given second. If you'd need more for that part, there can be more cashiers/apps to make "asking" part scale indefinitely (even you'd have 1 worker only).

[s.gif]

[892]golergka [893]on April 18, 2020 | [894]parent | [895]prev | [896]next [897][–] Right now, I'm designing a service that's very similar to OP, with workers waiting for an external API (or APIs) to answer, which can be slow sometimes. Looks like we're going to use websockets or polling to update the client with all the delivered data, and introduce yet another service for it, which would actually play the role of "LED screen" and ready order station in this analogy.

But as we decided to implement an MVP with a single HTTP request from the client, this whole separation doesn't make any sense, exactly as you noted.

[s.gif]

[898]doliveira [899]on April 18, 2020 | [900]parent | [901]prev | [902]next [903][–] Checking the result is just doing a SELECT in your database.

[s.gif]

[904]procinct [905]on April 18, 2020 | [906]root | [907]parent | [908]next [909][–] I was more referring to how it knows once it’s finished since the task is asynchronous. So for the backend to find out, it could do the select you mentioned and find out it’s still in progress. Then it checks again next second and still in progress. Then checks again and it’s done. But now your backend has been polling for an update and so you might as well have performed the task in the application because it is still being used up for the duration of the task.

[s.gif]

[910]turtlebits [911]on April 18, 2020 | [912]root | [913]parent | [914]next [915][–] Have your worker POST back to your web server when it’s done. Use websockets to notify the user.

[s.gif]

[916]nickjj [917]on April 18, 2020 | [918]prev | [919]next [920][–] If anyone is looking for another Celery post that goes over common web development use cases for using Celery there's: [921]https://nickjanetakis.com/blog/4-use-cases-for-when-to-use-c...

The above post walks through sending emails out with and without using Celery, making third party API calls, executing long running tasks and firing off periodic tasks on a schedule to replace cron jobs.

There's links to code examples too in an example Flask app which happens to use Docker as well.

[s.gif]

[922]doteka [923]on April 18, 2020 | [924]prev | [925]next [926][–] They mostly need Celery and Redis because in the Python world concurrency was an afterthought. In most other languages you can get away with just running tasks in the background for a really long time before you need spin up a distributed task queue. In Python I’ve seen Celery setups on a single machine.

[s.gif]

[927]mattbillenstein [928]on April 18, 2020 | [929]parent | [930]next [931][–] You still should use some sort of work queue - your application process may need to restart (deploys), or for a period of time, work could overflow the amount of available resources (bursts), so having some place to put the task before it goes onto processing is useful regardless of the underlying concurrency primitives of the language.

[s.gif]

[932]rollingbarreler [933]on April 18, 2020 | [934]root | [935]parent | [936]next [937][–] Transactionality is enough for most systems. Your order either succeeds or fails, it never stays in an incomplete state. Queues are not a panacea, and introduce their own problems like obscuring problems by delaying them long enough to bring everything to a halt.

[s.gif]

[938]mattbillenstein [939]on April 19, 2020 | [940]root | [941]parent | [942]next [943][–] Yes, you wouldn't do all work in the task queue - commonly, we make some change in the database which can happen pretty fast, and after that transaction commits, we might defer a task that sends a notification, email, whatever.

[s.gif]

[944]acjohnson55 [945]on April 18, 2020 | [946]root | [947]parent | [948]prev | [949]next [950][–] It may not make sense to retain jobs across deployments. What if the contract of the job is changed by the code being deployed? Might be easier to keep it all in-process, letting queues drain in a graceful shutdown.

[s.gif]

[951]mattbillenstein [952]on April 19, 2020 | [953]root | [954]parent | [955]next [956][–] I haven't found that to be the case typically -- you could always serialize some information into the task to check for things like this.

Also consider if the machine running that process just disappears and that process dies. Putting work into a task queue allows you to do it durably until it can be processed so that it's not lost in some typical "that machine/instance died" scenario.

[s.gif]

[957]sateesh [958]on April 18, 2020 | [959]root | [960]parent | [961]prev | [962]next [963][–] This might not be viable all the time, what if you have a stream of tasks being put to the queue ? The alternative would be to ensure that any change in the job contracts are backward compatible, and if any change in contract would need to have a remediation/migration plan for handling pending tasks.

[s.gif]

[964]momokoko [965]on April 18, 2020 | [966]root | [967]parent | [968]prev | [969]next [970][–] In the business, customer, end-user sense, in many situations, you are much better off to have a transaction fail with an error as opposed to finally successfully happening after 2 hours once a service disruption is cleared.

Every problem is not the same. Work queues introduce a magnitude or more of complexity to an http application. Sometimes that is very needed. Sometimes its overengineering. Sometimes it is a gray area.

[s.gif]

[971]jb3689 [972]on April 18, 2020 | [973]parent | [974]prev | [975]next [976][–] > They mostly need Celery and Redis because in the Python world concurrency was an afterthought

You have an operating system that you can use. You don't really _need_ concurrency when you have a machine that can timeshare amongst processes. That's the world Python was designed for

> In most other languages you can get away with just running tasks in the background for a really long time before you need spin up a distributed task queue

This is partly true, but not a lot of people do this because you need to persist those tasks unless you want them dropped during a reboot. Same logic goes for entire machines disappearing. You _can_ get by without a distributed system, but you will need to tolerate loss in those scenarios. Those losses are non-trivial for most apps/companies, so it doesn't seem all that practical to me to consider a world without a distributed system (and yes, persisting things in postgres/mysql before they are being worked on is still using a distributed system)

[s.gif]

[977]lifty [978]on April 18, 2020 | [979]parent | [980]prev | [981]next [982][–] I agree. That is why I stopped using languages that have a poor concurrency story. Also, using an external queue and workers considerably increases the operational complexity of the system. An in-process solution with some light persistence for the work queue in an embedded database can go along way, at least until you outgrow a single machine. Doing both ops and development I’ve learned to appreciate simple solutions.

[s.gif]

[983]nickjj [984]on April 18, 2020 | [985]parent | [986]prev | [987]next [988][–] You could use something like async / await without Celery and Redis but Celery brings a lot to the table.

What happens when you want to retry jobs with exponential back off, or rate limit a task, or track completed / failed jobs?

You can wire all of this stuff up yourself but it's a hugely complicated problem and a massive time sink, but Celery gives you this stuff out of the box. With a decorator or 2 you can do all of those things on any tasks you want.

I use it in pretty much every Flask project, even on single box deploys.

[s.gif]

[989]BiteCode_dev [990]on April 18, 2020 | [991]parent | [992]prev | [993]next [994][–] > In most other languages you can get away with just running tasks in the background for a really long time before you need spin up a distributed task queue

In Python too:

# or ThreadPoolExecutor depending of the type of work from concurrent.futures import ProcessPoolExecutor, as_completed

with ProcessPoolExecutor(max_workers=2) as executor:

a = executor.submit(any_function) b = executor.submit(any_function)

for future in as_completed((a, b)): print(future.result())

Any task you would put in celery would be a good candidate for being first passed to a process pool executor.

No, the real reason we use celery is that it solves many problems at once:

- it features configurable task queues with priorities

- it comes as an independent service accessible from multiple processes

- its activity can be inspected and monitored with stuff like flower

- it has the ability to create persistent queues that survive restart

- error handling is backed in, they are logged and won't break your process

- it offers an optional result backend for persisting results and errors

- many distribution and error handling strategies can be configured

- tasks are composable, can depend on each others or be grouped

- celery also does recurring tasks, and better than cron

- you can start tasks from other languages than Python

Now some People use celery when they should use a ProcessPool, because they don't know it exists. But that's hardly because of the language: you didn't seem to know about it either.

It is true that Python concurrency story is not comparable to something like Go, Erlang or Rust, but very common use cases are solved.

In the same way, we can perfectly use shelves instead of redis.

We use redis beacuse it solves many problems at once:

- it's very performant on a single machine, and can be load balanced if need ed

- it has expiration baked in

- it offers many powerful data structures

- it embeds numerous strategies to deal with persistence and resilience

- it's accessible from multiple processes, and multiple languages

- its ecosystem is great, and it's hugely versatile

It's almost never a bad choice to add redis for your website. It's easy to setup, cheap to run, and and it shines to manage sessions and caching for any service with up to a few million users a day.

Once you are at it, why not later use it for other stuff, like storing the result of background tasks, log stream, geographical pin pointing, hyperlolog stats, etc. ? There are so many things it does better than your DBMS, faster, easier or for less resources.

It's such fantastic software really.

But no, nothing prevents you in Python to create a queue manually and serialize it manually. It's just more work for less features.

[s.gif]

[995]doteka [996]on April 19, 2020 | [997]root | [998]parent | [999]next [1000][–] Thanks, I am well aware of every kind of multiprocessing and quasi-threading in the standard library, having built several large Python systems over the years.

I also understand the benefits of task queues. However, there are many cases in which you do not need any of those. Specifically, everything you wrote applies to the web backend/distributed systems usecase. Doing things in the background in a simple application, not so much. My problem is exactly with introducing distributed systems machinery for a local process on a single machine that doesn't need any of that.

[s.gif]

[1001]Dowwie [1002]on April 18, 2020 | [1003]parent | [1004]prev | [1005]next [1006][–] You can signal events to invoke background processing and immediately return a response.

[s.gif]

[1007]trboyden [1008]on April 18, 2020 | [1009]prev | [1010]next [1011][–] Excellent craftmanship of a helpful blog. Very reminiscent of the style used by the Head Rush Ajax ([1012]http://shop.oreilly.com/product/9780596102258.do) book O'Reilly published back in 2009 and the rest of the Head First series.

[s.gif]

[1013]memco [1014]on April 18, 2020 | [1015]prev | [1016]next [1017][–] I think it’s really important to understand task queues and workers but my experience working with these particular tools isn’t exactly fun. I inherited a system built on celery, rabbitmq and nameko I’d be interested to hear how people setup their systems to debug and test new tasks. I’m currently using manually added psb.set_trace to telnet in to a debugging session, but I’d prefer to use an IDE so I can modify code while debugging. Anyone have any tips? One thing I would caution against is putting the business logic in the task logic. This is obviously up to whoever set up the tasks but it seems like most of the tutorials don’t mention how painful this can make testing especially once you start making chains, chords and sub tasks.

[s.gif]

[1018]rukittenme [1019]on April 18, 2020 | [1020]parent | [1021]next [1022][–] For testing you can set "CELERY_ALWAYS_EAGER" to "True" in your config.

[s.gif]

[1023]dralley [1024]on April 18, 2020 | [1025]prev | [1026]next [1027][–] Does anyone have enough experience with alternatives to Celery to give a good comparison of Celery vs. Dramatiq vs. RQ?

[s.gif]

[1028]timwis [1029]on April 19, 2020 | [1030]prev | [1031]next [1032][–] Cool article! But why do you need a database _and_ a message queue? I would think a message queue is the main thing, and a database is only necessary if you want long term persistence. Or you could just use a database as a message queue.

[s.gif]

[1033]bryanrasmussen [1034]on April 18, 2020 | [1035]prev | [1036]next [1037][–] I think the McDonald's order by touch screen also has the benefit of seeming to take less time when waiting because you are not standing in line behind someone, even if it takes the same amount of time psychologically it seems less.

[s.gif]

[1038]kantye [1039]on April 18, 2020 | [1040]prev | [1041]next [1042][–] Very noice! I am not normally not a huge fan of stick figures (a la waitbutwhy), but this was very pleasant to read :D And noice work picking an example I can relate to

[s.gif]

[1043]nurettin [1044]on April 18, 2020 | [1045]prev | [1046]next [1047][–] Celery is good for distributed and persistent message queues which can be monitored. If you just need multiprocessing, use a multiprocessing pool, it comes with python.

[s.gif]

[1048]quezzle [1049]on April 18, 2020 | [1050]prev | [1051]next [1052][–] I only use celery for sending out emails. It’s overkill.

I wonder how many other people have celery just for email.

[s.gif]

[1053]tchaffee [1054]on April 18, 2020 | [1055]prev | [1056]next [1057][–] McDonald's is very often a love or hate divide as you can already see from some of the comments here. You could prevent that distraction by using a generic food takeout store and ask people to imagine their favorite. The article will resonate with a larger audience, and the comments will be higher quality.

[s.gif]

[1058]ljvmiranda [1059]on April 18, 2020 | [1060]parent | [1061]next [1062][–] Hi author here, definitely didn't intend and expected that! I'm mostly drawing from my own experience and that insight while ordering food inside Mcdo.

[s.gif]

[1063]tchaffee [1064]on April 18, 2020 | [1065]root | [1066]parent | [1067]next [1068][–] As someone who also does technical writing, I agree you should draw from your own experience.

It can be hard to find the right analogy. If the subject of the analogy is enough of a hot topic, it will get attention itself. As you can see, you've got comments in here even talking about how McDonald's isn't faster with their new system, or how they could have better optimized for customers, links to articles about McDonald's business model etc. Some of the earlier negative comments about McDonald's were deleted - probably due to downvotes. Since my advice to other writers was sincere and I believe useful, I'm keeping my comment.

For sure I'm not expecting you to change your article. Just hoping that my tip might help you with future technical writing. If not, no worries.

[s.gif]

[1069]alanfranz [1070]on April 18, 2020 | [1071]prev | [1072]next [1073][–] And, of course, you need multiple separate components because Python/Flask has no central "application" concept,there are multiple, stateless processes.

Had you got e.g. a Java app running with a multithread application server model, you could serve and process everything within a single process. No Celery, no Redis, no MQ.

This doesn't mean that the above stack has no use. But, whenever picking a tech, you should understand the use case. The "simpler" Python/Flask solution has an increased complexity when the task at hand is not simple anymore.

[s.gif]

[1074]icebraining [1075]on April 18, 2020 | [1076]parent | [1077]next [1078][–] > Python/Flask has no central "application" concept,

They do, it's a WSGI application. Flask has been multithreaded for many years. Python also has multi-process queues that don't need an extra process.

[s.gif]

[1079]alanfranz [1080]on April 18, 2020 | [1081]root | [1082]parent | [1083]next [1084][–] WSGI is purely an interface between a webserver and python. What has WSGI to do with state?

The application server model makes it so there's a running application, with a state, and which exposes an HTTP endpoint.

> Flask has been multithreaded for many years

So? You run a blocking thread to performing a long-running task in Flask? With Python? Try, then report what you find.

Flask/Django are mostly designed to work with a stateless approach. Nothing wrong with that, but it's got drawbacks.

> multi-process queues that don't need an extra process.

More processes usually imply more complexity. And still, since you don't have a central application with a state, you NEED an extra piece to manage the result from the queue.

[s.gif]

[1085]icebraining [1086]on April 18, 2020 | [1087]root | [1088]parent | [1089]next [1090][–] > So? You run a blocking thread to performing a long-running task in Flask? With Python? Try, then report what you find.

I did it for years. It works just fine. The GIL is essentially like running an app on a single core, which works just fine for many use cases. CPU cores are quite powerful.

> More processes usually imply more complexity.

Right, but I'm only saying you can have more processes without requiring Redis.

> And still, since you don't have a central application with a state, you NEED an extra piece to manage the result from the queue.

A regular thread can do that.

[s.gif]

[1091]WJW [1092]on April 18, 2020 | [1093]parent | [1094]prev | [1095]next [1096][–] When the task complexity rises further, splitting out the message queue and workers into separate processes makes sense again. That way, you can easily scale worker capacity up and down and you can restart your web server processes without having to worry about background job persistence since that is handled by the message queue.

[s.gif]

[1097]alanfranz [1098]on April 18, 2020 | [1099]root | [1100]parent | [1101]next [1102][–] Sure. You can do the same with the application server model. But you haven't to as long as you don't want to.

[s.gif]

[1103]polote [1104]on April 18, 2020 | [1105]parent | [1106]prev | [1107]next [1108][–] It has nothing to do with Python, there a plenty of async web python framework.

[s.gif]

[1109]alanfranz [1110]on April 18, 2020 | [1111]root | [1112]parent | [1113]next [1114][–] I wrote Python/Flask because the application server model is inherently flawed in Python, while Flask is not asynchronous AFAIK; you MUST use an async model (because Python and multithreading still don't work well together), you can't use threads for long-running tasks.

[s.gif]

[1115]pupdogg [1116]on April 18, 2020 | [1117]prev [1118][–] With all due respect, my recent experiences ordering at McDonald's have been nothing short of horrible! As nice as the kiosk is, it has taken the accountability factor for your order out of the picture. I vividly recall getting blank stares from employees when asked "how much longer until my order is complete?". My past few visits (11 to be specific from 11/19 thru 2/20) have yielded 8 minutes of wait time on average. This is ordering inside the facility and at 5 different locations. Last I recall, it used to be a lot faster...I think between 1-3mins tops! I can't say the same for drive-thru though...seems like any orders from the drive through are always tagged with a higher priority. I do remember this since I was in my teens in the late 90s. Though it looked like a mainframe system, McDonald's did have a countdown timer that would initiate on orders. I'm all for tech and automating queues...but humans are complex beings and until the gap is bridged, I think we have a lot more room for improvement!

[s.gif]

[1119]jessaustin [1120]on April 18, 2020 | [1121]parent [1122][–] Drive-through is higher priority at most restaurants, because the customer can drive away after ordering but before paying.

[s.gif]

Join us for [1123]AI Startup School this June 16-17 in San Francisco!

[1124]Guidelines | [1125]FAQ | [1126]Lists | [1127]API | [1128]Security | [1129]Legal | [1130]Apply to YC | [1131]Contact Search: _________________

References

Visible links: 1. https://news.ycombinator.com/ 2. https://news.ycombinator.com/news 3. https://news.ycombinator.com/newest 4. https://news.ycombinator.com/front 5. https://news.ycombinator.com/newcomments 6. https://news.ycombinator.com/ask 7. https://news.ycombinator.com/show 8. https://news.ycombinator.com/jobs 9. https://news.ycombinator.com/submit 10. https://news.ycombinator.com/login?goto=item?id=22901856 11. https://ljvmiranda921.github.io/notebook/2019/11/08/flask-redis-celery-mcdo/ 12. https://news.ycombinator.com/from?site=ljvmiranda921.github.io 13. https://news.ycombinator.com/user?id=feross 14. https://news.ycombinator.com/item?id=22901856 15. https://news.ycombinator.com/hide?id=22901856&goto=item?id=22901856 16. https://hn.algolia.com/?query=Why do we need Flask, Celery, and Redis?&type=story&dateRange=all&sort=byDate&storyText=false&prefix&page=0 17. https://news.ycombinator.com/fave?id=22901856&auth=d7718e8a8539ac3789c85074521380cd4f0fa78b 18. https://news.ycombinator.com/item?id=22901856 19. https://news.ycombinator.com/user?id=sandGorgon 20. https://news.ycombinator.com/item?id=22907390 21. https://news.ycombinator.com/item?id=22901856#22906986 22. javascript:void(0) 23. https://www.integralist.co.uk/posts/python-asyncio/#running-async-code-in-the-repl 24. https://news.ycombinator.com/user?id=pinkbeanz 25. https://news.ycombinator.com/item?id=22907475 26. https://news.ycombinator.com/item?id=22901856#22907390 27. https://news.ycombinator.com/item?id=22901856#22907584 28. javascript:void(0) 29. https://news.ycombinator.com/user?id=lmeyerov 30. https://news.ycombinator.com/item?id=22911497 31. https://news.ycombinator.com/item?id=22901856#22907390 32. https://news.ycombinator.com/item?id=22901856#22907475 33. https://news.ycombinator.com/item?id=22901856#22910922 34. javascript:void(0) 35. https://news.ycombinator.com/user?id=stavros 36. https://news.ycombinator.com/item?id=22910922 37. https://news.ycombinator.com/item?id=22901856#22907390 38. https://news.ycombinator.com/item?id=22901856#22907475 39. https://news.ycombinator.com/item?id=22901856#22911497 40. https://news.ycombinator.com/item?id=22901856#22907584 41. javascript:void(0) 42. https://news.ycombinator.com/user?id=CalRobert 43. https://news.ycombinator.com/item?id=22911399 44. https://news.ycombinator.com/item?id=22901856#22907390 45. https://news.ycombinator.com/item?id=22901856#22910922 46. https://news.ycombinator.com/item?id=22901856#22907584 47. javascript:void(0) 48. https://news.ycombinator.com/user?id=stavros 49. https://news.ycombinator.com/item?id=22911421 50. https://news.ycombinator.com/item?id=22901856#22907390 51. https://news.ycombinator.com/item?id=22901856#22911399 52. https://news.ycombinator.com/item?id=22901856#22907584 53. javascript:void(0) 54. https://news.ycombinator.com/user?id=normalnorm 55. https://news.ycombinator.com/item?id=22914057 56. https://news.ycombinator.com/item?id=22901856#22907390 57. https://news.ycombinator.com/item?id=22901856#22911421 58. https://news.ycombinator.com/item?id=22901856#22907584 59. javascript:void(0) 60. https://news.ycombinator.com/user?id=stavros 61. https://news.ycombinator.com/item?id=22914795 62. https://news.ycombinator.com/item?id=22901856#22907390 63. https://news.ycombinator.com/item?id=22901856#22914057 64. https://news.ycombinator.com/item?id=22901856#22907584 65. javascript:void(0) 66. https://news.ycombinator.com/user?id=rumanator 67. https://news.ycombinator.com/item?id=22915351 68. https://news.ycombinator.com/item?id=22901856#22907390 69. https://news.ycombinator.com/item?id=22901856#22914795 70. https://news.ycombinator.com/item?id=22901856#22907584 71. javascript:void(0) 72. https://news.ycombinator.com/user?id=stavros 73. https://news.ycombinator.com/item?id=22915458 74. https://news.ycombinator.com/item?id=22901856#22907390 75. https://news.ycombinator.com/item?id=22901856#22915351 76. https://news.ycombinator.com/item?id=22901856#22907584 77. javascript:void(0) 78. https://news.ycombinator.com/user?id=rumanator 79. https://news.ycombinator.com/item?id=22915492 80. https://news.ycombinator.com/item?id=22901856#22907390 81. https://news.ycombinator.com/item?id=22901856#22915458 82. https://news.ycombinator.com/item?id=22901856#22907584 83. javascript:void(0) 84. https://news.ycombinator.com/user?id=heyoni 85. https://news.ycombinator.com/item?id=22921383 86. https://news.ycombinator.com/item?id=22901856#22907390 87. https://news.ycombinator.com/item?id=22901856#22915492 88. https://news.ycombinator.com/item?id=22901856#22915520 89. javascript:void(0) 90. https://news.ycombinator.com/item?id=22911497 91. https://news.ycombinator.com/user?id=stavros 92. https://news.ycombinator.com/item?id=22915520 93. https://news.ycombinator.com/item?id=22901856#22907390 94. https://news.ycombinator.com/item?id=22901856#22915492 95. https://news.ycombinator.com/item?id=22901856#22921383 96. https://news.ycombinator.com/item?id=22901856#22907584 97. javascript:void(0) 98. https://news.ycombinator.com/user?id=BiteCode_dev 99. https://news.ycombinator.com/item?id=22907584 100. https://news.ycombinator.com/item?id=22901856#22907390 101. https://news.ycombinator.com/item?id=22901856#22907475 102. https://news.ycombinator.com/item?id=22901856#22907635 103. javascript:void(0) 104. https://news.ycombinator.com/user?id=arp242 105. https://news.ycombinator.com/item?id=22907635 106. https://news.ycombinator.com/item?id=22901856#22907390 107. https://news.ycombinator.com/item?id=22901856#22907584 108. https://news.ycombinator.com/item?id=22901856#22910617 109. javascript:void(0) 110. https://news.ycombinator.com/user?id=slashdev 111. https://news.ycombinator.com/item?id=22907891 112. https://news.ycombinator.com/item?id=22901856#22907390 113. https://news.ycombinator.com/item?id=22901856#22907635 114. https://news.ycombinator.com/item?id=22901856#22907695 115. javascript:void(0) 116. https://news.ycombinator.com/user?id=sandGorgon 117. https://news.ycombinator.com/item?id=22908828 118. https://news.ycombinator.com/item?id=22901856#22907390 119. https://news.ycombinator.com/item?id=22901856#22907891 120. https://news.ycombinator.com/item?id=22901856#22908283 121. javascript:void(0) 122. https://www.mail-archive.com/python-dev@python.org/msg108063.html 123. https://news.ycombinator.com/user?id=amelius 124. https://news.ycombinator.com/item?id=22909875 125. https://news.ycombinator.com/item?id=22901856#22907390 126. https://news.ycombinator.com/item?id=22901856#22908828 127. https://news.ycombinator.com/item?id=22901856#22908283 128. javascript:void(0) 129. https://news.ycombinator.com/user?id=YawningAngel 130. https://news.ycombinator.com/item?id=22911973 131. https://news.ycombinator.com/item?id=22901856#22907390 132. https://news.ycombinator.com/item?id=22901856#22909875 133. https://news.ycombinator.com/item?id=22901856#22908283 134. javascript:void(0) 135. https://news.ycombinator.com/user?id=antoinealb 136. https://news.ycombinator.com/item?id=22908283 137. https://news.ycombinator.com/item?id=22901856#22907390 138. https://news.ycombinator.com/item?id=22901856#22907891 139. https://news.ycombinator.com/item?id=22901856#22908828 140. https://news.ycombinator.com/item?id=22901856#22908492 141. javascript:void(0) 142. https://news.ycombinator.com/user?id=slashdev 143. https://news.ycombinator.com/item?id=22908881 144. https://news.ycombinator.com/item?id=22901856#22907390 145. https://news.ycombinator.com/item?id=22901856#22908283 146. https://news.ycombinator.com/item?id=22901856#22908421 147. javascript:void(0) 148. https://news.ycombinator.com/user?id=zepto 149. https://news.ycombinator.com/item?id=22908421 150. https://news.ycombinator.com/item?id=22901856#22907390 151. https://news.ycombinator.com/item?id=22901856#22908283 152. https://news.ycombinator.com/item?id=22901856#22908881 153. https://news.ycombinator.com/item?id=22901856#22908492 154. javascript:void(0) 155. https://news.ycombinator.com/user?id=quacker 156. https://news.ycombinator.com/item?id=22908518 157. https://news.ycombinator.com/item?id=22901856#22907390 158. https://news.ycombinator.com/item?id=22901856#22908421 159. https://news.ycombinator.com/item?id=22901856#22908567 160. javascript:void(0) 161. https://docs.python.org/3.6/library/multiprocessing.html 162. https://news.ycombinator.com/user?id=goostavos 163. https://news.ycombinator.com/item?id=22908995 164. https://news.ycombinator.com/item?id=22901856#22907390 165. https://news.ycombinator.com/item?id=22901856#22908518 166. https://news.ycombinator.com/item?id=22901856#22908567 167. javascript:void(0) 168. https://news.ycombinator.com/user?id=kbutler 169. https://news.ycombinator.com/item?id=22908567 170. https://news.ycombinator.com/item?id=22901856#22907390 171. https://news.ycombinator.com/item?id=22901856#22908421 172. https://news.ycombinator.com/item?id=22901856#22908518 173. https://news.ycombinator.com/item?id=22901856#22908492 174. javascript:void(0) 175. https://docs.python.org/2/library/multiprocessing.html 176. https://news.ycombinator.com/user?id=quacker 177. https://news.ycombinator.com/item?id=22908492 178. https://news.ycombinator.com/item?id=22901856#22907390 179. https://news.ycombinator.com/item?id=22901856#22907891 180. https://news.ycombinator.com/item?id=22901856#22908283 181. https://news.ycombinator.com/item?id=22901856#22908471 182. javascript:void(0) 183. https://news.ycombinator.com/user?id=throwaway894345 184. https://news.ycombinator.com/item?id=22911120 185. https://news.ycombinator.com/item?id=22901856#22907390 186. https://news.ycombinator.com/item?id=22901856#22908492 187. https://news.ycombinator.com/item?id=22901856#22908471 188. javascript:void(0) 189. https://news.ycombinator.com/user?id=marcosdumay 190. https://news.ycombinator.com/item?id=22908471 191. https://news.ycombinator.com/item?id=22901856#22907390 192. https://news.ycombinator.com/item?id=22901856#22907891 193. https://news.ycombinator.com/item?id=22901856#22908492 194. https://news.ycombinator.com/item?id=22901856#22907695 195. javascript:void(0) 196. https://news.ycombinator.com/user?id=throwaway894345 197. https://news.ycombinator.com/item?id=22910782 198. https://news.ycombinator.com/item?id=22901856#22907390 199. https://news.ycombinator.com/item?id=22901856#22908471 200. https://news.ycombinator.com/item?id=22901856#22907695 201. javascript:void(0) 202. https://news.ycombinator.com/user?id=dnautics 203. https://news.ycombinator.com/item?id=22912886 204. https://news.ycombinator.com/item?id=22901856#22907390 205. https://news.ycombinator.com/item?id=22901856#22910782 206. https://news.ycombinator.com/item?id=22901856#22911649 207. javascript:void(0) 208. https://news.ycombinator.com/user?id=throwaway894345 209. https://news.ycombinator.com/item?id=22916753 210. https://news.ycombinator.com/item?id=22901856#22907390 211. https://news.ycombinator.com/item?id=22901856#22912886 212. https://news.ycombinator.com/item?id=22901856#22911649 213. javascript:void(0) 214. https://news.ycombinator.com/user?id=marcosdumay 215. https://news.ycombinator.com/item?id=22911649 216. https://news.ycombinator.com/item?id=22901856#22907390 217. https://news.ycombinator.com/item?id=22901856#22910782 218. https://news.ycombinator.com/item?id=22901856#22912886 219. https://news.ycombinator.com/item?id=22901856#22907695 220. javascript:void(0) 221. https://news.ycombinator.com/user?id=jatone 222. https://news.ycombinator.com/item?id=22915768 223. https://news.ycombinator.com/item?id=22901856#22907390 224. https://news.ycombinator.com/item?id=22901856#22911649 225. https://news.ycombinator.com/item?id=22901856#22907695 226. javascript:void(0) 227. https://news.ycombinator.com/user?id=marcosdumay 228. https://news.ycombinator.com/item?id=22916172 229. https://news.ycombinator.com/item?id=22901856#22907390 230. https://news.ycombinator.com/item?id=22901856#22915768 231. https://news.ycombinator.com/item?id=22901856#22907695 232. javascript:void(0) 233. https://news.ycombinator.com/user?id=meowface 234. https://news.ycombinator.com/item?id=22907695 235. https://news.ycombinator.com/item?id=22901856#22907390 236. https://news.ycombinator.com/item?id=22901856#22907635 237. https://news.ycombinator.com/item?id=22901856#22907891 238. https://news.ycombinator.com/item?id=22901856#22910617 239. javascript:void(0) 240. https://glyph.twistedmatrix.com/2014/02/unyielding.html 241. https://news.ycombinator.com/user?id=sandGorgon 242. https://news.ycombinator.com/item?id=22907716 243. https://news.ycombinator.com/item?id=22901856#22907390 244. https://news.ycombinator.com/item?id=22901856#22907695 245. https://news.ycombinator.com/item?id=22901856#22910617 246. javascript:void(0) 247. https://news.ycombinator.com/user?id=meowface 248. https://news.ycombinator.com/item?id=22907776 249. https://news.ycombinator.com/item?id=22901856#22907390 250. https://news.ycombinator.com/item?id=22901856#22907716 251. https://news.ycombinator.com/item?id=22901856#22910110 252. javascript:void(0) 253. https://news.ycombinator.com/user?id=quacker 254. https://news.ycombinator.com/item?id=22908536 255. https://news.ycombinator.com/item?id=22901856#22907390 256. https://news.ycombinator.com/item?id=22901856#22907776 257. https://news.ycombinator.com/item?id=22901856#22910110 258. javascript:void(0) 259. https://news.ycombinator.com/user?id=zenhack 260. https://news.ycombinator.com/item?id=22912246 261. https://news.ycombinator.com/item?id=22901856#22907390 262. https://news.ycombinator.com/item?id=22901856#22908536 263. https://news.ycombinator.com/item?id=22901856#22909185 264. javascript:void(0) 265. https://news.ycombinator.com/user?id=infinite8s 266. https://news.ycombinator.com/item?id=22909185 267. https://news.ycombinator.com/item?id=22901856#22907390 268. https://news.ycombinator.com/item?id=22901856#22908536 269. https://news.ycombinator.com/item?id=22901856#22912246 270. https://news.ycombinator.com/item?id=22901856#22910110 271. javascript:void(0) 272. https://news.ycombinator.com/user?id=sateesh 273. https://news.ycombinator.com/item?id=22910110 274. https://news.ycombinator.com/item?id=22901856#22907390 275. https://news.ycombinator.com/item?id=22901856#22907716 276. https://news.ycombinator.com/item?id=22901856#22907776 277. https://news.ycombinator.com/item?id=22901856#22911136 278. javascript:void(0) 279. https://news.ycombinator.com/user?id=throwaway894345 280. https://news.ycombinator.com/item?id=22911136 281. https://news.ycombinator.com/item?id=22901856#22907390 282. https://news.ycombinator.com/item?id=22901856#22907716 283. https://news.ycombinator.com/item?id=22901856#22910110 284. https://news.ycombinator.com/item?id=22901856#22910617 285. javascript:void(0) 286. https://news.ycombinator.com/user?id=meowface 287. https://news.ycombinator.com/item?id=22921254 288. https://news.ycombinator.com/item?id=22901856#22907390 289. https://news.ycombinator.com/item?id=22901856#22911136 290. https://news.ycombinator.com/item?id=22901856#22910617 291. javascript:void(0) 292. https://news.ycombinator.com/user?id=throwaway894345 293. https://news.ycombinator.com/item?id=22910617 294. https://news.ycombinator.com/item?id=22901856#22907390 295. https://news.ycombinator.com/item?id=22901856#22907635 296. https://news.ycombinator.com/item?id=22901856#22913823 297. javascript:void(0) 298. https://news.ycombinator.com/user?id=sandGorgon 299. https://news.ycombinator.com/item?id=22910902 300. https://news.ycombinator.com/item?id=22901856#22907390 301. https://news.ycombinator.com/item?id=22901856#22910617 302. https://news.ycombinator.com/item?id=22901856#22913823 303. javascript:void(0) 304. https://github.com/tiangolo/fastapi/ 305. https://news.ycombinator.com/user?id=solidasparagus 306. https://news.ycombinator.com/item?id=22913823 307. https://news.ycombinator.com/item?id=22901856#22907390 308. https://news.ycombinator.com/item?id=22901856#22910617 309. https://news.ycombinator.com/item?id=22901856#22913738 310. javascript:void(0) 311. https://news.ycombinator.com/user?id=jatone 312. https://news.ycombinator.com/item?id=22915756 313. https://news.ycombinator.com/item?id=22901856#22907390 314. https://news.ycombinator.com/item?id=22901856#22913823 315. https://news.ycombinator.com/item?id=22901856#22913738 316. javascript:void(0) 317. https://news.ycombinator.com/user?id=hackworks 318. https://news.ycombinator.com/item?id=22916067 319. https://news.ycombinator.com/item?id=22901856#22907390 320. https://news.ycombinator.com/item?id=22901856#22915756 321. https://news.ycombinator.com/item?id=22901856#22913738 322. javascript:void(0) 323. https://news.ycombinator.com/user?id=zaro 324. https://news.ycombinator.com/item?id=22913738 325. https://news.ycombinator.com/item?id=22901856#22907390 326. https://news.ycombinator.com/item?id=22901856#22913823 327. https://news.ycombinator.com/item?id=22901856#22907753 328. javascript:void(0) 329. https://news.ycombinator.com/user?id=jakearmitage 330. https://news.ycombinator.com/item?id=22907753 331. https://news.ycombinator.com/item?id=22901856#22907390 332. https://news.ycombinator.com/item?id=22901856#22913738 333. https://news.ycombinator.com/item?id=22901856#22906986 334. javascript:void(0) 335. https://news.ycombinator.com/user?id=sandGorgon 336. https://news.ycombinator.com/item?id=22908761 337. https://news.ycombinator.com/item?id=22901856#22907390 338. https://news.ycombinator.com/item?id=22901856#22907753 339. https://news.ycombinator.com/item?id=22901856#22908182 340. javascript:void(0) 341. https://twitter.com/ibuildthecloud/status/1187529098886664193?s=19 342. https://twitter.com/ibuildthecloud/status/1187538210152308736?s=19 343. https://news.ycombinator.com/user?id=throwaway894345 344. https://news.ycombinator.com/item?id=22911062 345. https://news.ycombinator.com/item?id=22901856#22907390 346. https://news.ycombinator.com/item?id=22901856#22908761 347. https://news.ycombinator.com/item?id=22901856#22908182 348. javascript:void(0) 349. https://news.ycombinator.com/user?id=ForHackernews 350. https://news.ycombinator.com/item?id=22911457 351. https://news.ycombinator.com/item?id=22901856#22907390 352. https://news.ycombinator.com/item?id=22901856#22911062 353. https://news.ycombinator.com/item?id=22901856#22912417 354. javascript:void(0) 355. https://news.ycombinator.com/user?id=kelnos 356. https://news.ycombinator.com/item?id=22911890 357. https://news.ycombinator.com/item?id=22901856#22907390 358. https://news.ycombinator.com/item?id=22901856#22911457 359. https://news.ycombinator.com/item?id=22901856#22912733 360. javascript:void(0) 361. https://news.ycombinator.com/user?id=ForHackernews 362. https://news.ycombinator.com/item?id=22914250 363. https://news.ycombinator.com/item?id=22901856#22907390 364. https://news.ycombinator.com/item?id=22901856#22911890 365. https://news.ycombinator.com/item?id=22901856#22912733 366. javascript:void(0) 367. https://news.ycombinator.com/user?id=morelisp 368. https://news.ycombinator.com/item?id=22914464 369. https://news.ycombinator.com/item?id=22901856#22907390 370. https://news.ycombinator.com/item?id=22901856#22914250 371. https://news.ycombinator.com/item?id=22901856#22915801 372. javascript:void(0) 373. https://news.ycombinator.com/user?id=jatone 374. https://news.ycombinator.com/item?id=22915801 375. https://news.ycombinator.com/item?id=22901856#22907390 376. https://news.ycombinator.com/item?id=22901856#22914250 377. https://news.ycombinator.com/item?id=22901856#22914464 378. https://news.ycombinator.com/item?id=22901856#22912733 379. javascript:void(0) 380. https://news.ycombinator.com/user?id=throwaway894345 381. https://news.ycombinator.com/item?id=22912733 382. https://news.ycombinator.com/item?id=22901856#22907390 383. https://news.ycombinator.com/item?id=22901856#22911457 384. https://news.ycombinator.com/item?id=22901856#22911890 385. https://news.ycombinator.com/item?id=22901856#22915786 386. javascript:void(0) 387. https://news.ycombinator.com/user?id=petre 388. https://news.ycombinator.com/item?id=22914293 389. https://news.ycombinator.com/item?id=22901856#22907390 390. https://news.ycombinator.com/item?id=22901856#22912733 391. https://news.ycombinator.com/item?id=22901856#22915786 392. javascript:void(0) 393. https://news.ycombinator.com/user?id=jatone 394. https://news.ycombinator.com/item?id=22915808 395. https://news.ycombinator.com/item?id=22901856#22907390 396. https://news.ycombinator.com/item?id=22901856#22914293 397. https://news.ycombinator.com/item?id=22901856#22915786 398. javascript:void(0) 399. https://news.ycombinator.com/user?id=jatone 400. https://news.ycombinator.com/item?id=22915786 401. https://news.ycombinator.com/item?id=22901856#22907390 402. https://news.ycombinator.com/item?id=22901856#22911457 403. https://news.ycombinator.com/item?id=22901856#22912733 404. https://news.ycombinator.com/item?id=22901856#22912417 405. javascript:void(0) 406. https://news.ycombinator.com/user?id=joshuamorton 407. https://news.ycombinator.com/item?id=22912417 408. https://news.ycombinator.com/item?id=22901856#22907390 409. https://news.ycombinator.com/item?id=22901856#22911062 410. https://news.ycombinator.com/item?id=22901856#22911457 411. https://news.ycombinator.com/item?id=22901856#22908182 412. javascript:void(0) 413. https://news.ycombinator.com/user?id=throwaway894345 414. https://news.ycombinator.com/item?id=22912798 415. https://news.ycombinator.com/item?id=22901856#22907390 416. https://news.ycombinator.com/item?id=22901856#22912417 417. https://news.ycombinator.com/item?id=22901856#22908182 418. javascript:void(0) 419. https://news.ycombinator.com/user?id=morelisp 420. https://news.ycombinator.com/item?id=22908182 421. https://news.ycombinator.com/item?id=22901856#22907390 422. https://news.ycombinator.com/item?id=22901856#22907753 423. https://news.ycombinator.com/item?id=22901856#22908761 424. https://news.ycombinator.com/item?id=22901856#22906986 425. javascript:void(0) 426. https://news.ycombinator.com/user?id=throwaway894345 427. https://news.ycombinator.com/item?id=22911144 428. https://news.ycombinator.com/item?id=22901856#22907390 429. https://news.ycombinator.com/item?id=22901856#22908182 430. https://news.ycombinator.com/item?id=22901856#22909080 431. javascript:void(0) 432. https://news.ycombinator.com/user?id=morelisp 433. https://news.ycombinator.com/item?id=22911771 434. https://news.ycombinator.com/item?id=22901856#22907390 435. https://news.ycombinator.com/item?id=22901856#22911144 436. https://news.ycombinator.com/item?id=22901856#22909080 437. javascript:void(0) 438. https://news.ycombinator.com/user?id=dnautics 439. https://news.ycombinator.com/item?id=22914091 440. https://news.ycombinator.com/item?id=22901856#22907390 441. https://news.ycombinator.com/item?id=22901856#22911771 442. https://news.ycombinator.com/item?id=22901856#22912831 443. javascript:void(0) 444. https://news.ycombinator.com/user?id=throwaway894345 445. https://news.ycombinator.com/item?id=22912831 446. https://news.ycombinator.com/item?id=22901856#22907390 447. https://news.ycombinator.com/item?id=22901856#22911771 448. https://news.ycombinator.com/item?id=22901856#22914091 449. https://news.ycombinator.com/item?id=22901856#22909080 450. javascript:void(0) 451. https://news.ycombinator.com/user?id=morelisp 452. https://news.ycombinator.com/item?id=22914450 453. https://news.ycombinator.com/item?id=22901856#22907390 454. https://news.ycombinator.com/item?id=22901856#22912831 455. https://news.ycombinator.com/item?id=22901856#22909080 456. javascript:void(0) 457. https://news.ycombinator.com/user?id=jatone 458. https://news.ycombinator.com/item?id=22915890 459. https://news.ycombinator.com/item?id=22901856#22907390 460. https://news.ycombinator.com/item?id=22901856#22914450 461. https://news.ycombinator.com/item?id=22901856#22909080 462. javascript:void(0) 463. https://news.ycombinator.com/user?id=morelisp 464. https://news.ycombinator.com/item?id=22918616 465. https://news.ycombinator.com/item?id=22901856#22907390 466. https://news.ycombinator.com/item?id=22901856#22915890 467. https://news.ycombinator.com/item?id=22901856#22909080 468. javascript:void(0) 469. https://news.ycombinator.com/user?id=takeda 470. https://news.ycombinator.com/item?id=22909080 471. https://news.ycombinator.com/item?id=22901856#22907390 472. https://news.ycombinator.com/item?id=22901856#22908182 473. https://news.ycombinator.com/item?id=22901856#22911144 474. https://news.ycombinator.com/item?id=22901856#22908469 475. javascript:void(0) 476. https://github.com/takeda/example_python_project/blob/master/setup.cfg 477. https://news.ycombinator.com/user?id=mdtusz 478. https://news.ycombinator.com/item?id=22908469 479. https://news.ycombinator.com/item?id=22901856#22907390 480. https://news.ycombinator.com/item?id=22901856#22908182 481. https://news.ycombinator.com/item?id=22901856#22909080 482. https://news.ycombinator.com/item?id=22901856#22906986 483. javascript:void(0) 484. https://news.ycombinator.com/user?id=takeda 485. https://news.ycombinator.com/item?id=22908994 486. https://news.ycombinator.com/item?id=22901856#22907390 487. https://news.ycombinator.com/item?id=22901856#22908469 488. https://news.ycombinator.com/item?id=22901856#22906986 489. javascript:void(0) 490. https://news.ycombinator.com/user?id=jessaustin 491. https://news.ycombinator.com/item?id=22911325 492. https://news.ycombinator.com/item?id=22901856#22907390 493. https://news.ycombinator.com/item?id=22901856#22908994 494. https://news.ycombinator.com/item?id=22901856#22906986 495. javascript:void(0) 496. https://news.ycombinator.com/user?id=waterside81 497. https://news.ycombinator.com/item?id=22906986 498. https://news.ycombinator.com/item?id=22901856#22907390 499. https://news.ycombinator.com/item?id=22901856#22907496 500. javascript:void(0) 501. https://www.businessinsider.com/mcdonalds-spending-millions-on-drive-thru-2019-10 502. https://news.ycombinator.com/user?id=skrebbel 503. https://news.ycombinator.com/item?id=22907429 504. https://news.ycombinator.com/item?id=22901856#22906986 505. https://news.ycombinator.com/item?id=22901856#22909039 506. javascript:void(0) 507. https://news.ycombinator.com/user?id=smacktoward 508. https://news.ycombinator.com/item?id=22908199 509. https://news.ycombinator.com/item?id=22901856#22906986 510. https://news.ycombinator.com/item?id=22901856#22907429 511. https://news.ycombinator.com/item?id=22901856#22907480 512. javascript:void(0) 513. https://news.ycombinator.com/user?id=toyg 514. https://news.ycombinator.com/item?id=22910883 515. https://news.ycombinator.com/item?id=22901856#22906986 516. https://news.ycombinator.com/item?id=22901856#22908199 517. https://news.ycombinator.com/item?id=22901856#22907480 518. javascript:void(0) 519. https://news.ycombinator.com/user?id=arrty88 520. https://news.ycombinator.com/item?id=22907480 521. https://news.ycombinator.com/item?id=22901856#22906986 522. https://news.ycombinator.com/item?id=22901856#22907429 523. https://news.ycombinator.com/item?id=22901856#22908199 524. https://news.ycombinator.com/item?id=22901856#22907846 525. javascript:void(0) 526. https://news.ycombinator.com/user?id=darkerside 527. https://news.ycombinator.com/item?id=22907563 528. https://news.ycombinator.com/item?id=22901856#22906986 529. https://news.ycombinator.com/item?id=22901856#22907480 530. https://news.ycombinator.com/item?id=22901856#22907944 531. javascript:void(0) 532. https://news.ycombinator.com/user?id=dillonmckay 533. https://news.ycombinator.com/item?id=22910824 534. https://news.ycombinator.com/item?id=22901856#22906986 535. https://news.ycombinator.com/item?id=22901856#22907563 536. https://news.ycombinator.com/item?id=22901856#22907944 537. javascript:void(0) 538. https://news.ycombinator.com/user?id=loblollyboy 539. https://news.ycombinator.com/item?id=22907944 540. https://news.ycombinator.com/item?id=22901856#22906986 541. https://news.ycombinator.com/item?id=22901856#22907480 542. https://news.ycombinator.com/item?id=22901856#22907563 543. https://news.ycombinator.com/item?id=22901856#22907846 544. javascript:void(0) 545. https://news.ycombinator.com/user?id=jiofih 546. https://news.ycombinator.com/item?id=22908254 547. https://news.ycombinator.com/item?id=22901856#22906986 548. https://news.ycombinator.com/item?id=22901856#22907944 549. https://news.ycombinator.com/item?id=22901856#22907846 550. javascript:void(0) 551. https://news.ycombinator.com/user?id=sli 552. https://news.ycombinator.com/item?id=22909979 553. https://news.ycombinator.com/item?id=22901856#22906986 554. https://news.ycombinator.com/item?id=22901856#22908254 555. https://news.ycombinator.com/item?id=22901856#22910152 556. javascript:void(0) 557. https://news.ycombinator.com/user?id=rhizome 558. https://news.ycombinator.com/item?id=22910152 559. https://news.ycombinator.com/item?id=22901856#22906986 560. https://news.ycombinator.com/item?id=22901856#22908254 561. https://news.ycombinator.com/item?id=22901856#22909979 562. https://news.ycombinator.com/item?id=22901856#22907846 563. javascript:void(0) 564. https://news.ycombinator.com/user?id=jessaustin 565. https://news.ycombinator.com/item?id=22911353 566. https://news.ycombinator.com/item?id=22901856#22906986 567. https://news.ycombinator.com/item?id=22901856#22910152 568. https://news.ycombinator.com/item?id=22901856#22910815 569. javascript:void(0) 570. https://news.ycombinator.com/user?id=freehunter 571. https://news.ycombinator.com/item?id=22910815 572. https://news.ycombinator.com/item?id=22901856#22906986 573. https://news.ycombinator.com/item?id=22901856#22910152 574. https://news.ycombinator.com/item?id=22901856#22911353 575. https://news.ycombinator.com/item?id=22901856#22911242 576. javascript:void(0) 577. https://news.ycombinator.com/user?id=AlphaSite 578. https://news.ycombinator.com/item?id=22912418 579. https://news.ycombinator.com/item?id=22901856#22906986 580. https://news.ycombinator.com/item?id=22901856#22910815 581. https://news.ycombinator.com/item?id=22901856#22911242 582. javascript:void(0) 583. https://news.ycombinator.com/user?id=seized 584. https://news.ycombinator.com/item?id=22911242 585. https://news.ycombinator.com/item?id=22901856#22906986 586. https://news.ycombinator.com/item?id=22901856#22910152 587. https://news.ycombinator.com/item?id=22901856#22910815 588. https://news.ycombinator.com/item?id=22901856#22907846 589. javascript:void(0) 590. https://news.ycombinator.com/user?id=rhizome 591. https://news.ycombinator.com/item?id=22927860 592. https://news.ycombinator.com/item?id=22901856#22906986 593. https://news.ycombinator.com/item?id=22901856#22911242 594. https://news.ycombinator.com/item?id=22901856#22907846 595. javascript:void(0) 596. https://news.ycombinator.com/user?id=agumonkey 597. https://news.ycombinator.com/item?id=22907846 598. https://news.ycombinator.com/item?id=22901856#22906986 599. https://news.ycombinator.com/item?id=22901856#22907429 600. https://news.ycombinator.com/item?id=22901856#22907480 601. https://news.ycombinator.com/item?id=22901856#22909039 602. javascript:void(0) 603. https://news.ycombinator.com/user?id=cle 604. https://news.ycombinator.com/item?id=22909039 605. https://news.ycombinator.com/item?id=22901856#22906986 606. https://news.ycombinator.com/item?id=22901856#22907429 607. https://news.ycombinator.com/item?id=22901856#22907561 608. javascript:void(0) 609. https://news.ycombinator.com/user?id=agumonkey 610. https://news.ycombinator.com/item?id=22907561 611. https://news.ycombinator.com/item?id=22901856#22906986 612. https://news.ycombinator.com/item?id=22901856#22909039 613. https://news.ycombinator.com/item?id=22901856#22907033 614. javascript:void(0) 615. https://news.ycombinator.com/user?id=satvikpendem 616. https://news.ycombinator.com/item?id=22907932 617. https://news.ycombinator.com/item?id=22901856#22906986 618. https://news.ycombinator.com/item?id=22901856#22907561 619. https://news.ycombinator.com/item?id=22901856#22907704 620. javascript:void(0) 621. https://news.ycombinator.com/user?id=toyg 622. https://news.ycombinator.com/item?id=22910917 623. https://news.ycombinator.com/item?id=22901856#22906986 624. https://news.ycombinator.com/item?id=22901856#22907932 625. https://news.ycombinator.com/item?id=22901856#22909428 626. javascript:void(0) 627. https://news.ycombinator.com/user?id=marktangotango 628. https://news.ycombinator.com/item?id=22909428 629. https://news.ycombinator.com/item?id=22901856#22906986 630. https://news.ycombinator.com/item?id=22901856#22907932 631. https://news.ycombinator.com/item?id=22901856#22910917 632. https://news.ycombinator.com/item?id=22901856#22907704 633. javascript:void(0) 634. https://news.ycombinator.com/user?id=m463 635. https://news.ycombinator.com/item?id=22907704 636. https://news.ycombinator.com/item?id=22901856#22906986 637. https://news.ycombinator.com/item?id=22901856#22907561 638. https://news.ycombinator.com/item?id=22901856#22907932 639. https://news.ycombinator.com/item?id=22901856#22907033 640. javascript:void(0) 641. https://news.ycombinator.com/user?id=bigyikes 642. https://news.ycombinator.com/item?id=22910051 643. https://news.ycombinator.com/item?id=22901856#22906986 644. https://news.ycombinator.com/item?id=22901856#22907704 645. https://news.ycombinator.com/item?id=22901856#22907862 646. javascript:void(0) 647. https://news.ycombinator.com/user?id=m463 648. https://news.ycombinator.com/item?id=22910932 649. https://news.ycombinator.com/item?id=22901856#22906986 650. https://news.ycombinator.com/item?id=22901856#22910051 651. https://news.ycombinator.com/item?id=22901856#22907862 652. javascript:void(0) 653. https://news.ycombinator.com/user?id=agumonkey 654. https://news.ycombinator.com/item?id=22907862 655. https://news.ycombinator.com/item?id=22901856#22906986 656. https://news.ycombinator.com/item?id=22901856#22907704 657. https://news.ycombinator.com/item?id=22901856#22910051 658. https://news.ycombinator.com/item?id=22901856#22907033 659. javascript:void(0) 660. https://news.ycombinator.com/user?id=nebulous1 661. https://news.ycombinator.com/item?id=22907033 662. https://news.ycombinator.com/item?id=22901856#22906986 663. https://news.ycombinator.com/item?id=22901856#22907561 664. https://news.ycombinator.com/item?id=22901856#22907643 665. javascript:void(0) 666. https://news.ycombinator.com/user?id=spamizbad 667. https://news.ycombinator.com/item?id=22907643 668. https://news.ycombinator.com/item?id=22901856#22906986 669. https://news.ycombinator.com/item?id=22901856#22907033 670. https://news.ycombinator.com/item?id=22901856#22907300 671. javascript:void(0) 672. https://news.ycombinator.com/user?id=rootusrootus 673. https://news.ycombinator.com/item?id=22908416 674. https://news.ycombinator.com/item?id=22901856#22906986 675. https://news.ycombinator.com/item?id=22901856#22907643 676. https://news.ycombinator.com/item?id=22901856#22907300 677. javascript:void(0) 678. https://news.ycombinator.com/user?id=DeonPenny 679. https://news.ycombinator.com/item?id=22907300 680. https://news.ycombinator.com/item?id=22901856#22906986 681. https://news.ycombinator.com/item?id=22901856#22907643 682. https://news.ycombinator.com/item?id=22901856#22907424 683. javascript:void(0) 684. https://news.ycombinator.com/user?id=punnerud 685. https://news.ycombinator.com/item?id=22907424 686. https://news.ycombinator.com/item?id=22901856#22906986 687. https://news.ycombinator.com/item?id=22901856#22907300 688. https://news.ycombinator.com/item?id=22901856#22907031 689. javascript:void(0) 690. https://news.ycombinator.com/user?id=xenonite 691. https://news.ycombinator.com/item?id=22907031 692. https://news.ycombinator.com/item?id=22901856#22906986 693. https://news.ycombinator.com/item?id=22901856#22907424 694. https://news.ycombinator.com/item?id=22901856#22907218 695. javascript:void(0) 696. https://news.ycombinator.com/user?id=formercoder 697. https://news.ycombinator.com/item?id=22907218 698. https://news.ycombinator.com/item?id=22901856#22906986 699. https://news.ycombinator.com/item?id=22901856#22907031 700. https://news.ycombinator.com/item?id=22901856#22907496 701. javascript:void(0) 702. https://news.ycombinator.com/user?id=1337shadow 703. https://news.ycombinator.com/item?id=22907496 704. https://news.ycombinator.com/item?id=22901856#22906986 705. https://news.ycombinator.com/item?id=22901856#22907325 706. javascript:void(0) 707. https://news.ycombinator.com/user?id=d33 708. https://news.ycombinator.com/item?id=22907558 709. https://news.ycombinator.com/item?id=22901856#22907496 710. https://news.ycombinator.com/item?id=22901856#22908544 711. javascript:void(0) 712. https://news.ycombinator.com/user?id=darkerside 713. https://news.ycombinator.com/item?id=22907653 714. https://news.ycombinator.com/item?id=22901856#22907496 715. https://news.ycombinator.com/item?id=22901856#22907558 716. https://news.ycombinator.com/item?id=22901856#22912713 717. javascript:void(0) 718. https://news.ycombinator.com/user?id=GlennS 719. https://news.ycombinator.com/item?id=22912740 720. https://news.ycombinator.com/item?id=22901856#22907496 721. https://news.ycombinator.com/item?id=22901856#22907653 722. https://news.ycombinator.com/item?id=22901856#22912713 723. javascript:void(0) 724. https://news.ycombinator.com/user?id=GlennS 725. https://news.ycombinator.com/item?id=22912713 726. https://news.ycombinator.com/item?id=22901856#22907496 727. https://news.ycombinator.com/item?id=22901856#22907558 728. https://news.ycombinator.com/item?id=22901856#22907653 729. https://news.ycombinator.com/item?id=22901856#22911565 730. javascript:void(0) 731. https://uwsgi-docs.readthedocs.io/en/latest/Caching.html 732. https://uwsgi-docs.readthedocs.io/en/latest/Mules.html 733. https://news.ycombinator.com/user?id=dzonga 734. https://news.ycombinator.com/item?id=22911565 735. https://news.ycombinator.com/item?id=22901856#22907496 736. https://news.ycombinator.com/item?id=22901856#22907558 737. https://news.ycombinator.com/item?id=22901856#22912713 738. https://news.ycombinator.com/item?id=22901856#22908544 739. javascript:void(0) 740. https://news.ycombinator.com/user?id=k_bx 741. https://news.ycombinator.com/item?id=22908544 742. https://news.ycombinator.com/item?id=22901856#22907496 743. https://news.ycombinator.com/item?id=22901856#22907558 744. https://news.ycombinator.com/item?id=22901856#22907325 745. javascript:void(0) 746. https://news.ycombinator.com/user?id=radus 747. https://news.ycombinator.com/item?id=22910416 748. https://news.ycombinator.com/item?id=22901856#22907496 749. https://news.ycombinator.com/item?id=22901856#22908544 750. https://news.ycombinator.com/item?id=22901856#22907325 751. javascript:void(0) 752. https://news.ycombinator.com/user?id=k_bx 753. https://news.ycombinator.com/item?id=22910564 754. https://news.ycombinator.com/item?id=22901856#22907496 755. https://news.ycombinator.com/item?id=22901856#22910416 756. https://news.ycombinator.com/item?id=22901856#22907325 757. javascript:void(0) 758. https://news.ycombinator.com/user?id=ljvmiranda 759. https://news.ycombinator.com/item?id=22907325 760. https://news.ycombinator.com/item?id=22901856#22907496 761. https://news.ycombinator.com/item?id=22901856#22906977 762. javascript:void(0) 763. https://news.ycombinator.com/user?id=throwaway888abc 764. https://news.ycombinator.com/item?id=22909138 765. https://news.ycombinator.com/item?id=22901856#22907325 766. https://news.ycombinator.com/item?id=22901856#22906977 767. javascript:void(0) 768. https://news.ycombinator.com/user?id=andybak 769. https://news.ycombinator.com/item?id=22906977 770. https://news.ycombinator.com/item?id=22901856#22907325 771. https://news.ycombinator.com/item?id=22901856#22906904 772. javascript:void(0) 773. https://news.ycombinator.com/user?id=danpalmer 774. https://news.ycombinator.com/item?id=22907362 775. https://news.ycombinator.com/item?id=22901856#22906977 776. https://news.ycombinator.com/item?id=22901856#22907967 777. javascript:void(0) 778. https://news.ycombinator.com/user?id=1337shadow 779. https://news.ycombinator.com/item?id=22907546 780. https://news.ycombinator.com/item?id=22901856#22906977 781. https://news.ycombinator.com/item?id=22901856#22907362 782. https://news.ycombinator.com/item?id=22901856#22907967 783. javascript:void(0) 784. https://news.ycombinator.com/user?id=raverbashing 785. https://news.ycombinator.com/item?id=22907967 786. https://news.ycombinator.com/item?id=22901856#22906977 787. https://news.ycombinator.com/item?id=22901856#22907362 788. https://news.ycombinator.com/item?id=22901856#22907020 789. javascript:void(0) 790. https://news.ycombinator.com/user?id=mattbillenstein 791. https://news.ycombinator.com/item?id=22907020 792. https://news.ycombinator.com/item?id=22901856#22906977 793. https://news.ycombinator.com/item?id=22901856#22907967 794. https://news.ycombinator.com/item?id=22901856#22906904 795. javascript:void(0) 796. https://news.ycombinator.com/user?id=ptype 797. https://news.ycombinator.com/item?id=22908145 798. https://news.ycombinator.com/item?id=22901856#22906977 799. https://news.ycombinator.com/item?id=22901856#22907020 800. https://news.ycombinator.com/item?id=22901856#22906904 801. javascript:void(0) 802. https://news.ycombinator.com/user?id=cepp 803. https://news.ycombinator.com/item?id=22910710 804. https://news.ycombinator.com/item?id=22901856#22906977 805. https://news.ycombinator.com/item?id=22901856#22908145 806. https://news.ycombinator.com/item?id=22901856#22912956 807. javascript:void(0) 808. https://news.ycombinator.com/user?id=mattbillenstein 809. https://news.ycombinator.com/item?id=22912966 810. https://news.ycombinator.com/item?id=22901856#22906977 811. https://news.ycombinator.com/item?id=22901856#22910710 812. https://news.ycombinator.com/item?id=22901856#22912956 813. javascript:void(0) 814. https://news.ycombinator.com/user?id=mattbillenstein 815. https://news.ycombinator.com/item?id=22912956 816. https://news.ycombinator.com/item?id=22901856#22906977 817. https://news.ycombinator.com/item?id=22901856#22908145 818. https://news.ycombinator.com/item?id=22901856#22910710 819. https://news.ycombinator.com/item?id=22901856#22906904 820. javascript:void(0) 821. https://news.ycombinator.com/user?id=procinct 822. https://news.ycombinator.com/item?id=22906904 823. https://news.ycombinator.com/item?id=22901856#22906977 824. https://news.ycombinator.com/item?id=22901856#22907387 825. javascript:void(0) 826. https://news.ycombinator.com/user?id=adamcharnock 827. https://news.ycombinator.com/item?id=22906980 828. https://news.ycombinator.com/item?id=22901856#22906904 829. https://news.ycombinator.com/item?id=22901856#22906957 830. javascript:void(0) 831. http://lightbus.org/ 832. https://news.ycombinator.com/user?id=doliveira 833. https://news.ycombinator.com/item?id=22907236 834. https://news.ycombinator.com/item?id=22901856#22906904 835. https://news.ycombinator.com/item?id=22901856#22906980 836. https://news.ycombinator.com/item?id=22901856#22906957 837. javascript:void(0) 838. https://news.ycombinator.com/user?id=marcosdumay 839. https://news.ycombinator.com/item?id=22909209 840. https://news.ycombinator.com/item?id=22901856#22906904 841. https://news.ycombinator.com/item?id=22901856#22907236 842. https://news.ycombinator.com/item?id=22901856#22906957 843. javascript:void(0) 844. https://news.ycombinator.com/user?id=WJW 845. https://news.ycombinator.com/item?id=22906957 846. https://news.ycombinator.com/item?id=22901856#22906904 847. https://news.ycombinator.com/item?id=22901856#22906980 848. https://news.ycombinator.com/item?id=22901856#22907220 849. javascript:void(0) 850. https://news.ycombinator.com/user?id=1337shadow 851. https://news.ycombinator.com/item?id=22907562 852. https://news.ycombinator.com/item?id=22901856#22906904 853. https://news.ycombinator.com/item?id=22901856#22906957 854. https://news.ycombinator.com/item?id=22901856#22907220 855. javascript:void(0) 856. https://news.ycombinator.com/user?id=notyourday 857. https://news.ycombinator.com/item?id=22907220 858. https://news.ycombinator.com/item?id=22901856#22906904 859. https://news.ycombinator.com/item?id=22901856#22906957 860. https://news.ycombinator.com/item?id=22901856#22906974 861. javascript:void(0) 862. https://news.ycombinator.com/user?id=masklinn 863. https://news.ycombinator.com/item?id=22906974 864. https://news.ycombinator.com/item?id=22901856#22906904 865. https://news.ycombinator.com/item?id=22901856#22907220 866. https://news.ycombinator.com/item?id=22901856#22907531 867. javascript:void(0) 868. https://news.ycombinator.com/user?id=jb3689 869. https://news.ycombinator.com/item?id=22907531 870. https://news.ycombinator.com/item?id=22901856#22906904 871. https://news.ycombinator.com/item?id=22901856#22906974 872. https://news.ycombinator.com/item?id=22901856#22906936 873. javascript:void(0) 874. https://news.ycombinator.com/user?id=leowoo91 875. https://news.ycombinator.com/item?id=22906936 876. https://news.ycombinator.com/item?id=22901856#22906904 877. https://news.ycombinator.com/item?id=22901856#22907531 878. https://news.ycombinator.com/item?id=22901856#22907067 879. javascript:void(0) 880. https://news.ycombinator.com/user?id=procinct 881. https://news.ycombinator.com/item?id=22907382 882. https://news.ycombinator.com/item?id=22901856#22906904 883. https://news.ycombinator.com/item?id=22901856#22906936 884. https://news.ycombinator.com/item?id=22901856#22907067 885. javascript:void(0) 886. https://news.ycombinator.com/user?id=leowoo91 887. https://news.ycombinator.com/item?id=22914127 888. https://news.ycombinator.com/item?id=22901856#22906904 889. https://news.ycombinator.com/item?id=22901856#22907382 890. https://news.ycombinator.com/item?id=22901856#22907067 891. javascript:void(0) 892. https://news.ycombinator.com/user?id=golergka 893. https://news.ycombinator.com/item?id=22907067 894. https://news.ycombinator.com/item?id=22901856#22906904 895. https://news.ycombinator.com/item?id=22901856#22906936 896. https://news.ycombinator.com/item?id=22901856#22907248 897. javascript:void(0) 898. https://news.ycombinator.com/user?id=doliveira 899. https://news.ycombinator.com/item?id=22907248 900. https://news.ycombinator.com/item?id=22901856#22906904 901. https://news.ycombinator.com/item?id=22901856#22907067 902. https://news.ycombinator.com/item?id=22901856#22907387 903. javascript:void(0) 904. https://news.ycombinator.com/user?id=procinct 905. https://news.ycombinator.com/item?id=22907406 906. https://news.ycombinator.com/item?id=22901856#22906904 907. https://news.ycombinator.com/item?id=22901856#22907248 908. https://news.ycombinator.com/item?id=22901856#22907387 909. javascript:void(0) 910. https://news.ycombinator.com/user?id=turtlebits 911. https://news.ycombinator.com/item?id=22907594 912. https://news.ycombinator.com/item?id=22901856#22906904 913. https://news.ycombinator.com/item?id=22901856#22907406 914. https://news.ycombinator.com/item?id=22901856#22907387 915. javascript:void(0) 916. https://news.ycombinator.com/user?id=nickjj 917. https://news.ycombinator.com/item?id=22907387 918. https://news.ycombinator.com/item?id=22901856#22906904 919. https://news.ycombinator.com/item?id=22901856#22906951 920. javascript:void(0) 921. https://nickjanetakis.com/blog/4-use-cases-for-when-to-use-celery-in-a-flask-application 922. https://news.ycombinator.com/user?id=doteka 923. https://news.ycombinator.com/item?id=22906951 924. https://news.ycombinator.com/item?id=22901856#22907387 925. https://news.ycombinator.com/item?id=22901856#22907427 926. javascript:void(0) 927. https://news.ycombinator.com/user?id=mattbillenstein 928. https://news.ycombinator.com/item?id=22906975 929. https://news.ycombinator.com/item?id=22901856#22906951 930. https://news.ycombinator.com/item?id=22901856#22907604 931. javascript:void(0) 932. https://news.ycombinator.com/user?id=rollingbarreler 933. https://news.ycombinator.com/item?id=22907672 934. https://news.ycombinator.com/item?id=22901856#22906951 935. https://news.ycombinator.com/item?id=22901856#22906975 936. https://news.ycombinator.com/item?id=22901856#22908356 937. javascript:void(0) 938. https://news.ycombinator.com/user?id=mattbillenstein 939. https://news.ycombinator.com/item?id=22912281 940. https://news.ycombinator.com/item?id=22901856#22906951 941. https://news.ycombinator.com/item?id=22901856#22907672 942. https://news.ycombinator.com/item?id=22901856#22908356 943. javascript:void(0) 944. https://news.ycombinator.com/user?id=acjohnson55 945. https://news.ycombinator.com/item?id=22908356 946. https://news.ycombinator.com/item?id=22901856#22906951 947. https://news.ycombinator.com/item?id=22901856#22906975 948. https://news.ycombinator.com/item?id=22901856#22907672 949. https://news.ycombinator.com/item?id=22901856#22908550 950. javascript:void(0) 951. https://news.ycombinator.com/user?id=mattbillenstein 952. https://news.ycombinator.com/item?id=22912297 953. https://news.ycombinator.com/item?id=22901856#22906951 954. https://news.ycombinator.com/item?id=22901856#22908356 955. https://news.ycombinator.com/item?id=22901856#22910040 956. javascript:void(0) 957. https://news.ycombinator.com/user?id=sateesh 958. https://news.ycombinator.com/item?id=22910040 959. https://news.ycombinator.com/item?id=22901856#22906951 960. https://news.ycombinator.com/item?id=22901856#22908356 961. https://news.ycombinator.com/item?id=22901856#22912297 962. https://news.ycombinator.com/item?id=22901856#22908550 963. javascript:void(0) 964. https://news.ycombinator.com/user?id=momokoko 965. https://news.ycombinator.com/item?id=22908550 966. https://news.ycombinator.com/item?id=22901856#22906951 967. https://news.ycombinator.com/item?id=22901856#22906975 968. https://news.ycombinator.com/item?id=22901856#22908356 969. https://news.ycombinator.com/item?id=22901856#22907604 970. javascript:void(0) 971. https://news.ycombinator.com/user?id=jb3689 972. https://news.ycombinator.com/item?id=22907604 973. https://news.ycombinator.com/item?id=22901856#22906951 974. https://news.ycombinator.com/item?id=22901856#22906975 975. https://news.ycombinator.com/item?id=22901856#22907290 976. javascript:void(0) 977. https://news.ycombinator.com/user?id=lifty 978. https://news.ycombinator.com/item?id=22907290 979. https://news.ycombinator.com/item?id=22901856#22906951 980. https://news.ycombinator.com/item?id=22901856#22907604 981. https://news.ycombinator.com/item?id=22901856#22907369 982. javascript:void(0) 983. https://news.ycombinator.com/user?id=nickjj 984. https://news.ycombinator.com/item?id=22907369 985. https://news.ycombinator.com/item?id=22901856#22906951 986. https://news.ycombinator.com/item?id=22901856#22907290 987. https://news.ycombinator.com/item?id=22901856#22907551 988. javascript:void(0) 989. https://news.ycombinator.com/user?id=BiteCode_dev 990. https://news.ycombinator.com/item?id=22907551 991. https://news.ycombinator.com/item?id=22901856#22906951 992. https://news.ycombinator.com/item?id=22901856#22907369 993. https://news.ycombinator.com/item?id=22901856#22907264 994. javascript:void(0) 995. https://news.ycombinator.com/user?id=doteka 996. https://news.ycombinator.com/item?id=22915087 997. https://news.ycombinator.com/item?id=22901856#22906951 998. https://news.ycombinator.com/item?id=22901856#22907551 999. https://news.ycombinator.com/item?id=22901856#22907264 1000. javascript:void(0) 1001. https://news.ycombinator.com/user?id=Dowwie 1002. https://news.ycombinator.com/item?id=22907264 1003. https://news.ycombinator.com/item?id=22901856#22906951 1004. https://news.ycombinator.com/item?id=22901856#22907551 1005. https://news.ycombinator.com/item?id=22901856#22907427 1006. javascript:void(0) 1007. https://news.ycombinator.com/user?id=trboyden 1008. https://news.ycombinator.com/item?id=22907427 1009. https://news.ycombinator.com/item?id=22901856#22906951 1010. https://news.ycombinator.com/item?id=22901856#22908731 1011. javascript:void(0) 1012. http://shop.oreilly.com/product/9780596102258.do 1013. https://news.ycombinator.com/user?id=memco 1014. https://news.ycombinator.com/item?id=22908731 1015. https://news.ycombinator.com/item?id=22901856#22907427 1016. https://news.ycombinator.com/item?id=22901856#22907935 1017. javascript:void(0) 1018. https://news.ycombinator.com/user?id=rukittenme 1019. https://news.ycombinator.com/item?id=22911177 1020. https://news.ycombinator.com/item?id=22901856#22908731 1021. https://news.ycombinator.com/item?id=22901856#22907935 1022. javascript:void(0) 1023. https://news.ycombinator.com/user?id=dralley 1024. https://news.ycombinator.com/item?id=22907935 1025. https://news.ycombinator.com/item?id=22901856#22908731 1026. https://news.ycombinator.com/item?id=22901856#22913852 1027. javascript:void(0) 1028. https://news.ycombinator.com/user?id=timwis 1029. https://news.ycombinator.com/item?id=22913852 1030. https://news.ycombinator.com/item?id=22901856#22907935 1031. https://news.ycombinator.com/item?id=22901856#22907802 1032. javascript:void(0) 1033. https://news.ycombinator.com/user?id=bryanrasmussen 1034. https://news.ycombinator.com/item?id=22907802 1035. https://news.ycombinator.com/item?id=22901856#22913852 1036. https://news.ycombinator.com/item?id=22901856#22908621 1037. javascript:void(0) 1038. https://news.ycombinator.com/user?id=kantye 1039. https://news.ycombinator.com/item?id=22908621 1040. https://news.ycombinator.com/item?id=22901856#22907802 1041. https://news.ycombinator.com/item?id=22901856#22908487 1042. javascript:void(0) 1043. https://news.ycombinator.com/user?id=nurettin 1044. https://news.ycombinator.com/item?id=22908487 1045. https://news.ycombinator.com/item?id=22901856#22908621 1046. https://news.ycombinator.com/item?id=22901856#22907933 1047. javascript:void(0) 1048. https://news.ycombinator.com/user?id=quezzle 1049. https://news.ycombinator.com/item?id=22907933 1050. https://news.ycombinator.com/item?id=22901856#22908487 1051. https://news.ycombinator.com/item?id=22901856#22907210 1052. javascript:void(0) 1053. https://news.ycombinator.com/user?id=tchaffee 1054. https://news.ycombinator.com/item?id=22907210 1055. https://news.ycombinator.com/item?id=22901856#22907933 1056. https://news.ycombinator.com/item?id=22901856#22906934 1057. javascript:void(0) 1058. https://news.ycombinator.com/user?id=ljvmiranda 1059. https://news.ycombinator.com/item?id=22907343 1060. https://news.ycombinator.com/item?id=22901856#22907210 1061. https://news.ycombinator.com/item?id=22901856#22906934 1062. javascript:void(0) 1063. https://news.ycombinator.com/user?id=tchaffee 1064. https://news.ycombinator.com/item?id=22907535 1065. https://news.ycombinator.com/item?id=22901856#22907210 1066. https://news.ycombinator.com/item?id=22901856#22907343 1067. https://news.ycombinator.com/item?id=22901856#22906934 1068. javascript:void(0) 1069. https://news.ycombinator.com/user?id=alanfranz 1070. https://news.ycombinator.com/item?id=22906934 1071. https://news.ycombinator.com/item?id=22901856#22907210 1072. https://news.ycombinator.com/item?id=22901856#22906899 1073. javascript:void(0) 1074. https://news.ycombinator.com/user?id=icebraining 1075. https://news.ycombinator.com/item?id=22907050 1076. https://news.ycombinator.com/item?id=22901856#22906934 1077. https://news.ycombinator.com/item?id=22901856#22906978 1078. javascript:void(0) 1079. https://news.ycombinator.com/user?id=alanfranz 1080. https://news.ycombinator.com/item?id=22908223 1081. https://news.ycombinator.com/item?id=22901856#22906934 1082. https://news.ycombinator.com/item?id=22901856#22907050 1083. https://news.ycombinator.com/item?id=22901856#22906978 1084. javascript:void(0) 1085. https://news.ycombinator.com/user?id=icebraining 1086. https://news.ycombinator.com/item?id=22908951 1087. https://news.ycombinator.com/item?id=22901856#22906934 1088. https://news.ycombinator.com/item?id=22901856#22908223 1089. https://news.ycombinator.com/item?id=22901856#22906978 1090. javascript:void(0) 1091. https://news.ycombinator.com/user?id=WJW 1092. https://news.ycombinator.com/item?id=22906978 1093. https://news.ycombinator.com/item?id=22901856#22906934 1094. https://news.ycombinator.com/item?id=22901856#22907050 1095. https://news.ycombinator.com/item?id=22901856#22906996 1096. javascript:void(0) 1097. https://news.ycombinator.com/user?id=alanfranz 1098. https://news.ycombinator.com/item?id=22908227 1099. https://news.ycombinator.com/item?id=22901856#22906934 1100. https://news.ycombinator.com/item?id=22901856#22906978 1101. https://news.ycombinator.com/item?id=22901856#22906996 1102. javascript:void(0) 1103. https://news.ycombinator.com/user?id=polote 1104. https://news.ycombinator.com/item?id=22906996 1105. https://news.ycombinator.com/item?id=22901856#22906934 1106. https://news.ycombinator.com/item?id=22901856#22906978 1107. https://news.ycombinator.com/item?id=22901856#22906899 1108. javascript:void(0) 1109. https://news.ycombinator.com/user?id=alanfranz 1110. https://news.ycombinator.com/item?id=22908248 1111. https://news.ycombinator.com/item?id=22901856#22906934 1112. https://news.ycombinator.com/item?id=22901856#22906996 1113. https://news.ycombinator.com/item?id=22901856#22906899 1114. javascript:void(0) 1115. https://news.ycombinator.com/user?id=pupdogg 1116. https://news.ycombinator.com/item?id=22906899 1117. https://news.ycombinator.com/item?id=22901856#22906934 1118. javascript:void(0) 1119. https://news.ycombinator.com/user?id=jessaustin 1120. https://news.ycombinator.com/item?id=22911409 1121. https://news.ycombinator.com/item?id=22901856#22906899 1122. javascript:void(0) 1123. https://events.ycombinator.com/ai-sus 1124. https://news.ycombinator.com/newsguidelines.html 1125. https://news.ycombinator.com/newsfaq.html 1126. https://news.ycombinator.com/lists 1127. https://github.com/HackerNews/API 1128. https://news.ycombinator.com/security.html 1129. https://www.ycombinator.com/legal/ 1130. https://www.ycombinator.com/apply/ 1131. mailto:hn@ycombinator.com

Hidden links: 1133. https://news.ycombinator.com/vote?id=22901856&how=up&goto=item%3Fid%3D22901856 1134. https://news.ycombinator.com/vote?id=22907390&how=up&goto=item%3Fid%3D22901856 1135. https://news.ycombinator.com/vote?id=22907475&how=up&goto=item%3Fid%3D22901856 1136. https://news.ycombinator.com/vote?id=22911497&how=up&goto=item%3Fid%3D22901856 1137. https://news.ycombinator.com/vote?id=22910922&how=up&goto=item%3Fid%3D22901856 1138. https://news.ycombinator.com/vote?id=22911399&how=up&goto=item%3Fid%3D22901856 1139. https://news.ycombinator.com/vote?id=22911421&how=up&goto=item%3Fid%3D22901856 1140. https://news.ycombinator.com/vote?id=22914057&how=up&goto=item%3Fid%3D22901856 1141. https://news.ycombinator.com/vote?id=22914795&how=up&goto=item%3Fid%3D22901856 1142. https://news.ycombinator.com/vote?id=22915351&how=up&goto=item%3Fid%3D22901856 1143. https://news.ycombinator.com/vote?id=22915458&how=up&goto=item%3Fid%3D22901856 1144. https://news.ycombinator.com/vote?id=22915492&how=up&goto=item%3Fid%3D22901856 1145. https://news.ycombinator.com/vote?id=22921383&how=up&goto=item%3Fid%3D22901856 1146. https://news.ycombinator.com/vote?id=22915520&how=up&goto=item%3Fid%3D22901856 1147. https://news.ycombinator.com/vote?id=22907584&how=up&goto=item%3Fid%3D22901856 1148. https://news.ycombinator.com/vote?id=22907635&how=up&goto=item%3Fid%3D22901856 1149. https://news.ycombinator.com/vote?id=22907891&how=up&goto=item%3Fid%3D22901856 1150. https://news.ycombinator.com/vote?id=22908828&how=up&goto=item%3Fid%3D22901856 1151. https://news.ycombinator.com/vote?id=22909875&how=up&goto=item%3Fid%3D22901856 1152. https://news.ycombinator.com/vote?id=22911973&how=up&goto=item%3Fid%3D22901856 1153. https://news.ycombinator.com/vote?id=22908283&how=up&goto=item%3Fid%3D22901856 1154. https://news.ycombinator.com/vote?id=22908881&how=up&goto=item%3Fid%3D22901856 1155. https://news.ycombinator.com/vote?id=22908421&how=up&goto=item%3Fid%3D22901856 1156. https://news.ycombinator.com/vote?id=22908518&how=up&goto=item%3Fid%3D22901856 1157. https://news.ycombinator.com/vote?id=22908995&how=up&goto=item%3Fid%3D22901856 1158. https://news.ycombinator.com/vote?id=22908567&how=up&goto=item%3Fid%3D22901856 1159. https://news.ycombinator.com/vote?id=22908492&how=up&goto=item%3Fid%3D22901856 1160. https://news.ycombinator.com/vote?id=22911120&how=up&goto=item%3Fid%3D22901856 1161. https://news.ycombinator.com/vote?id=22908471&how=up&goto=item%3Fid%3D22901856 1162. https://news.ycombinator.com/vote?id=22910782&how=up&goto=item%3Fid%3D22901856 1163. https://news.ycombinator.com/vote?id=22912886&how=up&goto=item%3Fid%3D22901856 1164. https://news.ycombinator.com/vote?id=22916753&how=up&goto=item%3Fid%3D22901856 1165. https://news.ycombinator.com/vote?id=22911649&how=up&goto=item%3Fid%3D22901856 1166. https://news.ycombinator.com/vote?id=22915768&how=up&goto=item%3Fid%3D22901856 1167. https://news.ycombinator.com/vote?id=22916172&how=up&goto=item%3Fid%3D22901856 1168. https://news.ycombinator.com/vote?id=22907695&how=up&goto=item%3Fid%3D22901856 1169. https://news.ycombinator.com/vote?id=22907716&how=up&goto=item%3Fid%3D22901856 1170. https://news.ycombinator.com/vote?id=22907776&how=up&goto=item%3Fid%3D22901856 1171. https://news.ycombinator.com/vote?id=22908536&how=up&goto=item%3Fid%3D22901856 1172. https://news.ycombinator.com/vote?id=22912246&how=up&goto=item%3Fid%3D22901856 1173. https://news.ycombinator.com/vote?id=22909185&how=up&goto=item%3Fid%3D22901856 1174. https://news.ycombinator.com/vote?id=22910110&how=up&goto=item%3Fid%3D22901856 1175. https://news.ycombinator.com/vote?id=22911136&how=up&goto=item%3Fid%3D22901856 1176. https://news.ycombinator.com/vote?id=22921254&how=up&goto=item%3Fid%3D22901856 1177. https://news.ycombinator.com/vote?id=22910617&how=up&goto=item%3Fid%3D22901856 1178. https://news.ycombinator.com/vote?id=22910902&how=up&goto=item%3Fid%3D22901856 1179. https://news.ycombinator.com/vote?id=22913823&how=up&goto=item%3Fid%3D22901856 1180. https://news.ycombinator.com/vote?id=22915756&how=up&goto=item%3Fid%3D22901856 1181. https://news.ycombinator.com/vote?id=22916067&how=up&goto=item%3Fid%3D22901856 1182. https://news.ycombinator.com/vote?id=22913738&how=up&goto=item%3Fid%3D22901856 1183. https://news.ycombinator.com/vote?id=22907753&how=up&goto=item%3Fid%3D22901856 1184. https://news.ycombinator.com/vote?id=22908761&how=up&goto=item%3Fid%3D22901856 1185. https://news.ycombinator.com/vote?id=22911062&how=up&goto=item%3Fid%3D22901856 1186. https://news.ycombinator.com/vote?id=22911457&how=up&goto=item%3Fid%3D22901856 1187. https://news.ycombinator.com/vote?id=22911890&how=up&goto=item%3Fid%3D22901856 1188. https://news.ycombinator.com/vote?id=22914250&how=up&goto=item%3Fid%3D22901856 1189. https://news.ycombinator.com/vote?id=22914464&how=up&goto=item%3Fid%3D22901856 1190. https://news.ycombinator.com/vote?id=22915801&how=up&goto=item%3Fid%3D22901856 1191. https://news.ycombinator.com/vote?id=22912733&how=up&goto=item%3Fid%3D22901856 1192. https://news.ycombinator.com/vote?id=22914293&how=up&goto=item%3Fid%3D22901856 1193. https://news.ycombinator.com/vote?id=22915808&how=up&goto=item%3Fid%3D22901856 1194. https://news.ycombinator.com/vote?id=22915786&how=up&goto=item%3Fid%3D22901856 1195. https://news.ycombinator.com/vote?id=22912417&how=up&goto=item%3Fid%3D22901856 1196. https://news.ycombinator.com/vote?id=22912798&how=up&goto=item%3Fid%3D22901856 1197. https://news.ycombinator.com/vote?id=22908182&how=up&goto=item%3Fid%3D22901856 1198. https://news.ycombinator.com/vote?id=22911144&how=up&goto=item%3Fid%3D22901856 1199. https://news.ycombinator.com/vote?id=22911771&how=up&goto=item%3Fid%3D22901856 1200. https://news.ycombinator.com/vote?id=22914091&how=up&goto=item%3Fid%3D22901856 1201. https://news.ycombinator.com/vote?id=22912831&how=up&goto=item%3Fid%3D22901856 1202. https://news.ycombinator.com/vote?id=22914450&how=up&goto=item%3Fid%3D22901856 1203. https://news.ycombinator.com/vote?id=22915890&how=up&goto=item%3Fid%3D22901856 1204. https://news.ycombinator.com/vote?id=22918616&how=up&goto=item%3Fid%3D22901856 1205. https://news.ycombinator.com/vote?id=22909080&how=up&goto=item%3Fid%3D22901856 1206. https://news.ycombinator.com/vote?id=22908469&how=up&goto=item%3Fid%3D22901856 1207. https://news.ycombinator.com/vote?id=22908994&how=up&goto=item%3Fid%3D22901856 1208. https://news.ycombinator.com/vote?id=22911325&how=up&goto=item%3Fid%3D22901856 1209. https://news.ycombinator.com/vote?id=22906986&how=up&goto=item%3Fid%3D22901856 1210. https://news.ycombinator.com/vote?id=22907429&how=up&goto=item%3Fid%3D22901856 1211. https://news.ycombinator.com/vote?id=22908199&how=up&goto=item%3Fid%3D22901856 1212. https://news.ycombinator.com/vote?id=22910883&how=up&goto=item%3Fid%3D22901856 1213. https://news.ycombinator.com/vote?id=22907480&how=up&goto=item%3Fid%3D22901856 1214. https://news.ycombinator.com/vote?id=22907563&how=up&goto=item%3Fid%3D22901856 1215. https://news.ycombinator.com/vote?id=22910824&how=up&goto=item%3Fid%3D22901856 1216. https://news.ycombinator.com/vote?id=22907944&how=up&goto=item%3Fid%3D22901856 1217. https://news.ycombinator.com/vote?id=22908254&how=up&goto=item%3Fid%3D22901856 1218. https://news.ycombinator.com/vote?id=22909979&how=up&goto=item%3Fid%3D22901856 1219. https://news.ycombinator.com/vote?id=22910152&how=up&goto=item%3Fid%3D22901856 1220. https://news.ycombinator.com/vote?id=22911353&how=up&goto=item%3Fid%3D22901856 1221. https://news.ycombinator.com/vote?id=22910815&how=up&goto=item%3Fid%3D22901856 1222. https://news.ycombinator.com/vote?id=22912418&how=up&goto=item%3Fid%3D22901856 1223. https://news.ycombinator.com/vote?id=22911242&how=up&goto=item%3Fid%3D22901856 1224. https://news.ycombinator.com/vote?id=22927860&how=up&goto=item%3Fid%3D22901856 1225. https://news.ycombinator.com/vote?id=22907846&how=up&goto=item%3Fid%3D22901856 1226. https://news.ycombinator.com/vote?id=22909039&how=up&goto=item%3Fid%3D22901856 1227. https://news.ycombinator.com/vote?id=22907561&how=up&goto=item%3Fid%3D22901856 1228. https://news.ycombinator.com/vote?id=22907932&how=up&goto=item%3Fid%3D22901856 1229. https://news.ycombinator.com/vote?id=22910917&how=up&goto=item%3Fid%3D22901856 1230. https://news.ycombinator.com/vote?id=22909428&how=up&goto=item%3Fid%3D22901856 1231. https://news.ycombinator.com/vote?id=22907704&how=up&goto=item%3Fid%3D22901856 1232. https://news.ycombinator.com/vote?id=22910051&how=up&goto=item%3Fid%3D22901856 1233. https://news.ycombinator.com/vote?id=22910932&how=up&goto=item%3Fid%3D22901856 1234. https://news.ycombinator.com/vote?id=22907862&how=up&goto=item%3Fid%3D22901856 1235. https://news.ycombinator.com/vote?id=22907033&how=up&goto=item%3Fid%3D22901856 1236. https://news.ycombinator.com/vote?id=22907643&how=up&goto=item%3Fid%3D22901856 1237. https://news.ycombinator.com/vote?id=22908416&how=up&goto=item%3Fid%3D22901856 1238. https://news.ycombinator.com/vote?id=22907300&how=up&goto=item%3Fid%3D22901856 1239. https://news.ycombinator.com/vote?id=22907424&how=up&goto=item%3Fid%3D22901856 1240. https://news.ycombinator.com/vote?id=22907031&how=up&goto=item%3Fid%3D22901856 1241. https://news.ycombinator.com/vote?id=22907218&how=up&goto=item%3Fid%3D22901856 1242. https://news.ycombinator.com/vote?id=22907496&how=up&goto=item%3Fid%3D22901856 1243. https://news.ycombinator.com/vote?id=22907558&how=up&goto=item%3Fid%3D22901856 1244. https://news.ycombinator.com/vote?id=22907653&how=up&goto=item%3Fid%3D22901856 1245. https://news.ycombinator.com/vote?id=22912740&how=up&goto=item%3Fid%3D22901856 1246. https://news.ycombinator.com/vote?id=22912713&how=up&goto=item%3Fid%3D22901856 1247. https://news.ycombinator.com/vote?id=22911565&how=up&goto=item%3Fid%3D22901856 1248. https://news.ycombinator.com/vote?id=22908544&how=up&goto=item%3Fid%3D22901856 1249. https://news.ycombinator.com/vote?id=22910416&how=up&goto=item%3Fid%3D22901856 1250. https://news.ycombinator.com/vote?id=22910564&how=up&goto=item%3Fid%3D22901856 1251. https://news.ycombinator.com/vote?id=22907325&how=up&goto=item%3Fid%3D22901856 1252. https://news.ycombinator.com/vote?id=22909138&how=up&goto=item%3Fid%3D22901856 1253. https://news.ycombinator.com/vote?id=22906977&how=up&goto=item%3Fid%3D22901856 1254. https://news.ycombinator.com/vote?id=22907362&how=up&goto=item%3Fid%3D22901856 1255. https://news.ycombinator.com/vote?id=22907546&how=up&goto=item%3Fid%3D22901856 1256. https://news.ycombinator.com/vote?id=22907967&how=up&goto=item%3Fid%3D22901856 1257. https://news.ycombinator.com/vote?id=22907020&how=up&goto=item%3Fid%3D22901856 1258. https://news.ycombinator.com/vote?id=22908145&how=up&goto=item%3Fid%3D22901856 1259. https://news.ycombinator.com/vote?id=22910710&how=up&goto=item%3Fid%3D22901856 1260. https://news.ycombinator.com/vote?id=22912966&how=up&goto=item%3Fid%3D22901856 1261. https://news.ycombinator.com/vote?id=22912956&how=up&goto=item%3Fid%3D22901856 1262. https://news.ycombinator.com/vote?id=22906904&how=up&goto=item%3Fid%3D22901856 1263. https://news.ycombinator.com/vote?id=22906980&how=up&goto=item%3Fid%3D22901856 1264. https://news.ycombinator.com/vote?id=22907236&how=up&goto=item%3Fid%3D22901856 1265. https://news.ycombinator.com/vote?id=22909209&how=up&goto=item%3Fid%3D22901856 1266. https://news.ycombinator.com/vote?id=22906957&how=up&goto=item%3Fid%3D22901856 1267. https://news.ycombinator.com/vote?id=22907562&how=up&goto=item%3Fid%3D22901856 1268. https://news.ycombinator.com/vote?id=22907220&how=up&goto=item%3Fid%3D22901856 1269. https://news.ycombinator.com/vote?id=22906974&how=up&goto=item%3Fid%3D22901856 1270. https://news.ycombinator.com/vote?id=22907531&how=up&goto=item%3Fid%3D22901856 1271. https://news.ycombinator.com/vote?id=22906936&how=up&goto=item%3Fid%3D22901856 1272. https://news.ycombinator.com/vote?id=22907382&how=up&goto=item%3Fid%3D22901856 1273. https://news.ycombinator.com/vote?id=22914127&how=up&goto=item%3Fid%3D22901856 1274. https://news.ycombinator.com/vote?id=22907067&how=up&goto=item%3Fid%3D22901856 1275. https://news.ycombinator.com/vote?id=22907248&how=up&goto=item%3Fid%3D22901856 1276. https://news.ycombinator.com/vote?id=22907406&how=up&goto=item%3Fid%3D22901856 1277. https://news.ycombinator.com/vote?id=22907594&how=up&goto=item%3Fid%3D22901856 1278. https://news.ycombinator.com/vote?id=22907387&how=up&goto=item%3Fid%3D22901856 1279. https://news.ycombinator.com/vote?id=22906951&how=up&goto=item%3Fid%3D22901856 1280. https://news.ycombinator.com/vote?id=22906975&how=up&goto=item%3Fid%3D22901856 1281. https://news.ycombinator.com/vote?id=22907672&how=up&goto=item%3Fid%3D22901856 1282. https://news.ycombinator.com/vote?id=22912281&how=up&goto=item%3Fid%3D22901856 1283. https://news.ycombinator.com/vote?id=22908356&how=up&goto=item%3Fid%3D22901856 1284. https://news.ycombinator.com/vote?id=22912297&how=up&goto=item%3Fid%3D22901856 1285. https://news.ycombinator.com/vote?id=22910040&how=up&goto=item%3Fid%3D22901856 1286. https://news.ycombinator.com/vote?id=22908550&how=up&goto=item%3Fid%3D22901856 1287. https://news.ycombinator.com/vote?id=22907604&how=up&goto=item%3Fid%3D22901856 1288. https://news.ycombinator.com/vote?id=22907290&how=up&goto=item%3Fid%3D22901856 1289. https://news.ycombinator.com/vote?id=22907369&how=up&goto=item%3Fid%3D22901856 1290. https://news.ycombinator.com/vote?id=22907551&how=up&goto=item%3Fid%3D22901856 1291. https://news.ycombinator.com/vote?id=22915087&how=up&goto=item%3Fid%3D22901856 1292. https://news.ycombinator.com/vote?id=22907264&how=up&goto=item%3Fid%3D22901856 1293. https://news.ycombinator.com/vote?id=22907427&how=up&goto=item%3Fid%3D22901856 1294. https://news.ycombinator.com/vote?id=22908731&how=up&goto=item%3Fid%3D22901856 1295. https://news.ycombinator.com/vote?id=22911177&how=up&goto=item%3Fid%3D22901856 1296. https://news.ycombinator.com/vote?id=22907935&how=up&goto=item%3Fid%3D22901856 1297. https://news.ycombinator.com/vote?id=22913852&how=up&goto=item%3Fid%3D22901856 1298. https://news.ycombinator.com/vote?id=22907802&how=up&goto=item%3Fid%3D22901856 1299. https://news.ycombinator.com/vote?id=22908621&how=up&goto=item%3Fid%3D22901856 1300. https://news.ycombinator.com/vote?id=22908487&how=up&goto=item%3Fid%3D22901856 1301. https://news.ycombinator.com/vote?id=22907933&how=up&goto=item%3Fid%3D22901856 1302. https://news.ycombinator.com/vote?id=22907210&how=up&goto=item%3Fid%3D22901856 1303. https://news.ycombinator.com/vote?id=22907343&how=up&goto=item%3Fid%3D22901856 1304. https://news.ycombinator.com/vote?id=22907535&how=up&goto=item%3Fid%3D22901856 1305. https://news.ycombinator.com/vote?id=22906934&how=up&goto=item%3Fid%3D22901856 1306. https://news.ycombinator.com/vote?id=22907050&how=up&goto=item%3Fid%3D22901856 1307. https://news.ycombinator.com/vote?id=22908223&how=up&goto=item%3Fid%3D22901856 1308. https://news.ycombinator.com/vote?id=22908951&how=up&goto=item%3Fid%3D22901856 1309. https://news.ycombinator.com/vote?id=22906978&how=up&goto=item%3Fid%3D22901856 1310. https://news.ycombinator.com/vote?id=22908227&how=up&goto=item%3Fid%3D22901856 1311. https://news.ycombinator.com/vote?id=22906996&how=up&goto=item%3Fid%3D22901856 1312. https://news.ycombinator.com/vote?id=22908248&how=up&goto=item%3Fid%3D22901856 1313. https://news.ycombinator.com/vote?id=22906899&how=up&goto=item%3Fid%3D22901856 1314. https://news.ycombinator.com/vote?id=22911409&how=up&goto=item%3Fid%3D22901856

;