ਜਦੋਂ ਤੁਸੀਂ ਅਜ਼ਰਬਾਈਜਾਨ ਵਿੱਚ ਇੱਕ ਕਾਰ ਬ੍ਰੋਕਰੇਜ ਚਲਾ ਰਹੇ ਹੁੰਦੇ ਹੋ ਅਤੇ ਅਮਰੀਕਾ ਤੋਂ ਸੈਲਵੇਜ ਵਾਹਨ (salvage vehicles) ਆਯਾਤ ਕਰ ਰਹੇ ਹੁੰਦੇ ਹੋ, ਤਾਂ ਤੁਹਾਡੀਆਂ ਸਾਫਟਵੇਅਰ ਸਮੱਸਿਆਵਾਂ ਇੱਕ ਸਿਲੀਕਾਨ ਵੈਲੀ ਸਟਾਰਟਅੱਪ ਨਾਲੋਂ ਵੱਖਰੀਆਂ ਹੁੰਦੀਆਂ ਹਨ। ਤੁਸੀਂ ਲੱਖਾਂ ਇੱਕੋ ਸਮੇਂ ਵਰਤੋਂ ਕਰਨ ਵਾਲੇ ਯੂਜ਼ਰਾਂ (concurrent users) ਲਈ ਆਪਟੀਮਾਈਜ਼ ਨਹੀਂ ਕਰ ਰਹੇ ਹੁੰਦੇ। ਤੁਸੀਂ ਸਪੱਸ਼ਟਤਾ, ਅਪਟਾਈਮ (uptime), ਅਤੇ ਅੱਧੀ ਰਾਤ ਨੂੰ ਦਰਜਨਾਂ ਸਮਾਂ ਖੇਤਰ (time zones) ਦੂਰ ਇੱਕ ਔਕਸ਼ਨ ਹਾਊਸ ਨਾਲ ਤਾਲਮੇਲ ਕਰਦੇ ਹੋਏ ਚੀਜ਼ਾਂ ਨੂੰ ਖੁਦ ਠੀਕ ਕਰਨ ਦੀ ਯੋਗਤਾ ਲਈ ਆਪਟੀਮਾਈਜ਼ ਕਰ ਰਹੇ ਹੁੰਦੇ ਹੋ। AutoMakler ਬਣਾਉਂਦੇ ਸਮੇਂ ਮੈਂ ਬਿਲਕੁਲ ਇਸੇ ਸਥਿਤੀ ਵਿੱਚ ਸੀ। ਇਹ ਪਲੇਟਫਾਰਮ ਲਾਈਵ ਔਕਸ਼ਨ ਸਕ੍ਰੇਪਿੰਗ (live auction scraping) ਅਤੇ Carfax ਲੁੱਕਅੱਪ ਤੋਂ ਲੈ ਕੇ ਡਿਲੀਵਰੀ ਅਨੁਮਾਨ ਅਤੇ ਭੁਗਤਾਨ ਪ੍ਰੋਸੈਸਿੰਗ ਤੱਕ ਸਭ ਕੁਝ ਸੰਭਾਲਦਾ ਹੈ। ਇਹ ਇੱਕ ਅਸਲੀ ਪ੍ਰੋਡਕਸ਼ਨ ਸਿਸਟਮ ਹੈ ਜੋ ਅਸਲੀ ਗਾਹਕਾਂ ਦੀ ਸੇਵਾ ਕਰਦਾ ਹੈ, ਅਤੇ ਇਹ ਉਸ ਸਟੈਕ 'ਤੇ ਚੱਲਦਾ ਹੈ ਜਿਸ ਨੂੰ ਜ਼ਿਆਦਾਤਰ ਡਿਵੈਲਪਰ ਇੱਕ ਬਹੁਤ ਹੀ ਬੋਰਿੰਗ ਸਟੈਕ ਕਹਿਣਗੇ।

ਉਹ ਸਟੈਕ ਜਿਸ ਬਾਰੇ ਕੋਈ ਵੀ ਗੱਲ ਨਹੀਂ ਕਰਨਾ ਚਾਹੁੰਦਾ

ਇੱਥੇ ਕੋਈ React ਨਹੀਂ ਹੈ। ਕੋਈ Vue ਨਹੀਂ ਹੈ। ਕੋਈ Redis, ਕੋਈ Celery, ਅਤੇ ਕੋਈ WebSocket ਸਰਵਰ ਨਹੀਂ ਹੈ। ਬੈਕਐਂਡ (backend) ਸਾਧਾਰਨ Python ਦੇ ਨਾਲ FastAPI ਹੈ। ਡਾਟਾਬੇਸ PostgreSQL ਹੈ। ਫਰੰਟਐਂਡ Jinja2 ਟੈਂਪਲੇਟਸ, Bootstrap, ਅਤੇ ਥੋੜ੍ਹੇ ਜਿਹੇ vanilla JavaScript ਦੀ ਵਰਤੋਂ ਕਰਦੇ ਹੋਏ ਸਰਵਰ-ਰੈਂਡਰਡ HTML ਹੈ। ਸਕ੍ਰੇਪਿੰਗ ਲਈ, ਮੈਂ Playwright ਦੀ ਵਰਤੋਂ ਕਰਦਾ ਹਾਂ। ਸਭ ਕੁਝ ਇੱਕ ਸਿੰਗਲ Python ਪ੍ਰੋਸੈਸ ਵਜੋਂ ਚੱਲਦਾ ਹੈ ਜੋ ਸਿੱਧੇ ਤੌਰ 'ਤੇ HTML ਸਰਵ ਕਰਦਾ ਹੈ।

ਇਸ ਵਿੱਚ ਕੋਈ ਬਿਲਡ ਸਟੈਪ (build step) ਨਹੀਂ ਹੈ। ਆਡਿਟ ਕਰਨ ਲਈ ਕੋਈ node_modules ਫੋਲਡਰ ਨਹੀਂ ਹਨ, ਕੌਂਫਿਗਰ ਕਰਨ ਲਈ ਕੋਈ ਟ੍ਰਾਂਸਪਾਈਲਰ (transpilers) ਨਹੀਂ ਹਨ, ਅਤੇ ਫਰੰਟਐਂਡ ਫਰੇਮਵਰਕ ਦੇ ਲਗਾਤਾਰ ਬਦਲਾਅ (churn) ਨਾਲ ਚੱਲਣ ਦੀ ਲੋੜ ਨਹੀਂ ਹੈ। ਜਦੋਂ ਮੈਂ ਡਿਪਲੋਏ ਕਰਦਾ ਹਾਂ, ਤਾਂ ਮੈਂ Python ਫਾਈਲਾਂ ਅਤੇ ਟੈਂਪਲੇਟਸ ਨੂੰ ਮੂਵ ਕਰ ਰਿਹਾ ਹੁੰਦਾ ਹਾਂ, ਨਾ ਕਿ ਬੰਡਲਰਾਂ ਦੀ ਇੱਕ ਪਾਈਪਲਾਈਨ ਨੂੰ ਸੰਚਾਲਿਤ ਕਰ ਰਿਹਾ ਹੁੰਦਾ ਹਾਂ। ਉਹ ਸਾਦਗੀ ਕੋਈ ਸਮਝੌਤਾ ਨਹੀਂ ਹੈ। ਇਹ ਤਾਂ ਇਸਦਾ ਮੁੱਖ ਉਦੇਸ਼ ਹੀ ਹੈ।

ਮੈਸੇਜ ਬ੍ਰੋਕਰ ਤੋਂ ਬਿਨਾਂ ਜੌਬਸ (Jobs) ਨੂੰ ਕਿਊ (Queue) ਕਿਵੇਂ ਕਰੀਏ

ਲਾਈਵ ਕਾਰ ਔਕਸ਼ਨ ਦੀ ਸਕ੍ਰੇਪਿੰਗ ਸਿੰਕਰੋਨਸਲੀ (synchronously) ਨਹੀਂ ਹੋ ਸਕਦੀ। ਇੱਕ ਸਿੰਗਲ ਸਕ੍ਰੇਪ ਵਿੱਚ ਕਈ ਸਕਿੰਟ ਲੱਗ ਸਕਦੇ ਹਨ ਕਿਉਂਕਿ Playwright ਪੇਜ ਨੂੰ ਲੋਡ ਕਰਦਾ ਹੈ, JavaScript ਨੂੰ ਚਲਾਉਂਦਾ ਹੈ, ਅਤੇ ਡਾਟਾ ਕੱਢਦਾ ਹੈ। ਇਸ ਦੌਰਾਨ ਯੂਜ਼ਰ ਨੂੰ ਰੋਕਣਾ ਕੋਈ ਵਿਕਲਪ ਨਹੀਂ ਹੈ। ਸਟੈਂਡਰਡ ਪਲੇਅਬੁੱਕ ਕਹਿੰਦੀ ਹੈ ਕਿ Redis ਇੰਸਟਾਲ ਕਰੋ, Celery ਕੌਂਫਿਗਰ ਕਰੋ, ਅਤੇ ਇੱਕ ਵਰਕਰ ਪੂਲ (worker pool) ਤਿਆਰ ਕਰੋ। ਮੈਂ ਇਹ ਸਭ ਕੁਝ ਛੱਡ ਦਿੱਤਾ।

ਇਸ ਦੀ ਬਜਾਏ, AutoMakler Postgres ਨੂੰ ਆਪਣੇ ਜੌਬ ਕਿਊ (job queue) ਵਜੋਂ ਵਰਤਦਾ ਹੈ। ਜਦੋਂ ਕੋਈ ਯੂਜ਼ਰ ਸਕ੍ਰੇਪ ਟ੍ਰਿਗਰ ਕਰਦਾ ਹੈ, ਤਾਂ ਐਪਲੀਕੇਸ਼ਨ 'pending' ਸਟੇਟਸ ਦੇ ਨਾਲ ਇੱਕ ਨਵੀਂ ਰੋਅ (row) ਨੂੰ tasks ਟੇਬਲ ਵਿੱਚ ਲਿਖਦੀ ਹੈ। ਇੱਕ asyncio ਬੈਕਗਰਾਊਂਡ ਟਾਸਕ ਉਸ ਰੋਅ ਨੂੰ ਚੁੱਕਦਾ ਹੈ ਅਤੇ ਬ੍ਰਾਊਜ਼ਰ ਸਕ੍ਰੇਪ ਸ਼ੁਰੂ ਕਰਦਾ ਹੈ। ਇਸ ਦੌਰਾਨ, ਬ੍ਰਾਊਜ਼ਰ ਸਟੇਟਸ ਦੀ ਜਾਂਚ ਕਰਨ ਲਈ ਹਰ ਤਿੰਨ ਸਕਿੰਟ ਬਾਅਦ ਇੱਕ ਲਾਈਟਵੇਟ ਐਂਡਪੁਆਇੰਟ (endpoint) ਨੂੰ ਪੋਲ (poll) ਕਰਦਾ ਹੈ। ਜਦੋਂ ਰੋਅ 'completed' ਵਿੱਚ ਅਪਡੇਟ ਹੁੰਦੀ ਹੈ, ਤਾਂ ਪੇਜ ਰਿਫ੍ਰੈਸ਼ ਹੁੰਦਾ ਹੈ ਅਤੇ ਨਤੀਜੇ ਦਿਖਾਉਂਦਾ ਹੈ।

ਇਹ ਪੈਟਰਨ ਇਸ ਲਈ ਕੰਮ ਕਰਦਾ ਹੈ ਕਿਉਂਕਿ ਪੋਲਿੰਗ ਇੰਟਰਵਲ ਇੰਨਾ ਛੋਟਾ ਹੈ ਕਿ ਇਹ ਰਿਸਪੌਂਸਿਵ ਮਹਿਸੂਸ ਹੁੰਦਾ ਹੈ ਪਰ ਸਰਵਰ 'ਤੇ ਬੋਝ ਪਾਉਣ ਤੋਂ ਬਚਣ ਲਈ ਕਾਫ਼ੀ ਲੰਬਾ ਹੈ। ਇੱਕ ਕੰਪਿਊਟਰ ਲਈ ਤਿੰਨ ਸਕਿੰਟ ਇੱਕ ਲੰਬਾ ਸਮਾਂ ਹੈ ਅਤੇ ਇੱਕ ਬਾਹਰੀ ਔਕਸ਼ਨ ਸਾਈਟ ਦੀ ਉਡੀਕ ਕਰ ਰਹੇ ਇਨਸਾਨ ਲਈ ਬਹੁਤ ਹੀ ਘੱਟ ਮਹਿਸੂਸ ਹੁੰਦਾ ਹੈ। ਡਾਟਾਬੇਸ ਕੁਦਰਤੀ ਤੌਰ 'ਤੇ ਕੰਕਰੈਂਸੀ (concurrency) ਨੂੰ ਸੰਭਾਲਦਾ ਹੈ, ਅਤੇ ਕਿਉਂਕਿ ਜੌਬਸ ਸਿਰਫ਼ Postgres ਵਿੱਚ ਰੋਅ ਹਨ, ਮੈਂ Celery ਲੌਗਸ ਜਾਂ Redis ਕੀਜ਼ ਵਿੱਚ ਡੂੰਘਾਈ ਤੱਕ ਜਾਣ ਦੀ ਬਜਾਏ ਇੱਕ ਸਧਾਰਨ SQL ਕੁਐਰੀ ਨਾਲ ਕਿਊ ਦੀ ਜਾਂਚ ਕਰ ਸਕਦਾ ਹਾਂ।

ਵਰਕਰ ਪੂਲ ਤੋਂ ਬਿਨਾਂ ਸਰਵਰ ਨੂੰ ਚਾਲੂ ਕਿਵੇਂ ਰੱਖੀਏ

ਬ੍ਰਾਊਜ਼ਰ ਆਟੋਮੇਸ਼ਨ ਮੈਮੋਰੀ ਦੀ ਬਹੁਤ ਵਰਤੋਂ ਕਰਦੀ ਹੈ। ਇੱਕੋ ਸਮੇਂ ਬਹੁਤ ਜ਼ਿਆਦਾ Playwright ਇੰਸਟੈਂਸ ਲਾਂਚ ਕਰੋ ਅਤੇ ਤੁਹਾਡਾ ਸਰਵਰ ਡਿੱਗ ਜਾਵੇਗਾ। ਰਵਾਇਤੀ ਹੱਲ ਕੰਕਰੈਂਸੀ ਸੀਮਾਵਾਂ ਵਾਲਾ ਇੱਕ ਮੈਨੇਜਡ ਵਰਕਰ ਪੂਲ ਹੈ, ਜੋ ਅਕਸਰ ਉਸੇ Redis ਅਤੇ Celery ਦੇ ਸੁਮੇਲ ਦੁਆਰਾ ਚਲਾਇਆ ਜਾਂਦਾ ਹੈ। ਮੈਂ Python ਦੀ ਇੱਕ ਲਾਈਨ ਦੀ ਵਰਤੋਂ ਕਰਦਾ ਹਾਂ: ਇੱਕ asyncio.Semaphore

ਸੇਮਾਫੋਰ (semaphore) ਇਸ ਗੱਲ ਨੂੰ ਸੀਮਤ ਕਰਦਾ ਹੈ ਕਿ ਇੱਕੋ ਸਮੇਂ ਕਿੰਨੇ ਬ੍ਰਾਊਜ਼ਰ ਇੰਸਟੈਂਸ ਚੱਲ ਸਕਦੇ ਹਨ। ਜਦੋਂ ਇੱਕ ਨਵਾਂ ਸਕ੍ਰੇਪ ਰਿਕਵੈਸਟ ਆਉਂਦੀ ਹੈ, ਤਾਂ ਇਹ ਜਾਂ ਤਾਂ ਤੁਰੰਤ ਇੱਕ ਸਲਾਟ ਲੈ ਲੈਂਦੀ ਹੈ ਜਾਂ ਉਦੋਂ ਤੱਕ ਉਡੀਕ ਕਰਦੀ ਹੈ ਜਦੋਂ ਤੱਕ ਇੱਕ ਖਾਲੀ ਨਹੀਂ ਹੋ ਜਾਂਦਾ। ਇਹ ਸਭ ਇੱਕੋ ਪ੍ਰੋਸੈਸ ਦੇ ਅੰਦਰ ਹੁੰਦਾ ਹੈ। ਇੱਥੇ ਫੇਲ ਹੋਣ ਲਈ ਕੋਈ ਬਾਹਰੀ ਆਰਕੈਸਟਰੇਟਰ ਨਹੀਂ ਹੈ, ਕੋਈ ਵਰਕਰ ਪ੍ਰੋਸੈਸ ਨਹੀਂ ਹੈ ਜੋ ਚੁੱਪਚਾਪ ਮਰ ਜਾਵੇ, ਅਤੇ ਨਿਗਰਾਨੀ ਕਰਨ ਲਈ ਕੋਈ ਵਾਧੂ ਇਨਫਰਾਸਟ੍ਰਕਚਰ ਨਹੀਂ ਹੈ। ਮੇਰੀ ਮੈਮੋਰੀ ਅਨੁਮਾਨਿਤ ਰਹਿੰਦੀ ਹੈ, ਅਤੇ ਸਰਵਰ ਦੀ ਰੱਖਿਆ ਕਰਨ ਵਾਲਾ ਕੋਡ ਉਸੇ ਕੋਡ ਦੇ ਕੋਲ ਹੁੰਦਾ ਹੈ ਜੋ ਇਸਦੀ ਵਰਤੋਂ ਕਰਦਾ ਹੈ, ਨਾ ਕਿ ਕਿਸੇ ਡਿਪਲੋਇਮੈਂਟ ਮੈਨੀਫੈਸਟ ਵਿੱਚ ਲੁਕਿਆ ਹੋਇਆ।

ਇੱਕ ਕਾਲਬੈਕ URL ਨਾਲ ਪੈਸਿਆਂ ਦਾ ਰੁਟਿੰਗ ਕਰਨਾ

ਭੁਗਤਾਨ ਪ੍ਰੋਸੈਸਿੰਗ ਨੇ ਇੱਕ ਅਜਿਹੀ ਸੀਮਾ (constraint) ਪੈਦਾ ਕੀਤੀ ਜਿਸ ਨੂੰ ਮੈਂ ਬਦਲ ਨਹੀਂ ਸਕਦਾ ਸੀ। ਮੇਰਾ ਪੇਮੈਂਟ ਗੇਟਵੇਅ ਹਰੇਕ ਮਰਚੈਂਟ ਅਕਾਊਂਟ ਲਈ ਬਿਲਕੁਲ ਇੱਕ ਕਾਲਬੈਕ URL ਦੀ ਇਜਾਜ਼ਤ ਦਿੰਦਾ ਹੈ, ਪਰ ਮੈਨੂੰ ਉਸੇ ਸਿੰਗਲ ਅਕਾਊਂਟ ਰਾਹੀਂ ਦੋ ਵੱਖ-ਵੱਖ ਪ੍ਰੋਜੈਕਟਾਂ ਲਈ ਟ੍ਰਾਂਜੈਕਸ਼ਨਾਂ ਨੂੰ ਪ੍ਰੋਸੈਸ ਕਰਨ ਦੀ ਲੋੜ ਸੀ। ਦੂਜੀ ਮਰਚੈਂਟ ਪ੍ਰੋਫਾਈਲ ਬਣਾਉਣ ਦਾ ਮਤਲਬ ਵਾਧੂ ਫੀਸਾਂ, ਵਾਧੂ ਕੰਪਲਾਇੰਸ ਅਤੇ ਵਾਧੂ ਕਾਗਜ਼ੀ ਕਾਰਵਾਈ ਹੁੰਦੀ, ਜਿਸ ਲਈ ਇੱਕ ਛੋਟੀ ਬ੍ਰੋਕਰੇਜ ਕੋਲ ਸਮਾਂ ਨਹੀਂ ਹੁੰਦਾ।

ਇਸ ਦਾ ਹੱਲ ਗਾਹਕ ਨੂੰ ਗੇਟਵੇਅ 'ਤੇ ਭੇਜਣ ਤੋਂ ਪਹਿਲਾਂ ਆਰਡਰ ID ਸਟ੍ਰਿੰਗ ਵਿੱਚ ਸਿੱਧੇ ਤੌਰ 'ਤੇ ਪ੍ਰੋਜੈਕਟ ਦਾ ਨਾਮ ਇਨਕੋਡ (encode) ਕਰਨਾ ਸੀ। ਜਦੋਂ ਕਾਲਬੈਕ ਮੇਰੇ ਸਰਵਰ 'ਤੇ ਆਉਂਦਾ ਹੈ, AutoMakler ਉਸ ID ਨੂੰ ਡੀਕੋਡ ਕਰਦਾ ਹੈ, ਪਛਾਣਦਾ ਹੈ ਕਿ ਭੁਗਤਾਨ ਕਿਸ ਪ੍ਰੋਜੈਕਟ ਨਾਲ ਸਬੰਧਤ ਹੈ, ਅਤੇ ਨੋਟੀਫਿਕੇਸ਼ਨ ਨੂੰ ਸਹੀ ਅੰਦਰੂਨੀ ਹੈਂਡਲਰ (handler) ਨੂੰ ਭੇਜ ਦਿੰਦਾ ਹੈ। ਮੌਜੂਦਾ ਲੌਜਿਕ ਨੂੰ ਬਿਨਾਂ ਛੇੜਛਾੜ ਦੇ ਰੱਖਿਆ ਗਿਆ। ਇਹ ਇੱਕ ਐਡਿਟਿਵ ਡਿਜ਼ਾਈਨ (additive design) ਹੈ: ਮੈਂ ਭੁਗਤਾਨ ਪ੍ਰਵਾਹ ਨੂੰ ਦੁਬਾਰਾ ਨਹੀਂ ਲਿਖਿਆ, ਮੈਂ ਸਿਰਫ਼ ਪਛਾਣਕਰਤਾ (identifier) ਨੂੰ ਥੋੜ੍ਹਾ ਹੋਰ ਸੰਦਰਭ (context) ਦਿੱਤਾ। ਇਹ ਅਜਿਹਾ ਹੈਕ ਹੈ ਜੋ ਪਿੱਛੇ ਮੁੜ ਕੇ ਦੇਖਣ 'ਤੇ ਸਪੱਸ਼ਟ ਲੱਗਦਾ ਹੈ ਪਰ ਆਰਕੀਟੈਕਚਰਲ ਜਿਮਨਾਸਟਿਕਸ (architectural gymnastics) ਦੇ ਕਈ ਘੰਟੇ ਬਚਾਉਂਦਾ ਹੈ।

WebSockets ਤੋਂ ਬਿਨਾਂ ਕੰਮ ਕਰਨ ਵਾਲੀ ਚੈਟ

ਕਸਟਮਰ ਸਪੋਰਟ ਚੈਟ ਅਕਸਰ ਉਹ ਜਗ੍ਹਾ ਹੁੰਦੀ ਹੈ ਜਿੱਥੇ ਇੰਜੀਨੀਅਰ ਹਾਰ ਮੰਨ ਲੈਂਦੇ ਹਨ ਅਤੇ WebSockets ਜੋੜ ਦਿੰਦੇ ਹਨ। ਮੈਨੂੰ in-app messaging ਦੀ ਲੋੜ ਸੀ, ਪਰ ਮੈਂ ਇਨਫਰਾਸਟ੍ਰਕਚਰ ਦੇ ਪ੍ਰਭਾਵ ਨੂੰ ਵੀ ਬਹੁਤ ਘੱਟ ਰੱਖਣਾ ਚਾਹੁੰਦਾ ਸੀ। ਇਸ ਲਈ ਮੈਂ ਉਸੇ polling strategy ਦੀ ਵਰਤੋਂ ਕੀਤੀ ਜੋ auction scrapes ਨੂੰ ਚਲਾਉਂਦੀ ਹੈ।

ਮੈਸੇਜ Postgres ਵਿੱਚ ਸਟੋਰ ਕੀਤੇ ਜਾਂਦੇ ਹਨ। ਜਦੋਂ ਕੋਈ ਯੂਜ਼ਰ ਮੈਸੇਜ ਭੇਜਦਾ ਹੈ, ਤਾਂ ਇਹ ਟੇਬਲ ਵਿੱਚ ਲਿਖਿਆ ਜਾਂਦਾ ਹੈ। ਕਲਾਇੰਟ ਅੱਪਡੇਟਸ ਲਈ poll ਕਰਦਾ ਹੈ, ਅਤੇ UI ਲਗਭਗ real-time ਵਿੱਚ ਨਵੇਂ ਮੈਸੇਜ ਅਤੇ read receipts ਦਿਖਾਉਂਦਾ ਹੈ। ਜਿਵੇਂ-ਜਿਵੇਂ conversation table ਵਧਦਾ ਹੈ, ਇਸ ਨੂੰ ਤੇਜ਼ ਰੱਖਣ ਲਈ, ਮੈਂ ਇੱਕ Postgres partial index ਜੋੜਿਆ ਜੋ ਸਿਰਫ਼ ਸਰਗਰਮ (active) ਗੱਲਬਾਤਾਂ ਲਈ ਅਣਪੜ੍ਹੇ (unread) ਮੈਸੇਜਾਂ ਨੂੰ ਕਵਰ ਕਰਦਾ ਹੈ। ਡਾਟਾਬੇਸ ਪੁਰਾਣੀ ਹਿਸਟਰੀ ਨੂੰ ਸਕੈਨ ਕਰਨ ਵਿੱਚ ਸਾਈਕਲ ਬਰਬਾਦ ਨਹੀਂ ਕਰਦਾ, ਅਤੇ query planner ਇੱਕ ਤੰਗ index range scan ਨਾਲ ਜ਼ਿਆਦਾਤਰ ਚੈਟ ਲੁੱਕਅਪਸ ਨੂੰ ਪੂਰਾ ਕਰ ਸਕਦਾ ਹੈ।

ਇੱਕ ਸਪੋਰਟ ਚੈਟ ਲਈ ਜਿੱਥੇ ਕੁਝ ਸਕਿੰਟਾਂ ਦੀ latency ਸਵੀਕਾਰਯੋਗ ਹੈ, ਇਹ ਬਿਲਕੁਲ ਢੁਕਵਾਂ ਹੈ। ਯੂਜ਼ਰਾਂ ਨੂੰ ਉਹ ਫੀਡਬੈਕ ਮਿਲ ਜਾਂਦਾ ਹੈ ਜਿਸਦੀ ਉਹਨਾਂ ਨੂੰ ਲੋੜ ਹੈ, ਅਤੇ ਮੈਨੂੰ ਕਦੇ ਵੀ ਕਿਸੇ ਖ਼ਰਾਬ (stale) WebSocket ਕਨੈਕਸ਼ਨ ਨੂੰ ਡੀਬੱਗ ਕਰਨ ਜਾਂ ਵੱਖਰੇ ਸਾਕਟ ਸਰਵਰ ਨੂੰ ਪ੍ਰਬੰਧਿਤ ਕਰਨ ਦੀ ਲੋੜ ਨਹੀਂ ਪਈ।

ਇਮਾਨਦਾਰ ਕਮੀਆਂ

ਇਹ ਆਰਕੀਟੈਕਚਰ ਅਸਲ ਵਿੱਚ ਕੁਝ ਸਮਝੌਤੇ (trade-offs) ਕਰਦਾ ਹੈ, ਅਤੇ ਇਸਦੇ ਉਲਟ ਦਿਖਾਵਾ ਕਰਨਾ ਬੇਇਮਾਨੀ ਹੋਵੇਗੀ। Polling ਬਹੁਤ ਜ਼ਿਆਦਾ ਰਿਕਵੈਸਟਾਂ ਭੇਜਦਾ ਹੈ (chatty ਹੈ)। ਹਰ ਤਿੰਨ ਸਕਿੰਟਾਂ ਵਿੱਚ, ਹਰ ਸਰਗਰਮ ਕਲਾਇੰਟ ਸਰਵਰ ਨੂੰ ਰਿਕਵੈਸਟ ਭੇਜਦਾ ਹੈ। Bandwidth ਅਤੇ query load ਇੱਕ persistent socket connection ਦੀ ਮੰਗ ਨਾਲੋਂ ਜ਼ਿਆਦਾ ਹੁੰਦੇ ਹਨ। ਜੇਕਰ Python process ਰੀਸਟਾਰਟ ਹੁੰਦਾ ਹੈ, ਤਾਂ ਕੋਈ ਵੀ ਚੱਲ ਰਿਹਾ (in-flight) background task ਤੁਰੰਤ ਖ਼ਤਮ ਹੋ ਜਾਂਦਾ ਹੈ ਕਿਉਂਕਿ ਇਸਨੂੰ ਦੁਬਾਰਾ ਚੁੱਕਣ ਲਈ ਕੋਈ ਬਾਹਰੀ ਵਰਕਰ ਨਹੀਂ ਹੈ। ਮੈਂ ਇਸਨੂੰ ਸਵੀਕਾਰ ਕਰਦਾ ਹਾਂ ਕਿਉਂਕਿ ਕੰਮ ਛੋਟੇ ਹਨ ਅਤੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ (retry) ਕਰਨ ਦੀ ਲਾਗਤ ਘੱਟ ਹੈ। ਇੱਕ ਅਸਫਲ browser scrape ਨੂੰ ਯੂਜ਼ਰ ਦੁਆਰਾ ਸਿਰਫ਼ ਦੁਬਾਰਾ ਸ਼ੁਰੂ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ।

ਇਸ ਪਹੁੰਚ ਦੀ ਇੱਕ ਸੀਮਾ ਵੀ ਹੈ। ਜੇਕਰ AutoMakler ਨੂੰ ਕਦੇ ਹਜ਼ਾਰਾਂ ਸਮਾਨਾਂਤਰ (simultaneous) scrapes ਦੀ ਸੇਵਾ ਕਰਨ ਦੀ ਲੋੜ ਪੈਂਦੀ ਹੈ, ਤਾਂ polling ਵਾਲਾ single-process ਮਾਡਲ ਦਬਾਅ ਵਿੱਚ ਆ ਜਾਵੇਗਾ। ਪਰ ਇਹ ਉਹ ਕਾਰੋਬਾਰ ਨਹੀਂ ਹੈ ਜਿਸ ਵਿੱਚ ਮੈਂ ਹਾਂ। ਮੈਨੂੰ ਦਰਜਨਾਂ ਇਕਸਾਰ (concurrent) ਯੂਜ਼ਰਾਂ ਲਈ ਭਰੋਸੇਯੋਗਤਾ ਦੀ ਲੋੜ ਹੈ, ਨਾ ਕਿ