ਇੱਕ ਭਾਰੀ ਚੈਟ ਸਾਡੀ API ਨੂੰ ਕਿਵੇਂ ਬੰਦ ਕਰ ਸਕਦੀ ਸੀ
28 ਸਤੰਬਰ ਨੂੰ, ਇੱਕ ਰਿਲੀਜ਼ ਤੋਂ ਲਗਭਗ 17 ਮਿੰਟ ਬਾਅਦ, ਸਾਡੇ ਦੋਵੇਂ ਪ੍ਰੋਡਕਸ਼ਨ API ਸਰਵਰ ਇੱਕੋ ਪਲ 'ਤੇ ਮੈਮਰੀ ਤੋਂ ਬਾਹਰ ਹੋ ਗਏ, ਮੁੜ ਚਾਲੂ ਹੋਏ, ਅਤੇ ਲਗਭਗ ਪੰਜ ਮਿੰਟ ਲਈ ਲੋਡ ਬੈਲੈਂਸਰ ਕੋਲ ਆਵਾਜਾਈ ਭੇਜਣ ਲਈ ਕੋਈ ਤੰਦਰੁਸਤ ਸਰਵਰ ਨਹੀਂ ਸੀ। ਸਾਡੇ ਪਹਿਲੇ ਹੱਲ ਨੇ API ਨੂੰ ਦੁੱਗਣੀ ਮੈਮਰੀ ਦਿੱਤੀ। ਅਸਲ ਕਾਰਨ ਉਸੇ ਦਿਨ ਬਾਅਦ ਵਿੱਚ ਸਾਹਮਣੇ ਆਇਆ: ਇੱਕ ਖਾਸ ਚੈਟ ਖੋਲ੍ਹਣ ਨਾਲ API ਇੱਕ ਹੀ ਬੇਨਤੀ ਵਿੱਚ 53 MB ਸੁਨੇਹੇ ਲੋਡ ਕਰਨ ਲੱਗਦੀ ਸੀ। ਹੁਣ ਚੈਟ ਇਤਿਹਾਸ ਗਿਣਤੀ ਦੇ ਨਾਲ-ਨਾਲ ਆਕਾਰ ਨਾਲ ਵੀ ਸੀਮਤ ਪੰਨਿਆਂ ਵਿੱਚ ਲੋਡ ਹੁੰਦਾ ਹੈ, ਅਤੇ ਉਹ ਚੈਟ ਕਰੈਸ਼ ਦੀ ਥਾਂ 5 MB ਦੇ ਪਹਿਲੇ ਪੰਨੇ ਨਾਲ ਖੁੱਲ੍ਹਦੀ ਹੈ।
ਕੀ ਬੰਦ ਹੋਇਆ
ਸਾਡੀ API ਦੋ ਸਰਵਰਾਂ 'ਤੇ, ਲੋਡ ਬੈਲੈਂਸਰ ਦੇ ਪਿੱਛੇ, ਹਰ ਇੱਕ ਕੰਟੇਨਰ ਵਜੋਂ ਚੱਲਦੀ ਹੈ। ਹਰ ਕੰਟੇਨਰ ਦੀ ਮੈਮਰੀ ਹੱਦ 384 MiB ਸੀ। ਆਮ ਹਾਲਤ ਵਿੱਚ ਇਹ 130–140 MiB ਵਰਤਦੀ ਹੈ, ਇਸ ਲਈ ਹੱਦ ਕਾਫ਼ੀ ਖੁੱਲ੍ਹੀ ਲੱਗਦੀ ਸੀ।
ਦੋਵੇਂ ਕੰਟੇਨਰ ਇੱਕੋ ਵੇਲੇ ਇਸ ਹੱਦ ਤੱਕ ਪਹੁੰਚੇ ਅਤੇ “JavaScript heap out of memory” ਨਾਲ ਕਰੈਸ਼ ਹੋ ਗਏ। ਹੀਪ ਉਹ ਮੈਮਰੀ ਹੈ ਜੋ Node.js ਪ੍ਰੋਸੈਸ ਆਪਣੀਆਂ ਵਸਤੂਆਂ ਲਈ ਵਰਤਦਾ ਹੈ। ਕਿਉਂਕਿ ਦੋਵੇਂ ਸਰਵਰ ਇੱਕੋ ਸਮੇਂ ਫੇਲ੍ਹ ਹੋਏ, ਬੇਨਤੀਆਂ ਭੇਜਣ ਲਈ ਕੋਈ ਥਾਂ ਨਹੀਂ ਬਚੀ। ਦੋ-ਸਰਵਰ ਵਾਲੇ ਸੈੱਟਅੱਪ ਲਈ ਇਹ ਸਭ ਤੋਂ ਭੈੜੀ ਕਿਸਮ ਦੀ ਆਊਟੇਜ ਹੈ: ਰਿਡੰਡੈਂਸੀ ਉਦੋਂ ਹੀ ਮਦਦ ਕਰਦੀ ਹੈ ਜਦੋਂ ਫੇਲ੍ਹ ਹੋਣਾ ਇੱਕੋ ਸਮੇਂ ਨਾ ਹੋਵੇ।
ਪਹਿਲਾ ਹੱਲ: ਵੱਧ ਥਾਂ
ਸਮਾਂ ਡਿਪਲੌਇਮੈਂਟ ਵੱਲ ਇਸ਼ਾਰਾ ਕਰਦਾ ਸੀ। ਰਿਲੀਜ਼ ਤੋਂ ਬਾਅਦ, ਡਿਪਲੌਇ ਨੇ ਜਿਹੜੇ ਏਜੰਟ ਟਰਨ ਰੋਕੇ ਸਨ, ਉਹ ਮੁੜ ਸ਼ੁਰੂ ਹੁੰਦੇ ਹਨ ਅਤੇ ਆਪਣੇ ਟ੍ਰਾਂਸਕ੍ਰਿਪਟ ਮੁੜ ਸੰਭਾਲਦੇ ਹਨ, ਅਤੇ ਕੰਮ ਦੇ ਉਸ ਝਟਕੇ ਨੂੰ ਮੈਮਰੀ ਵਾਧੇ ਦਾ ਸਪੱਸ਼ਟ ਕਾਰਨ ਲੱਗਿਆ।
ਇਸ ਲਈ ਪਹਿਲੇ ਬਦਲਾਅ ਵਿੱਚ API ਦੀ ਹੱਦ 384 MiB ਤੋਂ ਵਧਾ ਕੇ 768 MiB ਕੀਤੀ ਗਈ। ਅਸੀਂ ਇਹ ਉਸੇ ਦਿਨ ਦੋਵੇਂ ਸਰਵਰਾਂ 'ਤੇ ਲਾਈਵ ਲਾਗੂ ਕੀਤਾ, ਅਤੇ ਡਿਪਲੌਇਮੈਂਟ ਕੌਂਫਿਗਰੇਸ਼ਨ ਵਿੱਚ ਵੀ ਕਮਿਟ ਕੀਤਾ, ਤਾਂ ਜੋ ਅਗਲਾ ਡਿਪਲੌਇ ਚੁੱਪਚਾਪ 384 ਵਾਪਸ ਨਾ ਲਿਆਵੇ। ਕਿਸੇ ਸਰਵਰ 'ਤੇ ਹੱਥੀਂ ਕੀਤਾ ਫਿਕਸ, ਜਿਸਨੂੰ ਅਗਲਾ ਡਿਪਲੌਇ ਉਲਟਾ ਦੇਵੇ, ਉਸੇ ਆਊਟੇਜ ਨੂੰ ਵਾਪਸ ਲਿਆਉਣ ਦਾ ਆਮ ਤਰੀਕਾ ਹੈ।
ਵੱਧ ਮੈਮਰੀ ਇੱਕ ਵਾਜਬ ਸੁਰੱਖਿਆ ਹਾਸ਼ੀਆ ਸੀ। ਇਹ ਕਾਰਨ ਦੀ ਵਿਆਖਿਆ ਨਹੀਂ ਸੀ।
ਅਸਲ ਕਾਰਨ: ਇੱਕ ਬੇਨਤੀ, 71 MB
ਉਸੇ ਦਿਨ ਬਾਅਦ ਵਿੱਚ ਅਸੀਂ ਇੱਕ ਚੈਟ ਦੀ ਕਾਪੀ 'ਤੇ ਕਰੈਸ਼ ਦੁਹਰਾਇਆ, ਪ੍ਰੋਡਕਸ਼ਨ ਦੀ ਪੁਰਾਣੀ ਮੈਮਰੀ ਹੱਦ ਨਾਲ। ਉਹ ਕਾਪੀ API ਨੂੰ ਆਪਣੇ ਆਪ ਕਰੈਸ਼ ਕਰ ਗਈ, ਬਿਨਾਂ ਕਿਸੇ ਡਿਪਲੌਇ ਦੇ।
ਜਦੋਂ ਤੁਸੀਂ ਕੋਈ ਪ੍ਰੋਜੈਕਟ ਖੋਲ੍ਹਦੇ ਹੋ, ਵੈੱਬ ਐਪ ਚੈਟ ਦਾ ਇਤਿਹਾਸ API ਤੋਂ ਮੰਗਦਾ ਹੈ। ਐਂਡਪੌਇੰਟ ਨਵੇਂ 30 ਸੁਨੇਹੇ ਪੂਰੇ ਵਾਪਸ ਕਰਦਾ ਸੀ। ਜ਼ਿਆਦਾਤਰ ਚੈਟਾਂ ਲਈ 30 ਸੁਨੇਹੇ ਛੋਟੇ ਹੁੰਦੇ ਹਨ। ਇਸ ਚੈਟ ਲਈ, ਨਵੇਂ 30 ਸੁਨੇਹੇ ਡੇਟਾਬੇਸ ਵਿੱਚ 53 MB ਅਤੇ ਜਵਾਬ 71 MB ਸਨ। ਏਜੰਟ ਦੇ ਕਈ ਜਵਾਬ 4–10 MB ਹਰ ਇੱਕ ਸਨ, ਜ਼ਿਆਦਾਤਰ ਸਬ-ਏਜੰਟਾਂ ਦੇ ਟ੍ਰਾਂਸਕ੍ਰਿਪਟ: ਉਹ ਸਹਾਇਕ ਏਜੰਟ ਜੋ ਮੁੱਖ ਏਜੰਟ ਕੰਮ ਦਾ ਹਿੱਸਾ ਸਮਾਨਾਂਤਰ ਕਰਵਾਉਣ ਲਈ ਸ਼ੁਰੂ ਕਰਦਾ ਹੈ, ਜਿਨ੍ਹਾਂ ਦਾ ਪੂਰਾ ਕੰਮ ਜਵਾਬ ਨਾਲ ਸੰਭਾਲਿਆ ਜਾਂਦਾ ਹੈ।
ਉਹ ਇੱਕ ਜਵਾਬ ਬਣਾਉਣ ਲਈ API ਕੋਲ ਹੀਪ ਨਾਲੋਂ ਵੱਧ ਮੈਮਰੀ ਲੱਗਦੀ ਸੀ। ਅਤੇ ਉਸ ਪ੍ਰੋਜੈਕਟ ਨੂੰ ਖੋਲ੍ਹਣ ਜਾਂ ਰਿਫਰੈਸ਼ ਕਰਨ ਨਾਲ ਬੇਨਤੀ ਮੁੜ ਜਾਂਦੀ ਸੀ। ਇੱਕ ਹੀ ਚੈਟ ਉਸ ਸਰਵਰ ਨੂੰ ਬੰਦ ਕਰ ਸਕਦੀ ਸੀ ਜਿਸ 'ਤੇ ਉਹ ਪਹੁੰਚਦੀ, ਅਤੇ ਕਿਉਂਕਿ ਪੇਜ ਰੀਲੋਡ ਹੋ ਸਕਦਾ ਸੀ, ਉਹ ਦੋਵਾਂ ਤੱਕ ਪਹੁੰਚ ਸਕਦੀ ਸੀ।
“30 ਸੁਨੇਹੇ” ਕਦੇ ਆਕਾਰ ਦੀ ਅਸਲ ਹੱਦ ਨਹੀਂ ਸੀ। ਇਹ ਗਿਣਤੀ ਦੀ ਹੱਦ ਸੀ, ਜੋ ਆਮ ਚੈਟਾਂ ਲਈ ਛੋਟੀ ਸੀ।
ਹੱਲ: ਗਿਣਤੀ ਦੇ ਨਾਲ-ਨਾਲ ਆਕਾਰ ਨਾਲ ਸੀਮਤ ਪੰਨੇ
ਇਤਿਹਾਸ ਦਾ ਇੱਕ ਪੰਨਾ ਹੁਣ 30 ਸੁਨੇਹੇ ਜਾਂ ਉਹਨਾਂ ਦਾ ਲਗਭਗ 4 MB, ਜੋ ਵੀ ਪਹਿਲਾਂ ਆਵੇ, ਹੈ।
ਇਹ ਦੋ ਕਦਮਾਂ ਵਿੱਚ ਕੰਮ ਕਰਦਾ ਹੈ:
- ਪਹਿਲਾਂ ਆਕਾਰ ਮੰਗੋ। API ਡੇਟਾਬੇਸ ਤੋਂ ਨਵੇਂ ਸੁਨੇਹਿਆਂ ਦੀਆਂ ID ਅਤੇ ਸਟੋਰ ਕੀਤੇ ਆਕਾਰ ਮੰਗਦਾ ਹੈ, ਉਹਨਾਂ ਦੀ ਸਮੱਗਰੀ ਤੋਂ ਬਿਨਾਂ। ਇਹ ਕਵੈਰੀ ਸੁਨੇਹੇ ਕਿੰਨੇ ਵੀ ਵੱਡੇ ਹੋਣ, ਸਸਤੀ ਹੈ।
- ਸਿਰਫ਼ ਉਹੀ ਲੋਡ ਕਰੋ ਜੋ ਫਿੱਟ ਹੋਵੇ। ਨਵੇਂ ਤੋਂ ਪੁਰਾਣੇ ਵੱਲ ਚੱਲਦਿਆਂ, ਇਹ ਸੁਨੇਹੇ ਜੋੜਦਾ ਹੈ ਜਦ ਤੱਕ ਅਗਲਾ ਸੁਨੇਹਾ ਪੰਨੇ ਨੂੰ 4 MB ਤੋਂ ਪਾਰ ਨਾ ਲੈ ਜਾਵੇ। ਫਿਰ ਸਿਰਫ਼ ਉਹ ਕਤਾਰਾਂ ਪੂਰੀਆਂ ਲੋਡ ਹੁੰਦੀਆਂ ਹਨ।
ਦੋ ਨਿਯਮ ਇਸਨੂੰ ਸੁਰੱਖਿਅਤ ਰੱਖਦੇ ਹਨ:
- ਸਭ ਤੋਂ ਨਵਾਂ ਸੁਨੇਹਾ ਹਮੇਸ਼ਾਂ ਪੰਨੇ 'ਤੇ ਜਾਂਦਾ ਹੈ, ਉਸਦੇ ਆਕਾਰ ਦੇ ਬਾਵਜੂਦ। ਜੇ ਪੰਨਾ ਕੁਝ ਵੀ ਨਾ ਦੇਵੇ, ਤਾਂ ਚੈਟ ਅਟਕ ਜਾਵੇਗੀ, ਅਤੇ ਪਿੱਛੇ ਸਕ੍ਰੋਲ ਕਰਨ ਦਾ ਕੋਈ ਰਸਤਾ ਨਹੀਂ ਰਹੇਗਾ।
- ਕੁਝ ਵੀ ਕੱਟਿਆ ਨਹੀਂ ਜਾਂਦਾ। ਕੋਈ ਸੁਨੇਹਾ ਛੋਟਾ ਨਹੀਂ ਕੀਤਾ ਜਾਂਦਾ ਜਾਂ ਸੁੱਟਿਆ ਨਹੀਂ ਜਾਂਦਾ। ਬਾਕੀ ਚੈਟ “Scroll up for earlier messages” ਕੰਟਰੋਲ ਰਾਹੀਂ ਲੋਡ ਹੁੰਦੀ ਹੈ, ਜੋ ਪੁਰਾਣੇ ਸੁਨੇਹਿਆਂ ਲਈ ਪਹਿਲਾਂ ਹੀ ਵਰਤੀ ਜਾਂਦੀ ਸੀ, ਇੱਕ ਵੇਲੇ ਇੱਕ ਪੰਨਾ।
ਇੱਕ ਹੋਰ ਥਾਂ ਵੀ ਇਹੀ ਢਾਂਚਾ ਮਿਲਿਆ। ਜਦੋਂ ਤੁਸੀਂ ਕੋਈ ਟਰਨ ਰੋਕਦੇ ਹੋ, API ਆਖਰੀ ਕੁਝ ਜਵਾਬ ਜਾਂਚਦਾ ਹੈ ਕਿ ਕੋਈ ਖਾਲੀ ਤਾਂ ਨਹੀਂ ਜਿਸਨੂੰ ਸਾਫ਼ ਕਰਨਾ ਚਾਹੀਦਾ ਹੈ। ਇਹ ਪੂਰੇ ਅੱਠ ਸੁਨੇਹੇ ਲੋਡ ਕਰਕੇ ਕਰਦਾ ਸੀ। ਕਈ-ਮੈਗਾਬਾਈਟ ਜਵਾਬਾਂ ਵਾਲੀ ਚੈਟ 'ਤੇ, ਇਹ ਛੋਟੇ ਰੂਪ ਵਿੱਚ ਉਹੀ ਸਮੱਸਿਆ ਸੀ। ਹੁਣ ਇਹ ਡੇਟਾਬੇਸ ਨੂੰ ਹਾਂ-ਜਾਂ-ਨਾਂਹ ਸਵਾਲ ਪੁੱਛਦਾ ਹੈ, ਕੀ ਇਸ ਸੁਨੇਹੇ ਵਿੱਚ ਕੋਈ ਸਮੱਗਰੀ ਹੈ? ਅਤੇ ਸਮੱਗਰੀ ਖੁਦ ਲੋਡ ਨਹੀਂ ਕਰਦਾ।
ਅਸੀਂ ਇਹ ਕਿਵੇਂ ਜਾਂਚਿਆ
ਚੈਟ ਦੀ ਕਾਪੀ 'ਤੇ, ਪੁਰਾਣੀ 384 MiB ਹੱਦ ਨਾਲ ਚਲਦੇ ਹੋਏ:
- ਪਹਿਲਾ ਪੰਨਾ 5 MB ਹੈ। ਪਹਿਲਾਂ ਉਸੇ ਬੇਨਤੀ ਨੇ API ਨੂੰ ਕਰੈਸ਼ ਕੀਤਾ ਸੀ।
- ਇੱਕੋ ਵੇਲੇ ਚੈਟ ਖੋਲ੍ਹਣ ਵਾਲੇ ਪੰਜ ਬ੍ਰਾਊਜ਼ਰ ਟੈਬ ਮੈਮਰੀ ਵਿੱਚ 154 MB ਦੀ ਸਿਖਰ ਤੱਕ ਪਹੁੰਚਦੇ ਹਨ।
- ਪੂਰੀ ਚੈਟ ਪਿੱਛੇ ਸਕ੍ਰੋਲ ਕਰਨ 'ਤੇ ਸਾਰੇ 190 ਸੁਨੇਹੇ ਮਿਲਦੇ ਹਨ, ਹਰ ਇੱਕ ਸਿਰਫ਼ ਇੱਕ ਵਾਰ, ਕ੍ਰਮ ਵਿੱਚ।
ਪੰਨਾ ਚੁਣਨ ਵਾਲੇ ਲਾਜਿਕ ਦੇ ਯੂਨਿਟ ਟੈਸਟ ਵੀ ਹਨ, ਜਿਹਨਾਂ ਵਿੱਚੋਂ ਇੱਕ ਉਸ ਚੈਟ ਦੇ ਨਵੇਂ ਸੁਨੇਹਿਆਂ ਦੇ ਅਸਲ ਆਕਾਰਾਂ ਨਾਲ ਬਣਿਆ ਹੈ। ਪਹਿਲਾ ਪੰਨਾ ਇੱਕ ਸੁਨੇਹਾ ਦਿੰਦਾ ਹੈ, ਦੱਸਦਾ ਹੈ ਕਿ ਹੋਰ ਵੀ ਹਨ, ਅਤੇ ਅਗਲਾ ਪੰਨਾ ਉਸਦੇ ਅਗਲੇ ਤੋਂ ਸ਼ੁਰੂ ਹੁੰਦਾ ਹੈ।
ਅਸੀਂ ਇਸ ਤੋਂ ਕੀ ਸਿੱਖਿਆ
- ਗਿਣਤੀ ਆਕਾਰ ਦੀ ਹੱਦ ਨਹੀਂ ਹੁੰਦੀ। ਹਰ ਐਂਡਪੌਇੰਟ ਜੋ “ਸਭ ਤੋਂ ਨਵੇਂ N” ਵਾਪਸ ਕਰਦਾ ਹੈ ਅਤੇ ਜੋ ਬੇਅੰਤ ਵਧ ਸਕਦਾ ਹੈ, ਉਸਨੂੰ ਬਾਈਟ ਬਜਟ ਵੀ ਚਾਹੀਦਾ ਹੈ। ਡੇਟਾ ਆਖਰਕਾਰ ਉਸ ਪਾੜੇ ਨੂੰ ਲੱਭ ਲੈਂਦਾ ਹੈ।
- ਸਪੱਸ਼ਟ ਸ਼ੱਕੀ ਹਮੇਸ਼ਾਂ ਕਾਰਨ ਨਹੀਂ ਹੁੰਦਾ। ਡਿਪਲੌਇ ਵਾਧੂ ਕੰਮ ਦਾ ਅਸਲ ਟਰਿੱਗਰ ਸੀ, ਅਤੇ ਵੱਧ ਮੈਮਰੀ ਲੈਣਾ ਵਾਜਬ ਸੀ। ਪਰ ਕਰੈਸ਼ ਡਿਪਲੌਇ ਤੋਂ ਬਿਨਾਂ ਦੁਹਰਾਇਆ ਗਿਆ, ਅਤੇ ਇਸਨੂੰ ਦੁਹਰਾਏ ਬਿਨਾਂ ਅਸੀਂ ਮੈਮਰੀ ਵਾਧੇ 'ਤੇ ਹੀ ਰੁਕ ਜਾਂਦੇ।
- ਦੋ ਸਰਵਰ ਇਕੱਠੇ ਫੇਲ੍ਹ ਹੁੰਦੇ ਹਨ ਜਦੋਂ ਉਹਨਾਂ ਨੂੰ ਇੱਕੋ ਬੇਨਤੀ ਮਿਲਦੀ ਹੈ। ਰਿਡੰਡੈਂਸੀ ਇੱਕ ਸਰਵਰ ਦੇ ਮਰਨ ਤੋਂ ਬਚਾਉਂਦੀ ਹੈ। ਇਹ ਉਸ ਬੇਨਤੀ ਤੋਂ ਨਹੀਂ ਬਚਾਉਂਦੀ ਜੋ ਜਿਸ ਵੀ ਸਰਵਰ ਤੱਕ ਪਹੁੰਚੇ ਉਸਨੂੰ ਮਾਰ ਦੇਵੇ, ਖਾਸ ਕਰਕੇ ਜਿਸਨੂੰ ਯੂਜ਼ਰ ਰਿਫਰੈਸ਼ ਕਰਕੇ ਕੁਦਰਤੀ ਤੌਰ 'ਤੇ ਮੁੜ ਚਲਾਏਗਾ।
- ਕੌਂਫਿਗ ਵਿੱਚ ਠੀਕ ਕਰੋ, ਸਿਰਫ਼ ਬਾਕਸ 'ਤੇ ਨਹੀਂ। ਮੈਮਰੀ ਵਾਧਾ ਉਸੇ ਦਿਨ ਡਿਪਲੌਇ ਕੌਂਫਿਗਰੇਸ਼ਨ ਵਿੱਚ ਗਿਆ, ਇਸ ਲਈ ਅਗਲੇ ਡਿਪਲੌਇ ਨੇ ਇਸਨੂੰ ਬਰਕਰਾਰ ਰੱਖਿਆ।
ਇਹ ਏਜੰਟ ਦੇ ਆਉਟਪੁੱਟ ਨਾਲ ਜੁੜੀ ਸਾਡੀ ਦੂਜੀ ਤਾਜ਼ਾ ਮੈਮਰੀ ਕਹਾਣੀ ਹੈ। ਪਹਿਲੀ ਸੀ ਇੱਕ ਸਟੇਟਸ ਲੇਬਲ ਜਿਸਨੇ 690 MB ਸਟਰਿੰਗਾਂ ਕਤਾਰ ਵਿੱਚ ਪਾਈਆਂ। ਜੇ ਤੁਸੀਂ Mythex 'ਤੇ ਸਬ-ਏਜੰਟ ਵਰਤਦੇ ਹੋ, ਤਾਂ ਉਹ ਕਿਵੇਂ ਕੰਮ ਕਰਦੇ ਹਨ ਇਹ ਦਸਤਾਵੇਜ਼ਾਂ ਵਿੱਚ ਪੜ੍ਹ ਸਕਦੇ ਹੋ।