{"id":90012,"date":"2020-07-28T13:42:19","date_gmt":"2020-07-28T11:42:19","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/apache-airflow-delaem-etl-proshhe"},"modified":"2021-02-15T18:59:36","modified_gmt":"2021-02-15T16:59:36","slug":"apache-airflow-delaem-etl-proshhe","status":"publish","type":"post","link":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/apache-airflow-delaem-etl-proshhe","title":{"rendered":"Apache Airflow: rendiamo l'ETL pi\u00f9 semplice","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u044f \u0414\u043c\u0438\u0442\u0440\u0438\u0439 \u041b\u043e\u0433\u0432\u0438\u043d\u0435\u043d\u043a\u043e \u2014 Data Engineer \u043e\u0442\u0434\u0435\u043b\u0430 \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0438 \u0433\u0440\u0443\u043f\u043f\u044b \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0439 \u00ab\u0412\u0435\u0437\u0451\u0442\u00bb.<\/p>\n<p>\u042f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u0432\u0430\u043c \u043e \u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u043c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0435 \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 ETL-\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0432 \u2014 Apache Airflow. \u041d\u043e Airflow \u043d\u0430\u0441\u0442\u043e\u043b\u044c\u043a\u043e \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u0435\u043d \u0438 \u043c\u043d\u043e\u0433\u043e\u0433\u0440\u0430\u043d\u0435\u043d, \u0447\u0442\u043e \u0432\u0430\u043c \u0441\u0442\u043e\u0438\u0442 \u043f\u0440\u0438\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c\u0441\u044f \u043a \u043d\u0435\u043c\u0443 \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u0432\u044b \u043d\u0435 \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442\u0435\u0441\u044c \u043f\u043e\u0442\u043e\u043a\u0430\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u0445, \u0430 \u0438\u043c\u0435\u0435\u0442\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u044c \u043f\u0435\u0440\u0438\u043e\u0434\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043a\u0430\u043a\u0438\u0435-\u043b\u0438\u0431\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u044b \u0438 \u0441\u043b\u0435\u0434\u0438\u0442\u044c \u0437\u0430 \u0438\u0445 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435\u043c.<\/p>\n<p>\u0418 \u0434\u0430, \u044f \u0431\u0443\u0434\u0443 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c, \u043d\u043e \u0438 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c: \u0432 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0435 \u043c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430, \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u043e\u0432 \u0438 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0439.<\/p>\n<p><img decoding=\"async\" alt=\"Apache Airflow: \u0434\u0435\u043b\u0430\u0435\u043c ETL \u043f\u0440\u043e\u0449\u0435\" src=\"\/wp-content\/uploads\/2020\/07\/8b20c546c805c28a6b9482eafc376752.png\" style=\"display:block;margin: 0 auto;\"><br \/>\n<em>\u0427\u0442\u043e \u043e\u0431\u044b\u0447\u043d\u043e \u0432\u0438\u0434\u0438\u0448\u044c, \u043a\u043e\u0433\u0434\u0430 \u0433\u0443\u0433\u043b\u0438\u0448\u044c \u0441\u043b\u043e\u0432\u043e Airflow \/ Wikimedia Commons<\/em><\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2 id=\"oglavlenie\">\u041e\u0433\u043b\u0430\u0432\u043b\u0435\u043d\u0438\u0435<\/h2>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"#vvedenie\">\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#chast-osnovnaya-prakticheskaya-i-nemnogo-teoreticheskaya\">\u0427\u0430\u0441\u0442\u044c \u043e\u0441\u043d\u043e\u0432\u043d\u0430\u044f, \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f (\u0438 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0442\u0435\u043e\u0440\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f)<\/a><\/noindex>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"#zachem-ono-nam-i-vam\">\u0417\u0430\u0447\u0435\u043c \u043e\u043d\u043e \u043d\u0430\u043c (\u0438 \u0432\u0430\u043c)<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#sobiraem-klaster\">\u0421\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u043a\u043b\u0430\u0441\u0442\u0435\u0440<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#osnovnye-ponyatiya\">\u041e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043f\u043e\u043d\u044f\u0442\u0438\u044f<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#generiruem-taski\">\u0413\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u0442\u0430\u0441\u043a\u0438<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#nemnogo-o-flower\">\u041d\u0435\u043c\u043d\u043e\u0433\u043e \u043e Flower<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#dogruzhaem-nedogruzhennoe\">\u0414\u043e\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u043d\u0435\u0434\u043e\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u043e\u0435<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#soedineniya-huki-i-prochie-peremennye\">\u0421\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f, \u0445\u0443\u043a\u0438 \u0438 \u043f\u0440\u043e\u0447\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#razbiraem-kastomnyy-operator\">\u0420\u0430\u0437\u0431\u0438\u0440\u0430\u0435\u043c \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0439 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#nalivat-to-budesh\">\u041d\u0430\u043b\u0438\u0432\u0430\u0442\u044c-\u0442\u043e \u0431\u0443\u0434\u0435\u0448\u044c?<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#podvodim-itogi\">\u041f\u043e\u0434\u0432\u043e\u0434\u0438\u043c \u0438\u0442\u043e\u0433\u0438<\/a><\/noindex><\/li>\n<\/ul>\n<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#chast-zaklyuchitelnaya-spravochno-informacionnaya\">\u0427\u0430\u0441\u0442\u044c \u0437\u0430\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f, \u0441\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u043e-\u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u043e\u043d\u043d\u0430\u044f<\/a><\/noindex>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"#grabli-kotorye-my-sobrali-za-vas\">\u0413\u0440\u0430\u0431\u043b\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u0441\u043e\u0431\u0440\u0430\u043b\u0438 \u0437\u0430 \u0432\u0430\u0441<\/a><\/noindex><\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#sredstva-eschyo-bolshey-avtomatizacii\">\u0421\u0440\u0435\u0434\u0441\u0442\u0432\u0430 \u0435\u0449\u0451 \u0431\u043e\u043b\u044c\u0448\u0435\u0439 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438<\/a><\/noindex><\/li>\n<\/ul>\n<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"#ssylki\">\u0421\u0441\u044b\u043b\u043a\u0438<\/a><\/noindex><\/li>\n<\/ul>\n<h2 id=\"vvedenie\">\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/h2>\n<p>Apache Airflow \u2014 \u043e\u043d \u043f\u0440\u044f\u043c\u043e \u043a\u0430\u043a Django:<\/p>\n<ul>\n<li>\u043d\u0430\u043f\u0438\u0441\u0430\u043d \u043d\u0430 Python,<\/li>\n<li>\u0435\u0441\u0442\u044c \u043e\u0442\u043b\u0438\u0447\u043d\u0430\u044f \u0430\u0434\u043c\u0438\u043d\u043a\u0430,<\/li>\n<li>\u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0435\u043c,<\/li>\n<\/ul>\n<p>\u2014 \u0442\u043e\u043b\u044c\u043a\u043e \u043b\u0443\u0447\u0448\u0435, \u0434\u0430 \u0438 \u0441\u0434\u0435\u043b\u0430\u043d \u0441\u043e\u0432\u0441\u0435\u043c \u0434\u043b\u044f \u0434\u0440\u0443\u0433\u0438\u0445 \u0446\u0435\u043b\u0435\u0439, \u0430 \u0438\u043c\u0435\u043d\u043d\u043e (\u043a\u0430\u043a \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e \u0434\u043e \u043a\u0430\u0442\u0430):<\/p>\n<ul>\n<li>\u0437\u0430\u043f\u0443\u0441\u043a \u0438 \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433 \u0437\u0430\u0434\u0430\u0447 \u043d\u0430 \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u043e\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0435 \u043c\u0430\u0448\u0438\u043d (\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u0430\u043c \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 Celery\/Kubernetes \u0438 \u0432\u0430\u0448\u0430 \u0441\u043e\u0432\u0435\u0441\u0442\u044c)<\/li>\n<li>\u0441 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0435\u0439 workflow \u0438\u0437 \u043e\u0447\u0435\u043d\u044c \u043b\u0435\u0433\u043a\u043e\u0433\u043e \u0434\u043b\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0438 \u0432\u043e\u0441\u043f\u0440\u0438\u044f\u0442\u0438\u044f Python-\u043a\u043e\u0434\u0430<\/li>\n<li>\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u0441\u0432\u044f\u0437\u044b\u0432\u0430\u0442\u044c \u0434\u0440\u0443\u0433 \u0441 \u0434\u0440\u0443\u0433 \u043b\u044e\u0431\u044b\u0435 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 API \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u0430\u043a \u0433\u043e\u0442\u043e\u0432\u044b\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432, \u0442\u0430\u043a \u0438 \u0441\u0430\u043c\u043e\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432 (\u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0447\u0440\u0435\u0437\u0432\u044b\u0447\u0430\u0439\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e).<\/li>\n<\/ul>\n<p>\u041c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c Apache Airflow \u0442\u0430\u043a:<\/p>\n<ul>\n<li>\u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u0432 (\u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u043e\u0432 SQL Server \u0438 PostgreSQL, \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 API \u0441 \u043c\u0435\u0442\u0440\u0438\u043a\u0430\u043c\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439, \u0434\u0430\u0436\u0435 1\u0421) \u0432 DWH \u0438 ODS (\u0443 \u043d\u0430\u0441 \u044d\u0442\u043e Vertica \u0438 Clickhouse).<\/li>\n<li>\u043a\u0430\u043a \u043f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u044b\u0439 <code>cron<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u044b \u043a\u043e\u043d\u0441\u043e\u043b\u0438\u0434\u0430\u0446\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 ODS, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0441\u043b\u0435\u0434\u0438\u0442 \u0437\u0430 \u0438\u0445 \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u043d\u0438\u0435\u043c.<\/li>\n<\/ul>\n<p>\u0414\u043e \u043d\u0435\u0434\u0430\u0432\u043d\u0435\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043d\u0430\u0448\u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u0438 \u043f\u043e\u043a\u0440\u044b\u0432\u0430\u043b \u043e\u0434\u0438\u043d \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0430 32 \u044f\u0434\u0440\u0430\u0445 \u0438 50 GB \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043a\u0438. \u0412 Airflow \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442:<\/p>\n<ul>\n<li>\u0431\u043e\u043b\u0435\u0435 <strong>200 \u0434\u0430\u0433\u043e\u0432<\/strong> (\u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e workflows, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u043d\u0430\u0431\u0438\u043b\u0438 \u0437\u0430\u0434\u0430\u0447\u043a\u0438),<\/li>\n<li>\u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u0432 \u0441\u0440\u0435\u0434\u043d\u0435\u043c \u043f\u043e <strong>70 \u0442\u0430\u0441\u043a\u043e\u0432<\/strong>,<\/li>\n<li>\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u044d\u0442\u043e \u0434\u043e\u0431\u0440\u043e (\u0442\u043e\u0436\u0435 \u0432 \u0441\u0440\u0435\u0434\u043d\u0435\u043c) <strong>\u0440\u0430\u0437 \u0432 \u0447\u0430\u0441<\/strong>.<\/li>\n<\/ul>\n<p>\u0410 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u043c\u044b \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u043b\u0438\u0441\u044c, \u044f \u043d\u0430\u043f\u0438\u0448\u0443 \u043d\u0438\u0436\u0435, \u0430 \u0441\u0435\u0439\u0447\u0430\u0441 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u00fcber-\u0437\u0430\u0434\u0430\u0447\u0443, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0440\u0435\u0448\u0430\u0442\u044c:<\/p>\n<blockquote><p>\u0415\u0441\u0442\u044c \u0442\u0440\u0438 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0445 SQL Server\u2019\u0430, \u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u043c \u043f\u043e 50 \u0431\u0430\u0437 \u0434\u0430\u043d\u043d\u044b\u0445 \u2014 \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u043e\u0432 \u043e\u0434\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0443 \u043d\u0438\u0445 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u0430\u044f (\u043f\u043e\u0447\u0442\u0438 \u0432\u0435\u0437\u0434\u0435, \u043c\u0443\u0430-\u0445\u0430-\u0445\u0430), \u0430 \u0437\u043d\u0430\u0447\u0438\u0442 \u0432 \u043a\u0430\u0436\u0434\u043e\u0439 \u0435\u0441\u0442\u044c \u0442\u0430\u0431\u043b\u0438\u0446\u0430 Orders (\u0431\u043b\u0430\u0433\u043e \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u0441 \u0442\u0430\u043a\u0438\u043c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0442\u043e\u043b\u043a\u0430\u0442\u044c \u0432 \u043b\u044e\u0431\u043e\u0439 \u0431\u0438\u0437\u043d\u0435\u0441). \u041c\u044b \u0437\u0430\u0431\u0438\u0440\u0430\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435, \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044f \u0441\u043b\u0443\u0436\u0435\u0431\u043d\u044b\u0435 \u043f\u043e\u043b\u044f (\u0441\u0435\u0440\u0432\u0435\u0440-\u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a, \u0431\u0430\u0437\u0430-\u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a, \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 ETL-\u0437\u0430\u0434\u0430\u0447\u0438) \u0438 \u043d\u0430\u0438\u0432\u043d\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0431\u0440\u043e\u0441\u0438\u043c \u0438\u0445 \u0432, \u0441\u043a\u0430\u0436\u0435\u043c, Vertica.<\/p><\/blockquote>\n<p>\u041f\u043e\u0435\u0445\u0430\u043b\u0438!<\/p>\n<h2 id=\"chast-osnovnaya-prakticheskaya-i-nemnogo-teoreticheskaya\">\u0427\u0430\u0441\u0442\u044c \u043e\u0441\u043d\u043e\u0432\u043d\u0430\u044f, \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f (\u0438 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0442\u0435\u043e\u0440\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f)<\/h2>\n<h3 id=\"zachem-ono-nam-i-vam\">\u0417\u0430\u0447\u0435\u043c \u043e\u043d\u043e \u043d\u0430\u043c (\u0438 \u0432\u0430\u043c)<\/h3>\n<p>\u041a\u043e\u0433\u0434\u0430 \u0434\u0435\u0440\u0435\u0432\u044c\u044f \u0431\u044b\u043b\u0438 \u0431\u043e\u043b\u044c\u0448\u0438\u043c\u0438, \u0430 \u044f \u0431\u044b\u043b \u043f\u0440\u043e\u0441\u0442\u044b\u043c <code>SQL<\/code>-\u0449\u0438\u043a\u043e\u043c \u0432 \u043e\u0434\u043d\u043e\u043c \u0440\u043e\u0441\u0441\u0438\u0439\u0441\u043a\u043e\u043c \u0440\u0438\u0442\u0435\u0439\u043b\u0435, \u043c\u044b \u0448\u043f\u0430\u0440\u0438\u043b\u0438 ETL-\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u044b aka \u043f\u043e\u0442\u043e\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0434\u0432\u0443\u0445 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u043d\u0430\u043c \u0441\u0440\u0435\u0434\u0441\u0442\u0432:<\/p>\n<ul>\n<li><strong>Informatica Power Center<\/strong> \u2014 \u043a\u0440\u0430\u0439\u043d\u0435 \u0440\u0430\u0437\u0432\u0435\u0441\u0438\u0441\u0442\u0430\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0430, \u0447\u0440\u0435\u0437\u0432\u044b\u0447\u0430\u0439\u043d\u043e \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f, \u0441\u043e \u0441\u0432\u043e\u0438\u043c\u0438 \u0436\u0435\u043b\u0435\u0437\u043a\u0430\u043c\u0438, \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u043c \u0432\u0435\u0440\u0441\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b \u044f \u0434\u0430\u0439 \u0431\u043e\u0433 1% \u0435\u0451 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439. \u041f\u043e\u0447\u0435\u043c\u0443? \u041d\u0443, \u0432\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u044d\u0442\u043e\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0433\u0434\u0435-\u0442\u043e \u0438\u0437 \u043d\u0443\u043b\u0435\u0432\u044b\u0445 \u043f\u0441\u0438\u0445\u0438\u0447\u0435\u0441\u043a\u0438 \u0434\u0430\u0432\u0438\u043b \u043d\u0430 \u043d\u0430\u0441. \u0412\u043e-\u0432\u0442\u043e\u0440\u044b\u0445, \u044d\u0442\u0430 \u0448\u0442\u0443\u043a\u043e\u0432\u0438\u043d\u0430 \u0437\u0430\u0442\u043e\u0447\u0435\u043d\u0430 \u043f\u043e\u0434 \u0447\u0440\u0435\u0437\u0432\u044b\u0447\u0430\u0439\u043d\u043e \u043d\u0430\u0432\u043e\u0440\u043e\u0447\u0435\u043d\u043d\u044b\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u044b, \u044f\u0440\u043e\u0441\u0442\u043d\u043e\u0435 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u043e\u0447\u0435\u043d\u044c-\u0432\u0430\u0436\u043d\u044b\u0435-\u044d\u043d\u0442\u0435\u0440\u043f\u0440\u0430\u0439\u0437-\u0444\u0438\u0448\u0435\u0447\u043a\u0438. \u041f\u0440\u043e \u0442\u043e \u0447\u0442\u043e \u0441\u0442\u043e\u0438\u0442 \u043e\u043d\u0430, \u043a\u0430\u043a \u043a\u0440\u044b\u043b\u043e Airbus A380\/\u0433\u043e\u0434, \u043c\u044b \u043f\u0440\u043e\u043c\u043e\u043b\u0447\u0438\u043c.\n<p><b class=\"spoiler_title\">\u041e\u0441\u0442\u043e\u0440\u043e\u0436\u043d\u043e, \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442 \u043c\u043e\u0436\u0435\u0442 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043b\u044e\u0434\u044f\u043c \u043c\u043b\u0430\u0434\u0448\u0435 30 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0431\u043e\u043b\u044c\u043d\u043e<\/b><\/p>\n<p><img decoding=\"async\" alt=\"Apache Airflow: \u0434\u0435\u043b\u0430\u0435\u043c ETL \u043f\u0440\u043e\u0449\u0435\" src=\"\/wp-content\/uploads\/2020\/07\/16c3b430338bce4c62c34d8b23bf5899.png\" style=\"display:block;margin: 0 auto;\"><\/li>\n<\/ul>\n<ul>\n<li><strong>SQL Server Integration Server<\/strong> \u2014 \u044d\u0442\u0438\u043c \u0442\u043e\u0432\u0430\u0440\u0438\u0449\u0435\u043c \u043c\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438\u0441\u044c \u0432 \u0441\u0432\u043e\u0438\u0445 \u0432\u043d\u0443\u0442\u0440\u0438\u043f\u0440\u043e\u0435\u043a\u0442\u043d\u044b\u0445 \u043f\u043e\u0442\u043e\u043a\u0430\u0445. \u041d\u0443 \u0430 \u0432 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435: SQL Server \u043c\u044b \u0443\u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c, \u0438 \u043d\u0435 \u044e\u0437\u0430\u0442\u044c \u0435\u0433\u043e ETL-\u0442\u0443\u043b\u0437\u044b \u0431\u044b\u043b\u043e \u0431\u044b \u043a\u0430\u043a-\u0442\u043e \u043d\u0435\u0440\u0430\u0437\u0443\u043c\u043d\u043e. \u0412\u0441\u0451 \u0432 \u043d\u0451\u043c \u0432 \u0445\u043e\u0440\u043e\u0448\u043e: \u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043a\u0440\u0430\u0441\u0438\u0432\u044b\u0439, \u0438 \u043e\u0442\u0447\u0451\u0442\u0438\u043a\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f\u2026 \u041d\u043e \u043d\u0435 \u0437\u0430 \u044d\u0442\u043e \u043c\u044b \u043b\u044e\u0431\u0438\u043c \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u044b\u0435 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u044b, \u043e\u0445 \u043d\u0435 \u0437\u0430 \u044d\u0442\u043e. \u0412\u0435\u0440\u0441\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e <code>dtsx<\/code> (\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 XML \u0441 \u043f\u0435\u0440\u0435\u043c\u0435\u0448\u0438\u0432\u0430\u044e\u0449\u0438\u043c\u0438\u0441\u044f \u043f\u0440\u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0438 \u043d\u043e\u0434\u0430\u043c\u0438) \u043c\u044b \u043c\u043e\u0436\u0435\u043c, \u0430 \u0442\u043e\u043b\u043a\u0443? \u0410 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0430\u043a\u0435\u0442 \u0442\u0430\u0441\u043a\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0435\u0440\u0435\u0442\u0430\u0449\u0438\u0442 \u0441\u043e\u0442\u043d\u044e \u0442\u0430\u0431\u043b\u0438\u0446 \u0441 \u043e\u0434\u043d\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043d\u0430 \u0434\u0440\u0443\u0433\u043e\u0439? \u0414\u0430 \u0447\u0442\u043e \u0441\u043e\u0442\u043d\u044e, \u0443 \u0432\u0430\u0441 \u043e\u0442 \u0434\u0432\u0430\u0434\u0446\u0430\u0442\u0438 \u0448\u0442\u0443\u043a \u043e\u0442\u0432\u0430\u043b\u0438\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u0430\u043b\u0435\u0446, \u0449\u0451\u043b\u043a\u0430\u044e\u0449\u0438\u0439 \u043f\u043e \u043c\u044b\u0448\u0438\u043d\u043e\u0439 \u043a\u043d\u043e\u043f\u043a\u0435. \u041d\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043e\u043d, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e, \u0431\u043e\u043b\u0435\u0435 \u043c\u043e\u0434\u043d\u043e:\n<p><img decoding=\"async\" alt=\"Apache Airflow: \u0434\u0435\u043b\u0430\u0435\u043c ETL \u043f\u0440\u043e\u0449\u0435\" src=\"\/wp-content\/uploads\/2020\/07\/8caa3aa9ab335f2f12bdd42716972980.png\" style=\"display:block;margin: 0 auto;\"><\/li>\n<\/ul>\n<p>\u041c\u044b \u0431\u0435\u0437\u0443\u0441\u043b\u043e\u0432\u043d\u043e \u0438\u0441\u043a\u0430\u043b\u0438 \u0432\u044b\u0445\u043e\u0434\u044b. \u0414\u0435\u043b\u043e \u0434\u0430\u0436\u0435 <em>\u043f\u043e\u0447\u0442\u0438<\/em> \u0434\u043e\u0448\u043b\u043e \u0434\u043e \u0441\u0430\u043c\u043e\u043f\u0438\u0441\u043d\u043e\u0433\u043e \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440\u0430 SSIS-\u043f\u0430\u043a\u0435\u0442\u043e\u0432&#8230;<\/p>\n<p>\u2026 \u0430 \u043f\u043e\u0442\u043e\u043c \u043c\u0435\u043d\u044f \u043d\u0430\u0448\u043b\u0430 \u043d\u043e\u0432\u0430\u044f \u0440\u0430\u0431\u043e\u0442\u0430. \u0410 \u043d\u0430 \u043d\u0435\u0439 \u043c\u0435\u043d\u044f \u043d\u0430\u0441\u0442\u0438\u0433 Apache Airflow.<\/p>\n<p>\u041a\u043e\u0433\u0434\u0430 \u044f \u0443\u0437\u043d\u0430\u043b, \u0447\u0442\u043e \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f ETL-\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0432 \u2014 \u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0439 Python-\u043a\u043e\u0434, \u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0442\u043e \u043d\u0435 \u043f\u043b\u044f\u0441\u0430\u043b \u043e\u0442 \u0440\u0430\u0434\u043e\u0441\u0442\u0438. \u0412\u043e\u0442 \u0442\u0430\u043a \u043f\u043e\u0442\u043e\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043e\u0434\u0432\u0435\u0440\u0433\u043b\u0438\u0441\u044c \u0432\u0435\u0440\u0441\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e \u0438 \u0434\u0438\u0444\u0444\u0443, \u0430 \u0441\u0441\u044b\u043f\u0430\u0442\u044c \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0441 \u0435\u0434\u0438\u043d\u043e\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043e\u0439 \u0438\u0437 \u0441\u043e\u0442\u043d\u0438 \u0431\u0430\u0437 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u043e\u0434\u0438\u043d \u0442\u0430\u0440\u0433\u0435\u0442 \u0441\u0442\u0430\u043b\u043e \u0434\u0435\u043b\u043e\u043c Python-\u043a\u043e\u0434\u0430 \u0432 \u043f\u043e\u043b\u0442\u043e\u0440\u0430-\u0434\u0432\u0430 13\u201d \u044d\u043a\u0440\u0430\u043d\u0430.<\/p>\n<h3 id=\"sobiraem-klaster\">\u0421\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u043a\u043b\u0430\u0441\u0442\u0435\u0440<\/h3>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043d\u0435 \u0443\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0441\u043e\u0432\u0441\u0435\u043c \u0443\u0436 \u0434\u0435\u0442\u0441\u043a\u0438\u0439 \u0441\u0430\u0434, \u0438 \u043d\u0435 \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c \u0442\u0443\u0442 \u043e \u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u043e \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b\u0445 \u0432\u0435\u0449\u0430\u0445, \u0432\u0440\u043e\u0434\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 Airflow, \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0439 \u0432\u0430\u043c\u0438 \u0411\u0414, Celery \u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u0434\u0435\u043b, \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0445 \u0432 \u0434\u043e\u043a\u0430\u0445.<\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u043c\u044b \u043c\u043e\u0433\u043b\u0438 \u0441\u0440\u0430\u0437\u0443 \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u0442\u044c \u043a \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0430\u043c, \u044f \u043d\u0430\u0431\u0440\u043e\u0441\u0430\u043b <code>docker-compose.yml<\/code> \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c:<\/p>\n<ul>\n<li>\u041f\u043e\u0434\u043d\u0438\u043c\u0435\u043c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e <strong>Airflow<\/strong>: Scheduler, Webserver. \u0422\u0430\u043c \u0436\u0435 \u0431\u0443\u0434\u0435\u0442 \u043a\u0440\u0443\u0442\u0438\u0442\u0441\u044f Flower \u0434\u043b\u044f \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433\u0430 Celery-\u0437\u0430\u0434\u0430\u0447 (\u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0435\u0433\u043e \u0443\u0436\u0435 \u0437\u0430\u0442\u043e\u043b\u043a\u0430\u043b\u0438 \u0432 <code>apache\/airflow:1.10.10-python3.7<\/code>, \u0430 \u043c\u044b \u0438 \u043d\u0435 \u043f\u0440\u043e\u0442\u0438\u0432);<\/li>\n<li><strong>PostgreSQL<\/strong>, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 Airflow \u0431\u0443\u0434\u0435\u0442 \u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0432\u043e\u044e \u0441\u043b\u0443\u0436\u0435\u0431\u043d\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e (\u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u0430, \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0438 \u0442. \u0434.), \u0430 Celery \u2014 \u043e\u0442\u043c\u0435\u0447\u0430\u0442\u044c \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u044b\u0435 \u0442\u0430\u0441\u043a\u0438;<\/li>\n<li><strong>Redis<\/strong>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0441\u0442\u0443\u043f\u0430\u0442\u044c \u0431\u0440\u043e\u043a\u0435\u0440\u043e\u043c \u0437\u0430\u0434\u0430\u0447 \u0434\u043b\u044f Celery;<\/li>\n<li><strong>Celery worker<\/strong>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438 \u0437\u0430\u0439\u043c\u0435\u0442\u0441\u044f \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435\u043c \u0437\u0430\u0434\u0430\u0447\u0435\u043a.<\/li>\n<li>\u0412 \u043f\u0430\u043f\u043a\u0443 <code>.\/dags<\/code> \u043c\u044b \u0431\u0443\u0434\u0435\u0442 \u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c \u043d\u0430\u0448\u0438 \u0444\u0430\u0439\u043b\u044b \u0441 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c \u0434\u0430\u0433\u043e\u0432. \u041e\u043d\u0438 \u0431\u0443\u0434\u0443\u0442 \u043f\u043e\u0434\u0445\u0432\u0430\u0442\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u043b\u0435\u0442\u0443, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0435\u0440\u0435\u0434\u0451\u0440\u0433\u0438\u0432\u0430\u0442\u044c \u0432\u0435\u0441\u044c \u0441\u0442\u0435\u043a \u043f\u043e\u0441\u043b\u0435 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0447\u0438\u0445\u0430 \u043d\u0435 \u043d\u0443\u0436\u043d\u043e.<\/li>\n<\/ul>\n<blockquote><p>\u041a\u043e\u0435-\u0433\u0434\u0435 \u043a\u043e\u0434 \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d \u043d\u0435 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e (\u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0437\u0430\u0433\u0440\u043e\u043c\u043e\u0436\u0434\u0430\u0442\u044c \u0442\u0435\u043a\u0441\u0442), \u0430 \u0433\u0434\u0435-\u0442\u043e \u043e\u043d \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435. \u0426\u0435\u043b\u044c\u043d\u044b\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u043a\u043e\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dm-logv\/airflow-tutorial\">https:\/\/github.com\/dm-logv\/airflow-tutorial<\/a><\/noindex>.<\/p><\/blockquote>\n<p><b class=\"spoiler_title\">docker-compose.yml<\/b><\/p>\n<pre><code class=\"plaintext\">version: '3.4'\n\nx-airflow-config: &amp;airflow-config\n  AIRFLOW__CORE__DAGS_FOLDER: \/dags\n  AIRFLOW__CORE__EXECUTOR: CeleryExecutor\n  AIRFLOW__CORE__FERNET_KEY: MJNz36Q8222VOQhBOmBROFrmeSxNOgTCMaVp2_HOtE0=\n  AIRFLOW__CORE__HOSTNAME_CALLABLE: airflow.utils.net:get_host_ip_address\n  AIRFLOW__CORE__SQL_ALCHEMY_CONN: postgres+psycopg2:\/\/airflow:airflow@airflow-db:5432\/airflow\n\n  AIRFLOW__CORE__PARALLELISM: 128\n  AIRFLOW__CORE__DAG_CONCURRENCY: 16\n  AIRFLOW__CORE__MAX_ACTIVE_RUNS_PER_DAG: 4\n  AIRFLOW__CORE__LOAD_EXAMPLES: 'False'\n  AIRFLOW__CORE__LOAD_DEFAULT_CONNECTIONS: 'False'\n\n  AIRFLOW__EMAIL__DEFAULT_EMAIL_ON_RETRY: 'False'\n  AIRFLOW__EMAIL__DEFAULT_EMAIL_ON_FAILURE: 'False'\n\n  AIRFLOW__CELERY__BROKER_URL: redis:\/\/broker:6379\/0\n  AIRFLOW__CELERY__RESULT_BACKEND: db+postgresql:\/\/airflow:airflow@airflow-db\/airflow\n\nx-airflow-base: &amp;airflow-base\n  image: apache\/airflow:1.10.10-python3.7\n  entrypoint: \/bin\/bash\n  restart: always\n  volumes:\n    - .\/dags:\/dags\n    - .\/requirements.txt:\/requirements.txt\n\nservices:\n  # Redis as a Celery broker\n  broker:\n    image: redis:6.0.5-alpine\n\n  # DB for the Airflow metadata\n  airflow-db:\n    image: postgres:10.13-alpine\n\n    environment:\n      - POSTGRES_USER=airflow\n      - POSTGRES_PASSWORD=airflow\n      - POSTGRES_DB=airflow\n\n    volumes:\n      - .\/db:\/var\/lib\/postgresql\/data\n\n  # Main container with Airflow Webserver, Scheduler, Celery Flower\n  airflow:\n    &lt;&lt;: *airflow-base\n\n    environment:\n      &lt;&lt;: *airflow-config\n\n      AIRFLOW__SCHEDULER__DAG_DIR_LIST_INTERVAL: 30\n      AIRFLOW__SCHEDULER__CATCHUP_BY_DEFAULT: 'False'\n      AIRFLOW__SCHEDULER__MAX_THREADS: 8\n\n      AIRFLOW__WEBSERVER__LOG_FETCH_TIMEOUT_SEC: 10\n\n    depends_on:\n      - airflow-db\n      - broker\n\n    command: &gt;\n      -c \" sleep 10 &amp;&amp;\n           pip install --user -r \/requirements.txt &amp;&amp;\n           \/entrypoint initdb &amp;&amp;\n          (\/entrypoint webserver &amp;) &amp;&amp;\n          (\/entrypoint flower &amp;) &amp;&amp;\n           \/entrypoint scheduler\"\n\n    ports:\n      # Celery Flower\n      - 5555:5555\n      # Airflow Webserver\n      - 8080:8080\n\n  # Celery worker, will be scaled using `--scale=n`\n  worker:\n    &lt;&lt;: *airflow-base\n\n    environment:\n      &lt;&lt;: *airflow-config\n\n    command: &gt;\n      -c \" sleep 10 &amp;&amp;\n           pip install --user -r \/requirements.txt &amp;&amp;\n           \/entrypoint worker\"\n\n    depends_on:\n      - airflow\n      - airflow-db\n      - broker<\/code><\/pre>\n<p>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u044f:<\/p>\n<ul>\n<li>\u0412 \u0441\u0431\u043e\u0440\u043a\u0435 \u043a\u043e\u043c\u043f\u043e\u0437\u0430 \u044f \u0432\u043e \u043c\u043d\u043e\u0433\u043e\u043c \u043e\u043f\u0438\u0440\u0430\u043b\u0441\u044f \u043d\u0430 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0439 \u043e\u0431\u0440\u0430\u0437 <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/puckel\/docker-airflow\">puckel\/docker-airflow<\/a><\/noindex> \u2013 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435. \u041c\u043e\u0436\u0435\u0442, \u0432\u0430\u043c \u0432 \u0436\u0438\u0437\u043d\u0438 \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0438\u0447\u0435\u0433\u043e \u0438 \u043d\u0435 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f.<\/li>\n<li>\u0412\u0441\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 Airflow \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0435\u0440\u0435\u0437 <code>airflow.cfg<\/code>, \u043d\u043e \u0438 \u0447\u0435\u0440\u0435\u0437 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0441\u0440\u0435\u0434\u044b (\u0441\u043b\u0430\u0432\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u043c), \u0447\u0435\u043c \u044f \u0437\u043b\u043e\u0441\u0442\u043d\u043e \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0441\u044f.<\/li>\n<li>\u0415\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043e\u043d \u043d\u0435 production-ready: \u044f \u043d\u0430\u043c\u0435\u0440\u0435\u043d\u043d\u043e \u043d\u0435 \u0441\u0442\u0430\u0432\u0438\u043b heartbeats \u043d\u0430 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u044b, \u043d\u0435 \u0437\u0430\u043c\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u043b\u0441\u044f \u0441 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c\u044e. \u041d\u043e \u043c\u0438\u043d\u0438\u043c\u0443\u043c, \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u0439 \u0434\u043b\u044f \u043d\u0430\u0448\u0438\u0445 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0438\u043a\u043e\u0432 \u044f \u0441\u0434\u0435\u043b\u0430\u043b.<\/li>\n<li>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e:\n<ul>\n<li>\u041f\u0430\u043f\u043a\u0430 \u0441 \u0434\u0430\u0433\u0430\u043c\u0438 \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u043a\u0430\u043a \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u0443, \u0442\u0430\u043a \u0438 \u0432\u043e\u0440\u043a\u0435\u0440\u0430\u043c.<\/li>\n<li>\u0422\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435 \u043a\u0430\u0441\u0430\u0435\u0442\u0441\u044f \u0438 \u0432\u0441\u0435\u0445 \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u0445 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a \u2014 \u043e\u043d\u0438 \u0432\u0441\u0435 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u044b \u043d\u0430 \u043c\u0430\u0448\u0438\u043d\u044b \u0441 \u0448\u0435\u0434\u0443\u043b\u0435\u0440\u043e\u043c \u0438 \u0432\u043e\u0440\u043a\u0435\u0440\u0430\u043c\u0438.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>\u041d\u0443 \u0430 \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u043e\u0441\u0442\u043e:<\/p>\n<pre><code class=\"plaintext\">$ docker-compose up --scale worker=3<\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u0432\u0441\u0451 \u043f\u043e\u0434\u043d\u0438\u043c\u0435\u0442\u0441\u044f, \u043c\u043e\u0436\u043d\u043e \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043d\u0430 \u0432\u0435\u0431-\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b:<\/p>\n<ul>\n<li>Airflow: <noindex><a rel=\"nofollow\" href=\"http:\/\/127.0.0.1:8080\/admin\/\">http:\/\/127.0.0.1:8080\/admin\/<\/a><\/noindex><\/li>\n<li>Flower: <noindex><a rel=\"nofollow\" href=\"http:\/\/127.0.0.1:5555\/dashboard\">http:\/\/127.0.0.1:5555\/dashboard<\/a><\/noindex><\/li>\n<\/ul>\n<h3 id=\"osnovnye-ponyatiya\">\u041e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043f\u043e\u043d\u044f\u0442\u0438\u044f<\/h3>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043f\u043e\u043d\u044f\u043b\u0438 \u0432\u043e \u0432\u0441\u0435\u0445 \u044d\u0442\u0438\u0445 \u00ab\u0434\u0430\u0433\u0430\u0445\u00bb, \u0442\u043e \u0432\u043e\u0442 \u043a\u0440\u0430\u0442\u043a\u0438\u0439 \u0441\u043b\u043e\u0432\u0430\u0440\u0438\u043a:<\/p>\n<ul>\n<li><strong>Scheduler<\/strong> \u2014 \u0441\u0430\u043c\u044b\u0439 \u0433\u043b\u0430\u0432\u043d\u044b\u0439 \u0434\u044f\u0434\u044c\u043a\u0430 \u0432 Airflow, \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u0443\u044e\u0449\u0438\u0439, \u0447\u0442\u043e\u0431\u044b \u0432\u043a\u0430\u043b\u044b\u0432\u0430\u043b\u0438 \u0440\u043e\u0431\u043e\u0442\u044b, \u0430 \u043d\u0435 \u0447\u0435\u043b\u043e\u0432\u0435\u043a: \u0441\u043b\u0435\u0434\u0438\u0442 \u0437\u0430 \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u0438\u0435\u043c, \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442 \u0434\u0430\u0433\u0438, \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0442\u0430\u0441\u043a\u0438.\n<p>\u0412\u043e\u043e\u0431\u0449\u0435, \u0432 \u0441\u0442\u0430\u0440\u044b\u0445 \u0432\u0435\u0440\u0441\u0438\u044f\u0445, \u0443 \u043d\u0435\u0433\u043e \u0431\u044b\u043b\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0441 \u043f\u0430\u043c\u044f\u0442\u044c\u044e (\u043d\u0435\u0442, \u043d\u0435 \u0430\u043c\u043d\u0435\u0437\u0438\u044f, \u0430 \u0443\u0442\u0435\u0447\u043a\u0438) \u0438 \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0430\u0445 \u0434\u0430\u0436\u0435 \u043e\u0441\u0442\u0430\u043b\u0441\u044f \u043b\u0435\u0433\u0430\u0441\u0438-\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 <code>run_duration<\/code> \u2014 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b \u0435\u0433\u043e \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430. \u041d\u043e \u0441\u0435\u0439\u0447\u0430\u0441 \u0432\u0441\u0451 \u0445\u043e\u0440\u043e\u0448\u043e.<\/li>\n<li><strong>DAG<\/strong> (\u043e\u043d \u0436\u0435 \u00ab\u0434\u0430\u0433\u00bb) \u2014 \u00ab\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u0430\u0446\u0438\u043a\u043b\u0438\u0447\u043d\u044b\u0439 \u0433\u0440\u0430\u0444\u00bb, \u043d\u043e \u0442\u0430\u043a\u043e\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043c\u0430\u043b\u043e \u043a\u043e\u043c\u0443 \u0447\u0442\u043e \u0441\u043a\u0430\u0436\u0435\u0442, \u0430 \u043f\u043e \u0441\u0443\u0442\u0438 \u044d\u0442\u043e \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u0434\u043b\u044f \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u0434\u0440\u0443\u0433 \u0441 \u0434\u0440\u0443\u0433\u043e\u043c \u0442\u0430\u0441\u043a\u043e\u0432 (\u0441\u043c. \u043d\u0438\u0436\u0435) \u0438\u043b\u0438 \u0430\u043d\u0430\u043b\u043e\u0433 Package \u0432 SSIS \u0438 Workflow \u0432 Informatica.\n<p>\u041f\u043e\u043c\u0438\u043c\u043e \u0434\u0430\u0433\u043e\u0432 \u0435\u0449\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0441\u0430\u0431\u0434\u0430\u0433\u0438, \u043d\u043e \u043c\u044b \u0434\u043e \u043d\u0438\u0445 \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e \u043d\u0435 \u0434\u043e\u0431\u0435\u0440\u0451\u043c\u0441\u044f.<\/li>\n<li><strong>DAG Run<\/strong> \u2014 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0434\u0430\u0433, \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043f\u0440\u0438\u0441\u0432\u043e\u0435\u043d \u0441\u0432\u043e\u0439 <code>execution_date<\/code>. \u0414\u0430\u0433\u0440\u0430\u043d\u044b \u043e\u0434\u043d\u043e\u0433\u043e \u0434\u0430\u0433\u0430 \u043c\u043e\u0433\u0443\u0442 \u0432\u043f\u043e\u043b\u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e (\u0435\u0441\u043b\u0438 \u0432\u044b, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u0441\u0434\u0435\u043b\u0430\u043b\u0438 \u0441\u0432\u043e\u0438 \u0442\u0430\u0441\u043a\u0438 \u0438\u0434\u0435\u043c\u043f\u043e\u0442\u0435\u043d\u0442\u043d\u044b\u043c\u0438).<\/li>\n<li><strong>Operator<\/strong> \u2014 \u044d\u0442\u043e \u043a\u0443\u0441\u043e\u0447\u043a\u0438 \u043a\u043e\u0434\u0430, \u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u0437\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043a\u0430\u043a\u043e\u0433\u043e-\u043b\u0438\u0431\u043e \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f. \u0415\u0441\u0442\u044c \u0442\u0440\u0438 \u0442\u0438\u043f\u0430 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432:\n<ul>\n<li><strong>action<\/strong>, \u043a\u0430\u043a \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u043d\u0430\u0448 \u043b\u044e\u0431\u0438\u043c\u044b\u0439 <code>PythonOperator<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432 \u0441\u0438\u043b\u0430\u0445 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043b\u044e\u0431\u043e\u0439 (\u0432\u0430\u043b\u0438\u0434\u043d\u044b\u0439) Python-\u043a\u043e\u0434;<\/li>\n<li><strong>transfer<\/strong>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0435\u0440\u0435\u0432\u043e\u0437\u044f\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0441 \u043c\u0435\u0441\u0442\u0430 \u043d\u0430 \u043c\u0435\u0441\u0442\u043e, \u0441\u043a\u0430\u0436\u0435\u043c, <code>MsSqlToHiveTransfer<\/code>;<\/li>\n<li><strong>sensor<\/strong> \u0436\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0440\u0435\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u043b\u0438 \u043f\u0440\u0438\u0442\u043e\u0440\u043c\u043e\u0437\u0438\u0442\u044c \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0434\u0430\u0433\u0430 \u0434\u043e \u043d\u0430\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u044f \u043a\u0430\u043a\u043e\u0433\u043e-\u043b\u0438\u0431\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u044f. <code>HttpSensor<\/code> \u043c\u043e\u0436\u0435\u0442 \u0434\u0435\u0440\u0433\u0430\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0439 \u044d\u043d\u0434\u043f\u043e\u0439\u043d\u0442, \u0438 \u043a\u043e\u0433\u0434\u0430 \u0434\u043e\u0436\u0434\u0435\u0442\u0441\u044f \u043d\u0443\u0436\u043d\u044b\u0439 \u043e\u0442\u0432\u0435\u0442, \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0442\u0440\u0430\u043d\u0441\u0444\u0435\u0440 <code>GoogleCloudStorageToS3Operator<\/code>. \u041f\u044b\u0442\u043b\u0438\u0432\u044b\u0439 \u0443\u043c \u0441\u043f\u0440\u043e\u0441\u0438\u0442: \u00ab\u0437\u0430\u0447\u0435\u043c? \u0412\u0435\u0434\u044c \u043c\u043e\u0436\u043d\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u043f\u043e\u0432\u0442\u043e\u0440\u044b \u043f\u0440\u044f\u043c\u043e \u0432 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0435!\u00bb \u0410 \u0437\u0430\u0442\u0435\u043c, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0437\u0430\u0431\u0438\u0432\u0430\u0442\u044c \u043f\u0443\u043b \u0442\u0430\u0441\u043a\u043e\u0432 \u043f\u043e\u0434\u0432\u0438\u0441\u0448\u0438\u043c\u0438 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430\u043c\u0438. \u0421\u0435\u043d\u0441\u043e\u0440 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f, \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0438 \u0443\u043c\u0438\u0440\u0430\u0435\u0442 \u0434\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u043f\u043e\u043f\u044b\u0442\u043a\u0438.<\/li>\n<\/ul>\n<\/li>\n<li><strong>Task<\/strong> \u2014 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u043d\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b \u0432\u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0442\u0438\u043f\u0430 \u0438 \u043f\u0440\u0438\u043a\u0440\u0435\u043f\u043b\u0435\u043d\u043d\u044b\u0435 \u043a \u0434\u0430\u0433\u0443 \u043f\u043e\u0432\u044b\u0448\u0430\u044e\u0442\u0441\u044f \u0434\u043e \u0447\u0438\u043d\u0430 \u0442\u0430\u0441\u043a\u0430.<\/li>\n<li><strong>Task instance<\/strong> \u2014 \u043a\u043e\u0433\u0434\u0430 \u0433\u0435\u043d\u0435\u0440\u0430\u043b-\u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0449\u0438\u043a \u0440\u0435\u0448\u0438\u043b, \u0447\u0442\u043e \u0442\u0430\u0441\u043a\u0438 \u043f\u043e\u0440\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0432 \u0431\u043e\u0439 \u043d\u0430 \u0438\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u0438-\u0432\u043e\u0440\u043a\u0435\u0440\u044b (\u043f\u0440\u044f\u043c\u043e \u043d\u0430 \u043c\u0435\u0441\u0442\u0435, \u0435\u0441\u043b\u0438 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <code>LocalExecutor<\/code> \u0438\u043b\u0438 \u043d\u0430 \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u0443\u044e \u043d\u043e\u0434\u0443 \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0441 <code>CeleryExecutor<\/code>), \u043e\u043d \u043d\u0430\u0437\u043d\u0430\u0447\u0430\u0435\u0442 \u0438\u043c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 (\u0442. \u0435. \u043a\u043e\u043c\u043f\u043b\u0435\u043a\u0442 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u2014 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f), \u0440\u0430\u0437\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u0442 \u0448\u0430\u0431\u043b\u043e\u043d\u044b \u043a\u043e\u043c\u0430\u043d\u0434 \u0438\u043b\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0438 \u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u0442 \u0438\u0445 \u0432 \u043f\u0443\u043b.<\/li>\n<\/ul>\n<h3 id=\"generiruem-taski\">\u0413\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u0442\u0430\u0441\u043a\u0438<\/h3>\n<p>\u0421\u043f\u0435\u0440\u0432\u0430 \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0438\u043c \u043e\u0431\u0449\u0443\u044e \u0441\u0445\u0435\u043c\u0443 \u043d\u0430\u0448\u0435\u0433\u043e \u0434\u0430\u0433\u0430, \u0430 \u0437\u0430\u0442\u0435\u043c \u0431\u0443\u0434\u0435\u043c \u0432\u0441\u0451 \u0431\u043e\u043b\u044c\u0448\u0435 \u0438 \u0431\u043e\u043b\u044c\u0448\u0435 \u043f\u043e\u0433\u0440\u0443\u0436\u0430\u0442\u044c\u0441\u044f \u0432 \u0434\u0435\u0442\u0430\u043b\u0438, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043c\u044b \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u043c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435\u0442\u0440\u0438\u0432\u0438\u0430\u043b\u044c\u043d\u044b\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f.<\/p>\n<p>\u0418\u0442\u0430\u043a, \u0432 \u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0435\u043c \u0432\u0438\u0434\u0435 \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0439 \u0434\u0430\u0433 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a:<\/p>\n<pre><code class=\"python\">from datetime import timedelta, datetime\n\nfrom airflow import DAG\nfrom airflow.operators.python_operator import PythonOperator\n\nfrom commons.datasources import sql_server_ds\n\ndag = DAG('orders',\n          schedule_interval=timedelta(hours=6),\n          start_date=datetime(2020, 7, 8, 0))\n\ndef workflow(**context):\n    print(context)\n\nfor conn_id, schema in sql_server_ds:\n    PythonOperator(\n        task_id=schema,\n        python_callable=workflow,\n        provide_context=True,\n        dag=dag)<\/code><\/pre>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f:<\/p>\n<ul>\n<li>\u0421\u043f\u0435\u0440\u0432\u0430 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u043d\u0443\u0436\u043d\u044b\u0435 \u043b\u0438\u0431\u044b \u0438 <em>\u043a\u043e\u0435 \u0447\u0442\u043e \u0435\u0449\u0451<\/em>;<\/li>\n<li><code>sql_server_ds<\/code> \u2014 \u044d\u0442\u043e <code>List[namedtuple[str, str]]<\/code> \u0441 \u0438\u043c\u0435\u043d\u0430\u043c\u0438 \u043a\u043e\u043d\u043d\u0435\u043a\u0442\u043e\u0432 \u0438\u0437 Airflow Connections \u0438 \u0431\u0430\u0437\u0430\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0437\u0430\u0431\u0438\u0440\u0430\u0442\u044c \u043d\u0430\u0448\u0443 \u0442\u0430\u0431\u043b\u0438\u0447\u043a\u0443;<\/li>\n<li><code>dag<\/code> \u2014 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0435 \u043d\u0430\u0448\u0435\u0433\u043e \u0434\u0430\u0433\u0430, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043e\u043b\u0436\u043d\u043e \u043b\u0435\u0436\u0430\u0442\u044c \u0432 <code>globals()<\/code>, \u0438\u043d\u0430\u0447\u0435 Airflow \u0435\u0433\u043e \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u0442. \u0414\u0430\u0433\u0443 \u0442\u0430\u043a\u0436\u0435 \u043d\u0443\u0436\u043d\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c:\n<ul>\n<li>\u0447\u0442\u043e \u0435\u0433\u043e \u0437\u043e\u0432\u0443\u0442 <code>orders<\/code> \u2014 \u044d\u0442\u043e \u0438\u043c\u044f \u043f\u043e\u0442\u043e\u043c \u0431\u0443\u0434\u0435\u0442 \u043c\u0430\u044f\u0447\u0438\u0442\u044c \u0432 \u0432\u0435\u0431-\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435,<\/li>\n<li>\u0447\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043e\u043d \u0431\u0443\u0434\u0435\u0442, \u043d\u0430\u0447\u0438\u043d\u0430\u044f \u0441 \u043f\u043e\u043b\u0443\u043d\u043e\u0447\u0438 \u0432\u043e\u0441\u044c\u043c\u043e\u0433\u043e \u0438\u044e\u043b\u044f,<\/li>\n<li>\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043e\u043d \u0434\u043e\u043b\u0436\u0435\u043d, \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u043a\u0430\u0436\u0434\u044b\u0435 6 \u0447\u0430\u0441\u043e\u0432 (\u0434\u043b\u044f \u043a\u0440\u0443\u0442\u044b\u0445 \u043f\u0430\u0440\u043d\u0435\u0439 \u0437\u0434\u0435\u0441\u044c \u0432\u043c\u0435\u0441\u0442\u043e <code>timedelta()<\/code> \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u0430 <code>cron<\/code>-\u0441\u0442\u0440\u043e\u043a\u0430 <code>0 0 0\/6 ? * * *<\/code>, \u0434\u043b\u044f \u043c\u0435\u043d\u0435\u0435 \u043a\u0440\u0443\u0442\u044b\u0445 \u2014 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0432\u0440\u043e\u0434\u0435 <code>@daily<\/code>);<\/li>\n<\/ul>\n<\/li>\n<li><code>workflow()<\/code> \u0431\u0443\u0434\u0435\u0442 \u0434\u0435\u043b\u0430\u0442\u044c \u043e\u0441\u043d\u043e\u0432\u043d\u0443\u044e \u0440\u0430\u0431\u043e\u0442\u0443, \u043d\u043e \u043d\u0435 \u0441\u0435\u0439\u0447\u0430\u0441. \u0421\u0435\u0439\u0447\u0430\u0441 \u043c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u044b\u0441\u044b\u043f\u0435\u043c \u043d\u0430\u0448 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0432 \u043b\u043e\u0433.<\/li>\n<li>\u0410 \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u043e\u0441\u0442\u0430\u044f \u043c\u0430\u0433\u0438\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0442\u0430\u0441\u043a\u043e\u0432:\n<ul>\n<li>\u043f\u0440\u043e\u0431\u0435\u0433\u0430\u0435\u043c \u043f\u043e \u043d\u0430\u0448\u0438\u043c \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430\u043c;<\/li>\n<li>\u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c <code>PythonOperator<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043d\u0430\u0448\u0443 \u043f\u0443\u0441\u0442\u044b\u0448\u043a\u0443 <code>workflow()<\/code>. \u041d\u0435 \u0437\u0430\u0431\u044b\u0432\u0430\u0439\u0442\u0435 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0435 (\u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u0434\u0430\u0433\u0430) \u0438\u043c\u044f \u0442\u0430\u0441\u043a\u0430 \u0438 \u043f\u043e\u0434\u0432\u044f\u0437\u044b\u0432\u0430\u0442\u044c \u0441\u0430\u043c \u0434\u0430\u0433. \u0424\u043b\u0430\u0433 <code>provide_context<\/code> \u0432 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u043d\u0430\u0441\u044b\u043f\u0435\u0442 \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u0431\u0435\u0440\u0435\u0436\u043d\u043e \u0441\u043e\u0431\u0435\u0440\u0451\u043c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>**context<\/code>.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>\u041f\u043e\u043a\u0430 \u043d\u0430 \u044d\u0442\u043e\u043c \u0432\u0441\u0451. \u0427\u0442\u043e \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438:<\/p>\n<ul>\n<li>\u043d\u043e\u0432\u044b\u0439 \u0434\u0430\u0433 \u0432 \u0432\u0435\u0431-\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435,<\/li>\n<li>\u043f\u043e\u043b\u0442\u043e\u0440\u044b \u0441\u043e\u0442\u043d\u0438 \u0442\u0430\u0441\u043a\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e (\u0435\u0441\u043b\u0438 \u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 Airflow, Celery \u0438 \u043c\u043e\u0449\u043d\u043e\u0441\u0442\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u0432).<\/li>\n<\/ul>\n<p>\u041d\u0443, \u043f\u043e\u0447\u0442\u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438.<\/p>\n<p><img decoding=\"async\" alt=\"Apache Airflow: \u0434\u0435\u043b\u0430\u0435\u043c ETL \u043f\u0440\u043e\u0449\u0435\" src=\"\/wp-content\/uploads\/2020\/07\/e71eff3f3d94f168fb55bdba29123874.png\" style=\"display:block;margin: 0 auto;\"><br \/>\n<em>\u0417\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043a\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0441\u0442\u0430\u0432\u0438\u0442\u044c?<\/em><\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u0432\u0441\u0451 \u044d\u0442\u043e \u0434\u0435\u043b\u043e \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u0442\u044c \u044f \u0432\u043a\u043e\u0440\u044f\u0447\u0438\u043b \u0432 <code>docker-compose.yml<\/code> \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 <code>requirements.txt<\/code> \u043d\u0430 \u0432\u0441\u0435\u0445 \u043d\u043e\u0434\u0430\u0445.<\/p>\n<p>\u0412\u043e\u0442 \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u043d\u0435\u0441\u043b\u0430\u0441\u044c:<\/p>\n<p><img decoding=\"async\" alt=\"Apache Airflow: \u0434\u0435\u043b\u0430\u0435\u043c ETL \u043f\u0440\u043e\u0449\u0435\" src=\"\/wp-content\/uploads\/2020\/07\/670932075aafd91f9c00a909b138a71e.png\" style=\"display:block;margin: 0 auto;\"><\/p>\n<p><em>\u0421\u0435\u0440\u044b\u0435 \u043a\u0432\u0430\u0434\u0440\u0430\u0442\u0438\u043a\u0438 \u2014 task instances, \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u044b\u0435 \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u043e\u043c.<\/em><\/p>\n<p>\u041d\u0435\u043c\u043d\u043e\u0433\u043e \u0436\u0434\u0435\u043c, \u0437\u0430\u0434\u0430\u0447\u0438 \u0440\u0430\u0441\u0445\u0432\u0430\u0442\u044b\u0432\u0430\u044e\u0442 \u0432\u043e\u0440\u043a\u0435\u0440\u044b:<\/p>\n<p><img decoding=\"async\" alt=\"Apache Airflow: \u0434\u0435\u043b\u0430\u0435\u043c ETL \u043f\u0440\u043e\u0449\u0435\" src=\"\/wp-content\/uploads\/2020\/07\/2579f3cfd087cbbc42aea2a58dfd17b5.png\" style=\"display:block;margin: 0 auto;\"><\/p>\n<p><em>\u0417\u0435\u043b\u0435\u043d\u044b\u0435, \u043f\u043e\u043d\u044f\u0442\u043d\u043e\u0435 \u0434\u0435\u043b\u043e, \u2014 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u043e\u0442\u0440\u0430\u0431\u043e\u0442\u0430\u0432\u0448\u0438\u0435. \u041a\u0440\u0430\u0441\u043d\u044b\u0435 \u2014 \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0443\u0441\u043f\u0435\u0448\u043d\u043e.<\/em><\/p>\n<blockquote><p>\u041a\u0441\u0442\u0430\u0442\u0438, \u043d\u0430 \u043d\u0430\u0448\u0435\u043c \u043f\u0440\u043e\u0434\u0435 \u043d\u0438\u043a\u0430\u043a\u043e\u0439 \u043f\u0430\u043f\u043a\u0438 <code>.\/dags<\/code>, \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0438\u0440\u0443\u044e\u0449\u0435\u0439\u0441\u044f \u043c\u0435\u0436\u0434\u0443 \u043c\u0430\u0448\u0438\u043d\u0430\u043c\u0438 \u043d\u0435\u0442 \u2014 \u0432\u0441\u0451 \u0434\u0430\u0433\u0438 \u043b\u0435\u0436\u0430\u0442 \u0432 <code>git<\/code> \u043d\u0430 \u043d\u0430\u0448\u0435\u043c Gitlab, \u0430 Gitlab CI \u0440\u0430\u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u0442 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043d\u0430 \u043c\u0430\u0448\u0438\u043d\u044b \u043f\u0440\u0438 \u043c\u0451\u0440\u0434\u0436\u0435 \u0432 <code>master<\/code>.<\/p><\/blockquote>\n<h3 id=\"nemnogo-o-flower\">\u041d\u0435\u043c\u043d\u043e\u0433\u043e \u043e Flower<\/h3>\n<p>\u041f\u043e\u043a\u0430 \u0432\u043e\u0440\u043a\u0435\u0440\u044b \u043c\u043e\u043b\u043e\u0442\u044f\u0442 \u043d\u0430\u0448\u0438 \u0442\u0430\u0441\u043e\u0447\u043a\u0438-\u043f\u0443\u0441\u0442\u044b\u0448\u043a\u0438, \u0432\u0441\u043f\u043e\u043c\u043d\u0438\u043c \u043f\u0440\u043e \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u0435\u0442 \u043d\u0430\u043c \u043a\u043e\u0435-\u0447\u0442\u043e \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u2014 Flower.<\/p>\n<p>\u0421\u0430\u043c\u0430\u044f \u043f\u0435\u0440\u0432\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0447\u043a\u0430 \u0441 \u0441\u0443\u043c\u043c\u0430\u0440\u043d\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439 \u043f\u043e \u043d\u043e\u0434\u0430\u043c-\u0432\u043e\u0440\u043a\u0435\u0440\u0430\u043c:<\/p>\n<p><img decoding=\"async\" alt=\"Apache Airflow: \u0434\u0435\u043b\u0430\u0435\u043c ETL \u043f\u0440\u043e\u0449\u0435\" src=\"\/wp-content\/uploads\/2020\/07\/73fc08d7c3f0e6a0e76ea1e63bc0a095.png\" style=\"display:block;margin: 0 auto;\"><\/p>\n<p>\u0421\u0430\u043c\u0430\u044f \u043d\u0430\u0441\u044b\u0449\u0435\u043d\u043d\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0447\u043a\u0430 \u0441 \u0437\u0430\u0434\u0430\u0447\u0430\u043c\u0438, \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0432\u0448\u0438\u043c\u0438\u0441\u044f \u0432 \u0440\u0430\u0431\u043e\u0442\u0443:<\/p>\n<p><img decoding=\"async\" alt=\"Apache Airflow: \u0434\u0435\u043b\u0430\u0435\u043c ETL \u043f\u0440\u043e\u0449\u0435\" src=\"\/wp-content\/uploads\/2020\/07\/991447e4e814a07c4b857761242e9f51.png\" style=\"display:block;margin: 0 auto;\"><\/p>\n<p>\u0421\u0430\u043c\u0430\u044f \u0441\u043a\u0443\u0447\u043d\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0447\u043a\u0430 \u0441 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u043c \u043d\u0430\u0448\u0435\u0433\u043e \u0431\u0440\u043e\u043a\u0435\u0440\u0430:<\/p>\n<p><img decoding=\"async\" alt=\"Apache Airflow: \u0434\u0435\u043b\u0430\u0435\u043c ETL \u043f\u0440\u043e\u0449\u0435\" src=\"\/wp-content\/uploads\/2020\/07\/e38e4ece42c03a8bb2cb0679312c28f1.png\" style=\"display:block;margin: 0 auto;\"><\/p>\n<p>\u0421\u0430\u043c\u0430\u044f \u044f\u0440\u043a\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0447\u043a\u0430 \u2014 \u0441 \u0433\u0440\u0430\u0444\u0438\u043a\u0430\u043c\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0442\u0430\u0441\u043a\u043e\u0432 \u0438 \u0438\u0445 \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f:<\/p>\n<p><img decoding=\"async\" alt=\"Apache Airflow: \u0434\u0435\u043b\u0430\u0435\u043c ETL \u043f\u0440\u043e\u0449\u0435\" src=\"\/wp-content\/uploads\/2020\/07\/76708648923b26887a8f625765d43bbb.png\" style=\"display:block;margin: 0 auto;\"><\/p>\n<h3 id=\"dogruzhaem-nedogruzhennoe\">\u0414\u043e\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u043d\u0435\u0434\u043e\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u043e\u0435<\/h3>\n<p>\u0418\u0442\u0430\u043a, \u0432\u0441\u0435 \u0442\u0430\u0441\u043a\u0438 \u043e\u0442\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438, \u043c\u043e\u0436\u043d\u043e \u0443\u043d\u043e\u0441\u0438\u0442\u044c \u0440\u0430\u043d\u0435\u043d\u044b\u0445.<\/p>\n<p><img decoding=\"async\" alt=\"Apache Airflow: \u0434\u0435\u043b\u0430\u0435\u043c ETL \u043f\u0440\u043e\u0449\u0435\" src=\"\/wp-content\/uploads\/2020\/07\/213107b1553806a5d29923b233eb87f9.png\" style=\"display:block;margin: 0 auto;\"><\/p>\n<p>\u0410 \u0440\u0430\u043d\u0435\u043d\u044b\u0445 \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u043d\u0435\u043c\u0430\u043b\u043e \u2014 \u043f\u043e \u0442\u0435\u043c \u0438\u043b\u0438 \u0438\u043d\u044b\u043c \u043f\u0440\u0438\u0447\u0438\u043d\u0430\u043c\u0438. \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f Airflow \u0432\u043e\u0442 \u044d\u0442\u0438 \u0441\u0430\u043c\u044b\u0435 \u043a\u0432\u0430\u0434\u0440\u0430\u0442\u044b \u0433\u043e\u0432\u043e\u0440\u044f\u0442 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e \u043d\u0435 \u0434\u043e\u0435\u0445\u0430\u043b\u0438.<\/p>\n<p>\u041d\u0443\u0436\u043d\u043e \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043b\u043e\u0433 \u0438 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0443\u043f\u0430\u0432\u0448\u0438\u0435 task instances.<\/p>\n<p>\u0416\u043c\u044f\u043a\u043d\u0443\u0432 \u043d\u0430 \u043b\u044e\u0431\u043e\u0439 \u043a\u0432\u0430\u0434\u0440\u0430\u0442, \u0443\u0432\u0438\u0434\u0438\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u043d\u0430\u043c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f:<\/p>\n<p><img decoding=\"async\" alt=\"Apache Airflow: \u0434\u0435\u043b\u0430\u0435\u043c ETL \u043f\u0440\u043e\u0449\u0435\" src=\"\/wp-content\/uploads\/2020\/07\/476f65997758a1fbd1101e03fa8d01cc.png\" style=\"display:block;margin: 0 auto;\"><\/p>\n<p>\u041c\u043e\u0436\u043d\u043e \u0432\u0437\u044f\u0442\u044c, \u0438 \u0441\u0434\u0435\u043b\u0430\u0442\u044c Clear \u0443\u043f\u0430\u0432\u0448\u0435\u043c\u0443. \u0422\u043e \u0435\u0441\u0442\u044c, \u043c\u044b \u0437\u0430\u0431\u044b\u0432\u0430\u0435\u043c \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u0442\u0430\u043c \u0447\u0442\u043e-\u0442\u043e \u0437\u0430\u0432\u0430\u043b\u0438\u043b\u043e\u0441\u044c, \u0438 \u0442\u043e\u0442 \u0436\u0435 \u0441\u0430\u043c\u044b\u0439 \u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u0442\u0430\u0441\u043a\u0430 \u0443\u0439\u0434\u0435\u0442 \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u0443.<\/p>\n<p><img decoding=\"async\" alt=\"Apache Airflow: \u0434\u0435\u043b\u0430\u0435\u043c ETL \u043f\u0440\u043e\u0449\u0435\" src=\"\/wp-content\/uploads\/2020\/07\/f56b9c22535c530e97c63135569d8a1a.png\" style=\"display:block;margin: 0 auto;\"><\/p>\n<p>\u041f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u0442\u0430\u043a \u043c\u044b\u0448\u043a\u043e\u0439 \u0441\u043e \u0432\u0441\u0435\u043c\u0438 \u043a\u0440\u0430\u0441\u043d\u044b\u043c\u0438 \u043a\u0432\u0430\u0434\u0440\u0430\u0442\u0430\u043c\u0438 \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0433\u0443\u043c\u0430\u043d\u043d\u043e \u2014 \u043d\u0435 \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u0436\u0434\u0435\u043c \u043e\u0442 Airflow. \u0415\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043e\u0440\u0443\u0436\u0438\u0435 \u043c\u0430\u0441\u0441\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u0440\u0430\u0436\u0435\u043d\u0438\u044f: <code>Browse\/Task Instances<\/code><\/p>\n<p><img decoding=\"async\" alt=\"Apache Airflow: \u0434\u0435\u043b\u0430\u0435\u043c ETL \u043f\u0440\u043e\u0449\u0435\" src=\"\/wp-content\/uploads\/2020\/07\/4ed5784ccc47980b249821a161d3aa4e.png\" style=\"display:block;margin: 0 auto;\"><\/p>\n<p>\u0412\u044b\u0431\u0435\u0440\u0435\u043c \u0432\u0441\u0451 \u0440\u0430\u0437\u043e\u043c \u0438 \u043e\u0431\u043d\u0443\u043b\u0438\u043c \u043d\u0430\u0436\u043c\u0435\u043c \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439 \u043f\u0443\u043d\u043a\u0442:<\/p>\n<p><img decoding=\"async\" alt=\"Apache Airflow: \u0434\u0435\u043b\u0430\u0435\u043c ETL \u043f\u0440\u043e\u0449\u0435\" src=\"\/wp-content\/uploads\/2020\/07\/da3ca714c0fe207453f554cd2ecb3cb2.png\" style=\"display:block;margin: 0 auto;\"><\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043e\u0447\u0438\u0441\u0442\u043a\u0438 \u043d\u0430\u0448\u0438 \u0442\u0430\u043a\u0441\u0438 \u0432\u044b\u0433\u043b\u044f\u0434\u044f\u0442 \u0442\u0430\u043a (\u043e\u043d\u0438 \u0443\u0436\u0435 \u0436\u0434\u0443\u0442 \u043d\u0435 \u0434\u043e\u0436\u0434\u0443\u0442\u0441\u044f, \u043a\u043e\u0433\u0434\u0430 \u0448\u0435\u0434\u0443\u043b\u0435\u0440 \u0438\u0445 \u0437\u0430\u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u0442):<\/p>\n<p><img decoding=\"async\" alt=\"Apache Airflow: \u0434\u0435\u043b\u0430\u0435\u043c ETL \u043f\u0440\u043e\u0449\u0435\" src=\"\/wp-content\/uploads\/2020\/07\/0ea89e512f9ca09e997955b2b0b2e615.png\" style=\"display:block;margin: 0 auto;\"><\/p>\n<h3 id=\"soedineniya-huki-i-prochie-peremennye\">\u0421\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f, \u0445\u0443\u043a\u0438 \u0438 \u043f\u0440\u043e\u0447\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435<\/h3>\n<p>\u0421\u0430\u043c\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043d\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 DAG, <code>update_reports.py<\/code>:<\/p>\n<pre><code class=\"python\">from collections import namedtuple\nfrom datetime import datetime, timedelta\nfrom textwrap import dedent\n\nfrom airflow import DAG\nfrom airflow.contrib.operators.vertica_operator import VerticaOperator\nfrom airflow.operators.email_operator import EmailOperator\nfrom airflow.utils.trigger_rule import TriggerRule\n\nfrom commons.operators import TelegramBotSendMessage\n\ndag = DAG('update_reports',\n          start_date=datetime(2020, 6, 7, 6),\n          schedule_interval=timedelta(days=1),\n          default_args={'retries': 3, 'retry_delay': timedelta(seconds=10)})\n\nReport = namedtuple('Report', 'source target')\nreports = [Report(f'{table}_view', table) for table in [\n    'reports.city_orders',\n    'reports.client_calls',\n    'reports.client_rates',\n    'reports.daily_orders',\n    'reports.order_duration']]\n\nemail = EmailOperator(\n    task_id='email_success', dag=dag,\n    to='{{ var.value.all_the_kings_men }}',\n    subject='DWH Reports updated',\n    html_content=dedent(\"\"\"\u0413\u043e\u0441\u043f\u043e\u0434\u0430 \u0445\u043e\u0440\u043e\u0448\u0438\u0435, \u043e\u0442\u0447\u0435\u0442\u044b \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u044b\"\"\"),\n    trigger_rule=TriggerRule.ALL_SUCCESS)\n\ntg = TelegramBotSendMessage(\n    task_id='telegram_fail', dag=dag,\n    tg_bot_conn_id='tg_main',\n    chat_id='{{ var.value.failures_chat }}',\n    message=dedent(\"\"\"\n         \u041d\u0430\u0442\u0430\u0448, \u043f\u0440\u043e\u0441\u044b\u043f\u0430\u0439\u0441\u044f, \u043c\u044b {{ dag.dag_id }} \u0443\u0440\u043e\u043d\u0438\u043b\u0438\n        \"\"\"),\n    trigger_rule=TriggerRule.ONE_FAILED)\n\nfor source, target in reports:\n    queries = [f\"TRUNCATE TABLE {target}\",\n               f\"INSERT INTO {target} SELECT * FROM {source}\"]\n\n    report_update = VerticaOperator(\n        task_id=target.replace('reports.', ''),\n        sql=queries, vertica_conn_id='dwh',\n        task_concurrency=1, dag=dag)\n\n    report_update &gt;&gt; [email, tg]<\/code><\/pre>\n<p>\u0412\u0441\u0435 \u0432\u0435\u0434\u044c \u043a\u043e\u0433\u0434\u0430-\u043d\u0438\u0431\u0443\u0434\u044c \u0434\u0435\u043b\u0430\u043b\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u043b\u043a\u0443 \u043e\u0442\u0447\u0435\u0442\u043e\u0432? \u042d\u0442\u043e \u0441\u043d\u043e\u0432\u0430 \u043e\u043d\u0430: \u0435\u0441\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u0432, \u043e\u0442\u043a\u0443\u0434\u0430 \u0437\u0430\u0431\u0440\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435; \u0435\u0441\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a, \u043a\u0443\u0434\u0430 \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c; \u043d\u0435 \u0437\u0430\u0431\u044b\u0432\u0430\u0435\u043c \u043f\u043e\u0441\u0438\u0433\u043d\u0430\u043b\u0438\u0442\u044c, \u043a\u043e\u0433\u0434\u0430 \u0432\u0441\u0451 \u0441\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c \u0438\u043b\u0438 \u0441\u043b\u043e\u043c\u0430\u043b\u043e\u0441\u044c (\u043d\u0443 \u044d\u0442\u043e \u043d\u0435 \u043f\u0440\u043e \u043d\u0430\u0441, \u043d\u0435\u0442).<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043d\u043e\u0432\u0430 \u043f\u0440\u043e\u0439\u0434\u0435\u043c\u0441\u044f \u043f\u043e \u0444\u0430\u0439\u043b\u0443 \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u043d\u043e\u0432\u044b\u0435 \u043d\u0435\u043f\u043e\u043d\u044f\u0442\u043d\u044b\u0435 \u0448\u0442\u0443\u043a\u0438:<\/p>\n<ul>\n<li><code>from commons.operators import TelegramBotSendMessage<\/code> \u2014 \u043d\u0430\u043c \u043d\u0438\u0447\u0442\u043e \u043d\u0435 \u043c\u0435\u0448\u0430\u0435\u0442 \u0434\u0435\u043b\u0430\u0442\u044c \u0441\u0432\u043e\u0438 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b, \u0447\u0435\u043c \u043c\u044b \u0438 \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438\u0441\u044c, \u0441\u0434\u0435\u043b\u0430\u0432 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0443\u044e \u043e\u0431\u0451\u0440\u0442\u043e\u0447\u043a\u0443 \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0432 \u0420\u0430\u0437\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439. (\u041e\u0431 \u044d\u0442\u043e\u043c \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0435 \u043c\u044b \u0435\u0449\u0435 \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043c \u043d\u0438\u0436\u0435);<\/li>\n<li><code>default_args={}<\/code> \u2014 \u0434\u0430\u0433 \u043c\u043e\u0436\u0435\u0442 \u0440\u0430\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043e\u0434\u043d\u0438 \u0438 \u0442\u0435 \u0436\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u0432\u0441\u0435\u043c \u0441\u0432\u043e\u0438\u043c \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430\u043c;<\/li>\n<li><code>to='{{ var.value.all_the_kings_men }}'<\/code> \u2014 \u043f\u043e\u043b\u0435 <code>to<\/code> \u0443 \u043d\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 \u043d\u0435 \u0437\u0430\u0445\u0430\u0440\u0434\u043a\u043e\u0436\u0435\u043d\u043d\u044b\u043c, \u0430 \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c\u044b\u043c \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Jinja \u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0441\u043e \u0441\u043f\u0438\u0441\u043a\u043e\u043c email-\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u044f \u0437\u0430\u0431\u043e\u0442\u043b\u0438\u0432\u043e \u043f\u043e\u043b\u043e\u0436\u0438\u043b \u0432 <code>Admin\/Variables<\/code>;<\/li>\n<li><code>trigger_rule=TriggerRule.ALL_SUCCESS<\/code> \u2014 \u0443\u0441\u043b\u043e\u0432\u0438\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430. \u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u043f\u0438\u0441\u044c\u043c\u043e \u043f\u043e\u043b\u0435\u0442\u0438\u0442 \u0431\u043e\u0441\u0441\u0430\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0435\u0441\u043b\u0438 \u0432\u0441\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 <strong>\u0443\u0441\u043f\u0435\u0448\u043d\u043e<\/strong>;<\/li>\n<li><code>tg_bot_conn_id='tg_main'<\/code> \u2014 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b <code>conn_id<\/code> \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0442 \u0432 \u0441\u0435\u0431\u044f \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u044b \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0432 <code>Admin\/Connections<\/code>;<\/li>\n<li><code>trigger_rule=TriggerRule.ONE_FAILED<\/code> \u2014 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0432 Telegram \u0443\u043b\u0435\u0442\u044f\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438 \u043d\u0430\u043b\u0438\u0447\u0438\u0438 \u0443\u043f\u0430\u0432\u0448\u0438\u0445 \u0442\u0430\u0441\u043a\u043e\u0432;<\/li>\n<li><code>task_concurrency=1<\/code> \u2014 \u0437\u0430\u043f\u0440\u0435\u0449\u0430\u0435\u043c \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0439 \u0437\u0430\u043f\u0443\u0441\u043a \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 task instances \u043e\u0434\u043d\u043e\u0433\u043e \u0442\u0430\u0441\u043a\u0430. \u0412 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0439 \u0437\u0430\u043f\u0443\u0441\u043a \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 <code>VerticaOperator<\/code> (\u0441\u043c\u043e\u0442\u0440\u044f\u0449\u0438\u0445 \u043d\u0430 \u043e\u0434\u043d\u0443 \u0442\u0430\u0431\u043b\u0438\u0446\u0443);<\/li>\n<li><code>report_update &gt;&gt; [email, tg]<\/code> \u2014 \u0432\u0441\u0435 <code>VerticaOperator<\/code> \u0441\u043e\u0439\u0434\u0443\u0442\u0441\u044f \u0432 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0435 \u043f\u0438\u0441\u044c\u043c\u0430 \u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f, \u0432\u043e\u0442 \u0442\u0430\u043a:<br \/>\n<img decoding=\"async\" alt=\"Apache Airflow: \u0434\u0435\u043b\u0430\u0435\u043c ETL \u043f\u0440\u043e\u0449\u0435\" src=\"\/wp-content\/uploads\/2020\/07\/a533e1dcbb252c2d8360929fa44b8ef8.png\" style=\"display:block;margin: 0 auto;\"><\/p>\n<p>\u041d\u043e \u0442\u0430\u043a \u043a\u0430\u043a \u0443 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432-\u043d\u043e\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u0432 \u0441\u0442\u043e\u044f\u0442 \u0440\u0430\u0437\u043d\u044b\u0435 \u0443\u0441\u043b\u043e\u0432\u0438\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430, \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0431\u0443\u0434\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d. \u0412 Tree View \u0432\u0441\u0451 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u0435\u043d\u0435\u0435 \u043d\u0430\u0433\u043b\u044f\u0434\u043d\u043e:<br \/>\n<img decoding=\"async\" alt=\"Apache Airflow: \u0434\u0435\u043b\u0430\u0435\u043c ETL \u043f\u0440\u043e\u0449\u0435\" src=\"\/wp-content\/uploads\/2020\/07\/bf5299ffd38849f2fb8668d673ab34ba.png\" style=\"display:block;margin: 0 auto;\"><\/li>\n<\/ul>\n<p>\u0421\u043a\u0430\u0436\u0443 \u043f\u0430\u0440\u0443 \u0441\u043b\u043e\u0432 \u043e <strong>\u043c\u0430\u043a\u0440\u043e\u0441\u0430\u0445<\/strong> \u0438 \u0438\u0445 \u0434\u0440\u0443\u0437\u044c\u044f\u0445 \u2014 <strong>\u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445<\/strong>.<\/p>\n<p>\u041c\u0430\u043a\u0440\u043e\u0441\u044b \u2014 \u044d\u0442\u043e Jinja-\u043f\u043b\u0435\u0439\u0441\u0445\u043e\u043b\u0434\u0435\u0440\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u043f\u043e\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0440\u0430\u0437\u043d\u0443\u044e \u043f\u043e\u043b\u0435\u0437\u043d\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0432 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0442\u0430\u043a:<\/p>\n<pre><code class=\"sql\">SELECT\n    id,\n    payment_dtm,\n    payment_type,\n    client_id\nFROM orders.payments\nWHERE\n    payment_dtm::DATE = '{{ ds }}'::DATE<\/code><\/pre>\n<p><code>{{ ds }}<\/code> \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0435\u0442\u0441\u044f \u0432 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 <code>execution_date<\/code> \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 <code>YYYY-MM-DD<\/code>: <code>2020-07-14<\/code>. \u0421\u0430\u043c\u043e\u0435 \u043f\u0440\u0438\u044f\u0442\u043d\u043e\u0435, \u0447\u0442\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 \u043f\u0440\u0438\u0431\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0433\u0432\u043e\u0437\u0434\u044f\u043c\u0438 \u043a \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u043c\u0443 \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u0443 \u0442\u0430\u0441\u043a\u0430 (\u043a\u0432\u0430\u0434\u0440\u0430\u0442\u0438\u043a\u0443 \u0432 Tree View), \u0438 \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u043f\u043b\u0435\u0439\u0441\u0445\u043e\u043b\u0434\u0435\u0440\u044b \u0440\u0430\u0441\u043a\u0440\u043e\u044e\u0442\u0441\u044f \u0432 \u0442\u0435 \u0436\u0435 \u0441\u0430\u043c\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f.<\/p>\n<p>\u041f\u0440\u0438\u0441\u0432\u043e\u0435\u043d\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043d\u043e\u043f\u043a\u0438 Rendered \u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u043c \u0442\u0430\u0441\u043a-\u0438\u043d\u0441\u0442\u0430\u043d\u0441\u0435. \u0412\u043e\u0442 \u0442\u0430\u043a \u0443 \u0442\u0430\u0441\u043a\u0430 \u0441 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u043e\u0439 \u043f\u0438\u0441\u044c\u043c\u0430:<\/p>\n<p><img decoding=\"async\" alt=\"Apache Airflow: \u0434\u0435\u043b\u0430\u0435\u043c ETL \u043f\u0440\u043e\u0449\u0435\" src=\"\/wp-content\/uploads\/2020\/07\/03accc86161d8b8011bbb3242ad38837.png\" style=\"display:block;margin: 0 auto;\"><\/p>\n<p>\u0410 \u0442\u0430\u043a \u0443 \u0442\u0430\u0441\u043a\u0438 \u0441 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u043e\u0439 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f:<\/p>\n<p><img decoding=\"async\" alt=\"Apache Airflow: \u0434\u0435\u043b\u0430\u0435\u043c ETL \u043f\u0440\u043e\u0449\u0435\" src=\"\/wp-content\/uploads\/2020\/07\/c3f9478073df7c4fb62592dbe21b6d3a.png\" style=\"display:block;margin: 0 auto;\"><\/p>\n<p>\u041f\u043e\u043b\u043d\u044b\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0445 \u043c\u0430\u043a\u0440\u043e\u0441\u043e\u0432 \u0434\u043b\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0439 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0437\u0434\u0435\u0441\u044c: <noindex><a rel=\"nofollow\" href=\"https:\/\/airflow.apache.org\/docs\/stable\/macros-ref.html\">Macros Reference<\/a><\/noindex><\/p>\n<p>\u0411\u043e\u043b\u0435\u0435 \u0442\u043e\u0433\u043e, \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043e\u0431\u044a\u044f\u0432\u043b\u044f\u0442\u044c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u043c\u0430\u043a\u0440\u043e\u0441\u044b, \u043d\u043e \u044d\u0442\u043e \u0443\u0436\u0435 \u0441\u043e\u0432\u0441\u0435\u043c \u0434\u0440\u0443\u0433\u0430\u044f \u0438\u0441\u0442\u043e\u0440\u0438\u044f.<\/p>\n<p>\u041f\u043e\u043c\u0438\u043c\u043e \u043f\u0440\u0435\u0434\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0445 \u0448\u0442\u0443\u043a, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0441\u0432\u043e\u0438\u0445 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 (\u0432\u044b\u0448\u0435 \u0432 \u043a\u043e\u0434\u0435 \u044f \u0443\u0436\u0435 \u044d\u0442\u0438\u043c \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0441\u044f). \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0432 <code>Admin\/Variables<\/code> \u043f\u0430\u0440\u0443 \u0448\u0442\u0443\u043a:<\/p>\n<p><img decoding=\"async\" alt=\"Apache Airflow: \u0434\u0435\u043b\u0430\u0435\u043c ETL \u043f\u0440\u043e\u0449\u0435\" src=\"\/wp-content\/uploads\/2020\/07\/cc0ec12a524a622b1563126ac87f39c9.png\" style=\"display:block;margin: 0 auto;\"><\/p>\n<p>\u0412\u0441\u0451, \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f:<\/p>\n<pre><code class=\"python\">TelegramBotSendMessage(chat_id='{{ var.value.failures_chat }}')<\/code><\/pre>\n<p>\u0412 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0438 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0441\u043a\u0430\u043b\u044f\u0440, \u0430 \u043c\u043e\u0436\u0435\u0442 \u043b\u0435\u0436\u0430\u0442\u044c \u0438 JSON. \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 JSON-\u0430:<\/p>\n<pre><code class=\"json\">bot_config\n\n{\n    \"bot\": {\n        \"token\": 881hskdfASDA16641,\n        \"name\": \"Verter\"\n    },\n    \"service\": \"TG\"\n}<\/code><\/pre>\n<p>\u043f\u0440\u043e\u0441\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043f\u0443\u0442\u044c \u043a \u043d\u0443\u0436\u043d\u043e\u043c\u0443 \u043a\u043b\u044e\u0447\u0443: <code>{{ var.json.bot_config.bot.token }}<\/code>.<\/p>\n<p>\u0421\u043a\u0430\u0436\u0443 \u0431\u0443\u043a\u0432\u0430\u043b\u044c\u043d\u043e \u043e\u0434\u043d\u043e \u0441\u043b\u043e\u0432\u043e \u0438 \u043f\u043e\u043a\u0430\u0436\u0443 \u043e\u0434\u0438\u043d \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442 \u043f\u0440\u043e <strong>\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f<\/strong>. \u0422\u0443\u0442 \u0432\u0441\u0451 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0440\u043d\u043e: \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 <code>Admin\/Connections<\/code> \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435, \u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u043c \u0442\u0443\u0434\u0430 \u043d\u0430\u0448\u0438 \u043b\u043e\u0433\u0438\u043d\u044b\/\u043f\u0430\u0440\u043e\u043b\u0438 \u0438 \u0431\u043e\u043b\u0435\u0435 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b. \u0412\u043e\u0442 \u0442\u0430\u043a:<\/p>\n<p><img decoding=\"async\" alt=\"Apache Airflow: \u0434\u0435\u043b\u0430\u0435\u043c ETL \u043f\u0440\u043e\u0449\u0435\" src=\"\/wp-content\/uploads\/2020\/07\/b67ba569482cd7acbd86d09eed38764f.png\" style=\"display:block;margin: 0 auto;\"><\/p>\n<p>\u041f\u0430\u0440\u043e\u043b\u0438 \u043c\u043e\u0436\u043d\u043e \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u0442\u044c (\u0431\u043e\u043b\u0435\u0435 \u0442\u0449\u0430\u0442\u0435\u043b\u044c\u043d\u043e, \u0447\u0435\u043c \u0432 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0435 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e), \u0430 \u043c\u043e\u0436\u043d\u043e \u043d\u0435 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0442\u0438\u043f \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f (\u043a\u0430\u043a \u044f \u0441\u0434\u0435\u043b\u0430\u043b \u0434\u043b\u044f <code>tg_main<\/code>) \u2014 \u0434\u0435\u043b\u043e \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0441\u043f\u0438\u0441\u043e\u043a \u0442\u0438\u043f\u043e\u0432 \u0437\u0430\u0448\u0438\u0442 \u0432 \u043c\u043e\u0434\u0435\u043b\u044f\u0445 Airflow \u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044e \u0431\u0435\u0437 \u0432\u043b\u0435\u0437\u0430\u043d\u0438\u044f \u0432 \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438 \u043d\u0435 \u043f\u043e\u0434\u0434\u0430\u0435\u0442\u0441\u044f (\u0435\u0441\u043b\u0438 \u0432\u0434\u0440\u0443\u0433 \u044f \u0447\u0435\u0433\u043e-\u0442\u043e \u043d\u0435 \u0434\u043e\u0433\u0443\u0433\u043b\u0438\u043b \u2014 \u043f\u0440\u043e\u0448\u0443 \u043c\u0435\u043d\u044f \u043f\u043e\u043f\u0440\u0430\u0432\u0438\u0442\u044c), \u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043a\u0440\u0435\u0434\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e \u0438\u043c\u0435\u043d\u0438 \u043d\u0430\u043c \u043d\u0438\u0447\u0442\u043e \u043d\u0435 \u043f\u043e\u043c\u0435\u0448\u0430\u0435\u0442.<\/p>\n<p>\u0410 \u0435\u0449\u0435 \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 \u0441 \u043e\u0434\u043d\u0438\u043c \u0438\u043c\u0435\u043d\u0435\u043c: \u0432 \u0442\u0430\u043a\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043c\u0435\u0442\u043e\u0434 <code>BaseHook.get_connection()<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u043e\u0441\u0442\u0430\u0435\u0442 \u043d\u0430\u043c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u043f\u043e \u0438\u043c\u0435\u043d\u0438, \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0434\u0430\u0432\u0430\u0442\u044c <em>\u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e\u0433\u043e<\/em> \u0438\u0437 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0442\u0451\u0437\u043e\u043a (\u0431\u044b\u043b\u043e \u0431\u044b \u043b\u043e\u0433\u0438\u0447\u043d\u0435\u0435 \u0441\u0434\u0435\u043b\u0430\u0442\u044c Round Robin, \u043d\u043e \u043e\u0441\u0442\u0430\u0432\u0438\u043c \u044d\u0442\u043e \u043d\u0430 \u0441\u043e\u0432\u0435\u0441\u0442\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 Airflow).<\/p>\n<blockquote><p>Variables \u0438 Connections, \u0431\u0435\u0437\u0443\u0441\u043b\u043e\u0432\u043d\u043e, \u043a\u043b\u0430\u0441\u0441\u043d\u044b\u0435 \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430, \u043d\u043e \u0432\u0430\u0436\u043d\u043e \u043d\u0435 \u043f\u043e\u0442\u0435\u0440\u044f\u0442\u044c \u0431\u0430\u043b\u0430\u043d\u0441: \u043a\u0430\u043a\u0438\u0435 \u0447\u0430\u0441\u0442\u0438 \u0432\u0430\u0448\u0438\u0445 \u043f\u043e\u0442\u043e\u043a\u043e\u0432 \u0432\u044b \u0445\u0440\u0430\u043d\u0438\u0442\u0435 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0432 \u043a\u043e\u0434\u0435, \u0430 \u043a\u0430\u043a\u0438\u0435 \u2014 \u043e\u0442\u0434\u0430\u0435\u0442\u0435 \u043d\u0430 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 Airflow. C \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u0431\u044b\u0441\u0442\u0440\u043e \u043f\u043e\u043c\u0435\u043d\u044f\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u044f\u0449\u0438\u043a \u0440\u0430\u0441\u0441\u044b\u043b\u043a\u0438, \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0443\u0434\u043e\u0431\u043d\u043e \u0447\u0435\u0440\u0435\u0437 UI. \u0410 \u0441 \u0434\u0440\u0443\u0433\u043e\u0439 \u2014 \u044d\u0442\u043e \u0432\u0441\u0451-\u0442\u0430\u043a\u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0442 \u043a \u043c\u044b\u0448\u0435\u043a\u043b\u0438\u043a\u0443, \u043e\u0442 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u044b (\u044f) \u0445\u043e\u0442\u0435\u043b\u0438 \u0438\u0437\u0431\u0430\u0432\u0438\u0442\u044c\u0441\u044f.<\/p><\/blockquote>\n<p>\u0420\u0430\u0431\u043e\u0442\u0430 \u0441 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f\u043c\u0438 \u2014 \u044d\u0442\u043e \u043e\u0434\u043d\u0430 \u0438\u0437 \u0437\u0430\u0434\u0430\u0447 <strong>\u0445\u0443\u043a\u043e\u0432<\/strong>. \u0412\u043e\u043e\u0431\u0449\u0435 \u0445\u0443\u043a\u0438 Airflow \u2014 \u044d\u0442\u043e \u0442\u043e\u0447\u043a\u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0435\u0433\u043e \u043a \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u043c \u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c \u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430\u043c. \u041a \u043f\u0440\u0438\u043c\u0435\u0440\u0443, <code>JiraHook<\/code> \u043e\u0442\u043a\u0440\u043e\u0435\u0442 \u0434\u043b\u044f \u043d\u0430\u0441 \u043a\u043b\u0438\u0435\u043d\u0442 \u0434\u043b\u044f \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 Jira (\u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0434\u0430\u0447\u043a\u0438 \u043f\u043e\u0434\u0432\u0438\u0433\u0430\u0442\u044c \u0442\u0443\u0434\u0430-\u0441\u044e\u0434\u0430), \u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>SambaHook<\/code> \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043f\u0443\u0448\u0438\u0442\u044c \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u043d\u0430 <code>smb<\/code>-\u0442\u043e\u0447\u043a\u0443.<\/p>\n<h3 id=\"razbiraem-kastomnyy-operator\">\u0420\u0430\u0437\u0431\u0438\u0440\u0430\u0435\u043c \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0439 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440<\/h3>\n<p>\u0418 \u043c\u044b \u0432\u043f\u043b\u043e\u0442\u043d\u0443\u044e \u043f\u043e\u0434\u043e\u0431\u0440\u0430\u043b\u0438\u0441\u044c \u043a \u0442\u043e\u043c\u0443, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043d\u0430 \u0442\u043e, \u043a\u0430\u043a \u0441\u0434\u0435\u043b\u0430\u043d <code>TelegramBotSendMessage<\/code><\/p>\n<p>\u041a\u043e\u0434 <code>commons\/operators.py<\/code> \u0441 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u043c:<\/p>\n<pre><code class=\"python\">from typing import Union\n\nfrom airflow.operators import BaseOperator\n\nfrom commons.hooks import TelegramBotHook, TelegramBot\n\nclass TelegramBotSendMessage(BaseOperator):\n    \"\"\"Send message to chat_id using TelegramBotHook\n\n    Example:\n        &gt;&gt;&gt; TelegramBotSendMessage(\n        ...     task_id='telegram_fail', dag=dag,\n        ...     tg_bot_conn_id='tg_bot_default',\n        ...     chat_id='{{ var.value.all_the_young_dudes_chat }}',\n        ...     message='{{ dag.dag_id }} failed :(',\n        ...     trigger_rule=TriggerRule.ONE_FAILED)\n    \"\"\"\n    template_fields = ['chat_id', 'message']\n\n    def __init__(self,\n                 chat_id: Union[int, str],\n                 message: str,\n                 tg_bot_conn_id: str = 'tg_bot_default',\n                 *args, **kwargs):\n        super().__init__(*args, **kwargs)\n\n        self._hook = TelegramBotHook(tg_bot_conn_id)\n        self.client: TelegramBot = self._hook.client\n        self.chat_id = chat_id\n        self.message = message\n\n    def execute(self, context):\n        print(f'Send \"{self.message}\" to the chat {self.chat_id}')\n        self.client.send_message(chat_id=self.chat_id,\n                                 message=self.message)<\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c, \u043a\u0430\u043a \u0438 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0435 \u0432 Airflow, \u0432\u0441\u0451 \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u043e:<\/p>\n<ul>\n<li>\u041e\u0442\u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043b\u0438\u0441\u044c \u043e\u0442 <code>BaseOperator<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043c\u043d\u043e\u0433\u043e Airflow-\u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u043d\u044b\u0445 \u0448\u0442\u0443\u043a (\u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435 \u043d\u0430 \u0434\u043e\u0441\u0443\u0433\u0435)<\/li>\n<li>\u041e\u0431\u044a\u044f\u0432\u0438\u043b\u0438 \u043f\u043e\u043b\u044f <code>template_fields<\/code>, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 Jinja \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043a\u0430\u0442\u044c \u043c\u0430\u043a\u0440\u043e\u0441\u044b \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438.<\/li>\n<li>\u041e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u043b\u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u0434\u043b\u044f <code>__init__()<\/code>, \u0440\u0430\u0441\u0441\u0442\u0430\u0432\u0438\u043b\u0438 \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044f, \u0433\u0434\u0435 \u043d\u0430\u0434\u043e.<\/li>\n<li>\u041e\u0431 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0440\u0435\u0434\u043a\u0430 \u0442\u043e\u0436\u0435 \u043d\u0435 \u0437\u0430\u0431\u044b\u043b\u0438.<\/li>\n<li>\u041e\u0442\u043a\u0440\u044b\u043b\u0438 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u0445\u0443\u043a <code>TelegramBotHook<\/code>, \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u043e\u0442 \u043d\u0435\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442-\u043a\u043b\u0438\u0435\u043d\u0442.<\/li>\n<li>\u041e\u0432\u0435\u0440\u0440\u0430\u0439\u0434\u043d\u0443\u043b\u0438 (\u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043b\u0438) \u043c\u0435\u0442\u043e\u0434 <code>BaseOperator.execute()<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 Airfow \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0434\u0435\u0440\u0433\u0438\u0432\u0430\u0442\u044c, \u043a\u043e\u0433\u0434\u0430 \u043d\u0430\u0441\u0442\u0443\u043f\u0438\u0442 \u0432\u0440\u0435\u043c\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 \u2014 \u0432 \u043d\u0435\u043c \u043c\u044b \u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435, \u043d\u0430 \u0437\u0430\u0431\u044b\u0432 \u0437\u0430\u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f. (\u041b\u043e\u0433\u0438\u0440\u0443\u0435\u043c\u0441\u044f, \u043a\u0441\u0442\u0430\u0442\u0438, \u043f\u0440\u044f\u043c\u043e \u0432 <code>stdout<\/code> \u0438 <code>stderr<\/code> \u2014 Airflow \u0432\u0441\u0451 \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u0438\u0442, \u043a\u0440\u0430\u0441\u0438\u0432\u043e \u043e\u0431\u0435\u0440\u043d\u0435\u0442, \u0440\u0430\u0437\u043b\u043e\u0436\u0438\u0442, \u043a\u0443\u0434\u0430 \u043d\u0430\u0434\u043e.)<\/li>\n<\/ul>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c, \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u0432 <code>commons\/hooks.py<\/code>. \u041f\u0435\u0440\u0432\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0444\u0430\u0439\u043b\u0438\u043a\u0430, \u0441 \u0441\u0430\u043c\u0438\u043c \u0445\u0443\u043a\u043e\u043c:<\/p>\n<pre><code class=\"python\">from typing import Union\n\nfrom airflow.hooks.base_hook import BaseHook\nfrom requests_toolbelt.sessions import BaseUrlSession\n\nclass TelegramBotHook(BaseHook):\n    \"\"\"Telegram Bot API hook\n\n    Note: add a connection with empty Conn Type and don't forget\n    to fill Extra:\n\n        {\"bot_token\": \"YOuRAwEsomeBOtToKen\"}\n    \"\"\"\n    def __init__(self,\n                 tg_bot_conn_id='tg_bot_default'):\n        super().__init__(tg_bot_conn_id)\n\n        self.tg_bot_conn_id = tg_bot_conn_id\n        self.tg_bot_token = None\n        self.client = None\n        self.get_conn()\n\n    def get_conn(self):\n        extra = self.get_connection(self.tg_bot_conn_id).extra_dejson\n        self.tg_bot_token = extra['bot_token']\n        self.client = TelegramBot(self.tg_bot_token)\n        return self.client<\/code><\/pre>\n<p>\u042f \u0434\u0430\u0436\u0435 \u043d\u0435 \u0437\u043d\u0430\u044e, \u0447\u0442\u043e \u0442\u0443\u0442 \u043c\u043e\u0436\u043d\u043e \u043e\u0431\u044a\u044f\u0441\u043d\u044f\u0442\u044c, \u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0442\u043c\u0435\u0447\u0443 \u0432\u0430\u0436\u043d\u044b\u0435 \u043c\u043e\u043c\u0435\u043d\u0442\u044b:<\/p>\n<ul>\n<li>\u041d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u043c\u0441\u044f, \u0434\u0443\u043c\u0430\u0435\u043c \u043d\u0430\u0434 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u2014 \u0432 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0435 \u0441\u043b\u0443\u0447\u0430\u0435\u0432 \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u043e\u0434\u0438\u043d: <code>conn_id<\/code>;<\/li>\n<li>\u041f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b: \u044f \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u043b\u0441\u044f <code>get_conn()<\/code>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u044f \u043f\u043e\u043b\u0443\u0447\u0430\u044e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u043f\u043e \u0438\u043c\u0435\u043d\u0438 \u0438 \u0432\u0441\u0435\u0433\u043e-\u043d\u0430\u0432\u0441\u0435\u0433\u043e \u0434\u043e\u0441\u0442\u0430\u044e \u0441\u0435\u043a\u0446\u0438\u044e <code>extra<\/code> (\u044d\u0442\u043e \u043f\u043e\u043b\u0435 \u0434\u043b\u044f JSON), \u0432 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u044f (\u043f\u043e \u0441\u0432\u043e\u0435\u0439 \u0436\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438!) \u043f\u043e\u043b\u043e\u0436\u0438\u043b \u0442\u043e\u043a\u0435\u043d Telegram-\u0431\u043e\u0442\u0430: <code>{\"bot_token\": \"YOuRAwEsomeBOtToKen\"}<\/code>.<\/li>\n<li>\u0421\u043e\u0437\u0434\u0430\u044e \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043d\u0430\u0448\u0435\u0433\u043e <code>TelegramBot<\/code>, \u043e\u0442\u0434\u0430\u0432\u0430\u044f \u0435\u043c\u0443 \u0443\u0436\u0435 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u0442\u043e\u043a\u0435\u043d.<\/li>\n<\/ul>\n<p>\u0412\u043e\u0442 \u0438 \u0432\u0441\u0451. \u041f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043a\u043b\u0438\u0435\u043d\u0442 \u0438\u0437 \u0445\u0443\u043a\u0430 \u043c\u043e\u0436\u043d\u043e c \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>TelegramBotHook().clent<\/code> \u0438\u043b\u0438 <code>TelegramBotHook().get_conn()<\/code>.<\/p>\n<p>\u0418 \u0432\u0442\u043e\u0440\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0444\u0430\u0439\u043b\u0438\u043a\u0430, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u044f \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043c\u0438\u043a\u0440\u043e\u043e\u0431\u0451\u0440\u0442\u043e\u0447\u043a\u0443 \u0434\u043b\u044f Telegram REST API, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0442\u0430\u0449\u0438\u0442\u044c \u0442\u043e\u0442 \u0436\u0435 <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/python-telegram-bot\/python-telegram-bot\"><code>python-telegram-bot<\/code><\/a><\/noindex> \u0440\u0430\u0434\u0438 \u043e\u0434\u043d\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 <code>sendMessage<\/code>.<\/p>\n<pre><code class=\"python\">class TelegramBot:\n    \"\"\"Telegram Bot API wrapper\n\n    Examples:\n        &gt;&gt;&gt; TelegramBot('YOuRAwEsomeBOtToKen', '@myprettydebugchat').send_message('Hi, darling')\n        &gt;&gt;&gt; TelegramBot('YOuRAwEsomeBOtToKen').send_message('Hi, darling', chat_id=-1762374628374)\n    \"\"\"\n    API_ENDPOINT = 'https:\/\/api.telegram.org\/bot{}\/'\n\n    def __init__(self, tg_bot_token: str, chat_id: Union[int, str] = None):\n        self._base_url = TelegramBot.API_ENDPOINT.format(tg_bot_token)\n        self.session = BaseUrlSession(self._base_url)\n        self.chat_id = chat_id\n\n    def send_message(self, message: str, chat_id: Union[int, str] = None):\n        method = 'sendMessage'\n\n        payload = {'chat_id': chat_id or self.chat_id,\n                   'text': message,\n                   'parse_mode': 'MarkdownV2'}\n\n        response = self.session.post(method, data=payload).json()\n        if not response.get('ok'):\n            raise TelegramBotException(response)\n\nclass TelegramBotException(Exception):\n    def __init__(self, *args, **kwargs):\n        super().__init__((args, kwargs))<\/code><\/pre>\n<blockquote><p>\u041f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439 \u043f\u0443\u0442\u044c \u2014 \u0441\u043b\u043e\u0436\u0438\u0442\u044c \u0432\u0441\u0451 \u044d\u0442\u043e: <code>TelegramBotSendMessage<\/code>, <code>TelegramBotHook<\/code>, <code>TelegramBot<\/code> \u2014 \u0432 \u043f\u043b\u0430\u0433\u0438\u043d, \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c \u0432 \u043e\u0431\u0449\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0439 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439, \u0438 \u043e\u0442\u0434\u0430\u0442\u044c \u0432 Open Source.<\/p><\/blockquote>\n<p>\u041f\u043e\u043a\u0430 \u043c\u044b \u0432\u0441\u0451 \u044d\u0442\u043e \u0438\u0437\u0443\u0447\u0430\u043b\u0438, \u043d\u0430\u0448\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043e\u0442\u0447\u0435\u0442\u043e\u0432 \u0443\u0441\u043f\u0435\u043b\u0438 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0437\u0430\u0432\u0430\u043b\u0438\u0442\u044c\u0441\u044f \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u043c\u043d\u0435 \u0432 \u043a\u0430\u043d\u0430\u043b \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0435. \u041f\u043e\u0439\u0434\u0443 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c, \u0447\u0442\u043e \u043e\u043f\u044f\u0442\u044c \u043d\u0435 \u0442\u0430\u043a&#8230;<\/p>\n<p><img decoding=\"async\" alt=\"Apache Airflow: \u0434\u0435\u043b\u0430\u0435\u043c ETL \u043f\u0440\u043e\u0449\u0435\" src=\"\/wp-content\/uploads\/2020\/07\/3c2502f2d0844c99b3de722fd7e9ef9d.png\" style=\"display:block;margin: 0 auto;\"><br \/>\n<em>\u0412 \u043d\u0430\u0448\u0435\u043c \u0434\u0430\u0433\u0435 \u0447\u0442\u043e-\u0442\u043e \u0441\u043b\u043e\u043c\u0430\u043b\u043e\u0441\u044c! \u0410 \u043d\u0438 \u044d\u0442\u043e\u0433\u043e \u043b\u0438 \u043c\u044b \u0436\u0434\u0430\u043b\u0438? \u0418\u043c\u0435\u043d\u043d\u043e!<\/em><\/p>\n<h3 id=\"nalivat-to-budesh\">\u041d\u0430\u043b\u0438\u0432\u0430\u0442\u044c-\u0442\u043e \u0431\u0443\u0434\u0435\u0448\u044c?<\/h3>\n<p>\u0427\u0443\u0432\u0441\u0442\u0432\u0443\u0435\u0442\u0435, \u0447\u0442\u043e-\u0442\u043e \u044f \u043f\u0440\u043e\u043f\u0443\u0441\u0442\u0438\u043b? \u0412\u0440\u043e\u0434\u0435 \u0431\u044b \u043e\u0431\u0435\u0449\u0430\u043b \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 SQL Server \u0432 Vertica \u043f\u0435\u0440\u0435\u043b\u0438\u0432\u0430\u0442\u044c, \u0438 \u0442\u0443\u0442 \u0432\u0437\u044f\u043b \u0438 \u0441\u044a\u0435\u0445\u0430\u043b \u0441 \u0442\u0435\u043c\u044b, \u043d\u0435\u0433\u043e\u0434\u044f\u0439!<\/p>\n<p>\u0417\u043b\u043e\u0434\u0435\u044f\u043d\u0438\u0435 \u044d\u0442\u043e \u0431\u044b\u043b\u043e \u043d\u0430\u043c\u0435\u0440\u0435\u043d\u043d\u044b\u043c, \u044f \u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0431\u044f\u0437\u0430\u043d \u0431\u044b\u043b \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0430\u043c \u043a\u043e\u0435-\u043a\u0430\u043a\u0443\u044e \u0442\u0435\u0440\u043c\u0438\u043d\u043e\u043b\u043e\u0433\u0438\u044e. \u0422\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u043d\u043e \u0435\u0445\u0430\u0442\u044c \u0434\u0430\u043b\u044c\u0448\u0435.<\/p>\n<p>\u041f\u043b\u0430\u043d \u0443 \u043d\u0430\u0441 \u0431\u044b\u043b \u0442\u0430\u043a\u043e\u0439:<\/p>\n<ol>\n<li>\u0421\u0434\u0435\u043b\u0430\u0442\u044c \u0434\u0430\u0433<\/li>\n<li>\u041d\u0430\u0433\u0435\u043d\u0435\u0440\u0438\u0442\u044c \u0442\u0430\u0441\u043a\u0438<\/li>\n<li>\u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c, \u043a\u0430\u043a \u0432\u0441\u0451 \u043a\u0440\u0430\u0441\u0438\u0432\u043e<\/li>\n<li>\u041f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u0442\u044c \u0437\u0430\u043b\u0438\u0432\u043a\u0430\u043c \u043d\u043e\u043c\u0435\u0440\u0430 \u0441\u0435\u0441\u0441\u0438\u0439<\/li>\n<li>\u0417\u0430\u0431\u0440\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 SQL Server<\/li>\n<li>\u041f\u043e\u043b\u043e\u0436\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 Vertica<\/li>\n<li>\u0421\u043e\u0431\u0440\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443<\/li>\n<\/ol>\n<p>\u0418\u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u0432\u0441\u0451 \u044d\u0442\u043e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c, \u044f \u0441\u0434\u0435\u043b\u0430\u043b \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u043e\u0435 \u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043a \u043d\u0430\u0448\u0435\u043c\u0443 <code>docker-compose.yml<\/code>:<\/p>\n<p><b class=\"spoiler_title\">docker-compose.db.yml<\/b><\/p>\n<pre><code class=\"plaintext\">version: '3.4'\n\nx-mssql-base: &amp;mssql-base\n  image: mcr.microsoft.com\/mssql\/server:2017-CU21-ubuntu-16.04\n  restart: always\n  environment:\n    ACCEPT_EULA: Y\n    MSSQL_PID: Express\n    SA_PASSWORD: SayThanksToSatiaAt2020\n    MSSQL_MEMORY_LIMIT_MB: 1024\n\nservices:\n  dwh:\n    image: jbfavre\/vertica:9.2.0-7_ubuntu-16.04\n\n  mssql_0:\n    &lt;&lt;: *mssql-base\n\n  mssql_1:\n    &lt;&lt;: *mssql-base\n\n  mssql_2:\n    &lt;&lt;: *mssql-base\n\n  mssql_init:\n    image: mio101\/py3-sql-db-client-base\n    command: python3 .\/mssql_init.py\n    depends_on:\n      - mssql_0\n      - mssql_1\n      - mssql_2\n    environment:\n      SA_PASSWORD: SayThanksToSatiaAt2020\n    volumes:\n      - .\/mssql_init.py:\/mssql_init.py\n      - .\/dags\/commons\/datasources.py:\/commons\/datasources.py<\/code><\/pre>\n<p>\u0422\u0430\u043c \u043c\u044b \u043f\u043e\u0434\u043d\u0438\u043c\u0430\u0435\u043c:<\/p>\n<ul>\n<li>Vertica \u043a\u0430\u043a \u0445\u043e\u0441\u0442 <code>dwh<\/code> \u0441 \u0441\u0430\u043c\u044b\u043c\u0438 \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u043c\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438,<\/li>\n<li>\u0442\u0440\u0438 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 SQL Server,<\/li>\n<li>\u043d\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0431\u0430\u0437\u044b \u0432 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0445 \u043a\u043e\u0435-\u043a\u0430\u043a\u0438\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 (\u043d\u0438 \u0432 \u043a\u043e\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0435 \u0437\u0430\u0433\u043b\u044f\u0434\u044b\u0432\u0430\u0439\u0442\u0435 \u0432 <code>mssql_init.py<\/code>!)<\/li>\n<\/ul>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0432\u0441\u0451 \u0434\u043e\u0431\u0440\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0447\u0443\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u043e\u0439, \u0447\u0435\u043c \u0432 \u043f\u0440\u043e\u0448\u043b\u044b\u0439 \u0440\u0430\u0437, \u043a\u043e\u043c\u0430\u043d\u0434\u044b:<\/p>\n<pre><code class=\"bash\">$ docker-compose -f docker-compose.yml -f docker-compose.db.yml up --scale worker=3<\/code><\/pre>\n<p>\u0427\u0442\u043e \u043d\u0430\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043b \u043d\u0430\u0448 \u0447\u0443\u0434\u043e\u0440\u0430\u043d\u0434\u043e\u043c\u0430\u0439\u0437\u0435\u0440, \u043c\u043e\u0436\u043d\u043e, \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0432\u0448\u0438\u0441\u044c \u043f\u0443\u043d\u043a\u0442\u043e\u043c <code>Data Profiling\/Ad Hoc Query<\/code>:<\/p>\n<p><img decoding=\"async\" alt=\"Apache Airflow: \u0434\u0435\u043b\u0430\u0435\u043c ETL \u043f\u0440\u043e\u0449\u0435\" src=\"\/wp-content\/uploads\/2020\/07\/716bca6a4ad9d56c752f98b528f32fdb.png\" style=\"display:block;margin: 0 auto;\"><br \/>\n<em>\u0413\u043b\u0430\u0432\u043d\u043e\u0435, \u043d\u0435 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u044d\u0442\u043e \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0430\u043c<\/em><\/p>\n<p>\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 <strong>ETL-\u0441\u0435\u0441\u0441\u0438\u044f\u0445<\/strong> \u044f \u043d\u0435 \u0431\u0443\u0434\u0443, \u0442\u0430\u043c \u0432\u0441\u0451 \u0442\u0440\u0438\u0432\u0438\u0430\u043b\u044c\u043d\u043e: \u0434\u0435\u043b\u0430\u0435\u043c \u0431\u0430\u0437\u0443, \u0432 \u043d\u0435\u0439 \u0442\u0430\u0431\u043b\u0438\u0447\u043a\u0443, \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u043c \u0432\u0441\u0451 \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u043e\u043c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430, \u0438 \u0442\u0435\u043f\u0435\u0440\u044c \u0434\u0435\u043b\u0430\u0435\u043c \u0442\u0430\u043a:<\/p>\n<pre><code class=\"python\">with Session(task_name) as session:\n    print('Load', session.id, 'started')\n\n    # Load worflow\n    ...\n\n    session.successful = True\n    session.loaded_rows = 15<\/code><\/pre>\n<p><b class=\"spoiler_title\">session.py<\/b><\/p>\n<pre><code class=\"python\">from sys import stderr\n\nclass Session:\n    \"\"\"ETL workflow session\n\n    Example:\n        with Session(task_name) as session:\n            print(session.id)\n            session.successful = True\n            session.loaded_rows = 15\n            session.comment = 'Well done'\n    \"\"\"\n\n    def __init__(self, connection, task_name):\n        self.connection = connection\n        self.connection.autocommit = True\n\n        self._task_name = task_name\n        self._id = None\n\n        self.loaded_rows = None\n        self.successful = None\n        self.comment = None\n\n    def __enter__(self):\n        return self.open()\n\n    def __exit__(self, exc_type, exc_val, exc_tb):\n        if any(exc_type, exc_val, exc_tb):\n            self.successful = False\n            self.comment = f'{exc_type}: {exc_val}n{exc_tb}'\n            print(exc_type, exc_val, exc_tb, file=stderr)\n        self.close()\n\n    def __repr__(self):\n        return (f'&lt;{self.__class__.__name__} ' \n                f'id={self.id} ' \n                f'task_name=\"{self.task_name}\"&gt;')\n\n    @property\n    def task_name(self):\n        return self._task_name\n\n    @property\n    def id(self):\n        return self._id\n\n    def _execute(self, query, *args):\n        with self.connection.cursor() as cursor:\n            cursor.execute(query, args)\n            return cursor.fetchone()[0]\n\n    def _create(self):\n        query = \"\"\"\n            CREATE TABLE IF NOT EXISTS sessions (\n                id          SERIAL       NOT NULL PRIMARY KEY,\n                task_name   VARCHAR(200) NOT NULL,\n\n                started     TIMESTAMPTZ  NOT NULL DEFAULT current_timestamp,\n                finished    TIMESTAMPTZ           DEFAULT current_timestamp,\n                successful  BOOL,\n\n                loaded_rows INT,\n                comment     VARCHAR(500)\n            );\n            \"\"\"\n        self._execute(query)\n\n    def open(self):\n        query = \"\"\"\n            INSERT INTO sessions (task_name, finished)\n            VALUES (%s, NULL)\n            RETURNING id;\n            \"\"\"\n        self._id = self._execute(query, self.task_name)\n        print(self, 'opened')\n        return self\n\n    def close(self):\n        if not self._id:\n            raise SessionClosedError('Session is not open')\n        query = \"\"\"\n            UPDATE sessions\n            SET\n                finished    = DEFAULT,\n                successful  = %s,\n                loaded_rows = %s,\n                comment     = %s\n            WHERE\n                id = %s\n            RETURNING id;\n            \"\"\"\n        self._execute(query, self.successful, self.loaded_rows,\n                      self.comment, self.id)\n        print(self, 'closed',\n              ', successful: ', self.successful,\n              ', Loaded: ', self.loaded_rows,\n              ', comment:', self.comment)\n\nclass SessionError(Exception):\n    pass\n\nclass SessionClosedError(SessionError):\n    pass<\/code><\/pre>\n<p>\u041d\u0430\u0441\u0442\u0430\u043b\u0430 \u043f\u043e\u0440\u0430 <strong>\u0437\u0430\u0431\u0440\u0430\u0442\u044c \u043d\u0430\u0448\u0438 \u0434\u0430\u043d\u043d\u044b\u0435<\/strong> \u0438\u0437 \u043d\u0430\u0448\u0438\u0445 \u043f\u043e\u043b\u0443\u0442\u043e\u0440\u0430 \u0441\u043e\u0442\u0435\u043d \u0442\u0430\u0431\u043b\u0438\u0446. \u0421\u0434\u0435\u043b\u0430\u0435\u043c \u044d\u0442\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043e\u0447\u0435\u043d\u044c \u043d\u0435\u0437\u0430\u0442\u0435\u0439\u043b\u0438\u0432\u044b\u0445 \u0441\u0442\u0440\u043e\u0447\u0435\u043a:<\/p>\n<pre><code class=\"python\">source_conn = MsSqlHook(mssql_conn_id=src_conn_id, schema=src_schema).get_conn()\n\nquery = f\"\"\"\n    SELECT \n        id, start_time, end_time, type, data\n    FROM dbo.Orders\n    WHERE\n        CONVERT(DATE, start_time) = '{dt}'\n    \"\"\"\n\ndf = pd.read_sql_query(query, source_conn)<\/code><\/pre>\n<ol>\n<li>\u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0445\u0443\u043a\u0430 \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0438\u0437 Airflow <code>pymssql<\/code>-\u043a\u043e\u043d\u043d\u0435\u043a\u0442<\/li>\n<li>\u0412 \u0437\u0430\u043f\u0440\u043e\u0441 \u043f\u043e\u0434\u0441\u0442\u0430\u0432\u0438\u043c \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0432 \u0432\u0438\u0434\u0435 \u0434\u0430\u0442\u044b \u2014 \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0435\u0451 \u043f\u043e\u0434\u0431\u0440\u043e\u0441\u0438\u0442 \u0448\u0430\u0431\u043b\u043e\u043d\u0438\u0437\u0430\u0442\u043e\u0440.<\/li>\n<li>\u0421\u043a\u0430\u0440\u043c\u043b\u0438\u0432\u0430\u0435\u043c \u043d\u0430\u0448 \u0437\u0430\u043f\u0440\u043e\u0441 <code>pandas<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u043e\u0441\u0442\u0430\u043d\u0435\u0442 \u0434\u043b\u044f \u043d\u0430\u0441 <code>DataFrame<\/code> \u2014 \u043e\u043d \u043d\u0430\u043c \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c.<\/li>\n<\/ol>\n<blockquote><p>\u042f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u043f\u043e\u0434\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443 <code>{dt}<\/code> \u0432\u043c\u0435\u0441\u0442\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 <code>%s<\/code> \u043d\u0435 \u043f\u043e\u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u044f \u0437\u043b\u043e\u0431\u043d\u044b\u0439 \u0411\u0443\u0440\u0430\u0442\u0438\u043d\u043e, \u0430 \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e <code>pandas<\/code> \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u0432\u043b\u0430\u0434\u0430\u0442\u044c \u0441 <code>pymssql<\/code> \u0438 \u043f\u043e\u0434\u0441\u043e\u0432\u044b\u0432\u0430\u0435\u0442 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u043c\u0443 <code>params: List<\/code>, \u0445\u043e\u0442\u044f \u0442\u043e\u0442 \u043e\u0447\u0435\u043d\u044c \u0445\u043e\u0447\u0435\u0442 <code>tuple<\/code>.<br \/>\n\u0422\u0430\u043a\u0436\u0435 \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a <code>pymssql<\/code> \u0440\u0435\u0448\u0438\u043b \u0431\u043e\u043b\u044c\u0448\u0435 \u0435\u0433\u043e \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c, \u0438 \u0441\u0430\u043c\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u0441\u044a\u0435\u0445\u0430\u0442\u044c \u043d\u0430 <code>pyodbc<\/code>.<\/p><\/blockquote>\n<p>\u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u0447\u0435\u043c Airflow \u043d\u0430\u0448\u043f\u0438\u0433\u043e\u0432\u0430\u043b \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u043d\u0430\u0448\u0438\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439:<\/p>\n<p><img decoding=\"async\" alt=\"Apache Airflow: \u0434\u0435\u043b\u0430\u0435\u043c ETL \u043f\u0440\u043e\u0449\u0435\" src=\"\/wp-content\/uploads\/2020\/07\/ead5e4c795c913d929e169a09a930f8f.png\" style=\"display:block;margin: 0 auto;\"><\/p>\n<p>\u0415\u0441\u043b\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0435 \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c, \u0442\u043e \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0442\u044c \u0441\u043c\u044b\u0441\u043b\u0430 \u043d\u0435\u0442. \u041d\u043e \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u0437\u0430\u043b\u0438\u0432\u043a\u0443 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0439 \u0442\u043e\u0436\u0435 \u0441\u0442\u0440\u0430\u043d\u043d\u043e. \u041d\u043e \u044d\u0442\u043e \u0438 \u043d\u0435 \u043e\u0448\u0438\u0431\u043a\u0430. \u0410-\u0430-\u0430, \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c?! \u0410 \u0432\u043e\u0442 \u0447\u0442\u043e:<\/p>\n<pre><code class=\"python\">if df.empty:\n    raise AirflowSkipException('No rows to load')<\/code><\/pre>\n<p><code>AirflowSkipException<\/code> \u0441\u043a\u0430\u0436\u0435\u0442 Airflow, \u0447\u0442\u043e \u043e\u0448\u0438\u0431\u043a\u0438, \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043d\u0435\u0442, \u0430 \u0442\u0430\u0441\u043a \u043c\u044b \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u0435\u043c. \u0412 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435 \u0431\u0443\u0434\u0435\u0442 \u043d\u0435 \u0437\u0435\u043b\u0435\u043d\u044b\u0439 \u0438 \u043d\u0435 \u043a\u0440\u0430\u0441\u043d\u044b\u0439 \u043a\u0432\u0430\u0434\u0440\u0430\u0442\u0438\u043a, \u0430 \u0446\u0432\u0435\u0442\u0430 pink.<\/p>\n<p>\u041f\u043e\u0434\u0431\u0440\u043e\u0441\u0438\u043c \u043d\u0430\u0448\u0438\u043c \u0434\u0430\u043d\u043d\u044b\u043c <strong>\u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u043b\u043e\u043d\u043e\u043a<\/strong>:<\/p>\n<pre><code class=\"python\">df['etl_source'] = src_schema\ndf['etl_id'] = session.id\ndf['hash_id'] = hash_pandas_object(df[['etl_source', 'id']])<\/code><\/pre>\n<p>\u0410 \u0438\u043c\u0435\u043d\u043d\u043e:<\/p>\n<ul>\n<li>\u0411\u0414, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043c\u044b \u0437\u0430\u0431\u0440\u0430\u043b\u0438 \u0437\u0430\u043a\u0430\u0437\u044b,<\/li>\n<li>\u0418\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043d\u0430\u0448\u0435\u0439 \u0437\u0430\u043b\u0438\u0432\u0430\u044e\u0449\u0435\u0439 \u0441\u0435\u0441\u0441\u0438\u0438 (\u043e\u043d\u0430 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0437\u043d\u043e\u0439 <em>\u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u0442\u0430\u0441\u043a<\/em>),<\/li>\n<li>\u0425\u044d\u0448 \u043e\u0442 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430 \u0438 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u0430 \u0437\u0430\u043a\u0430\u0437\u0430 \u2014 \u0447\u0442\u043e\u0431\u044b \u0432 \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0439 \u0431\u0430\u0437\u0435 (\u0433\u0434\u0435 \u0432\u0441\u0451 \u0441\u0441\u044b\u043f\u0435\u0442\u0441\u044f \u0432 \u043e\u0434\u043d\u0443 \u0442\u0430\u0431\u043b\u0438\u0446\u0443) \u0443 \u043d\u0430\u0441 \u0431\u044b\u043b \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0437\u0430\u043a\u0430\u0437\u0430.<\/li>\n<\/ul>\n<p>\u041e\u0441\u0442\u0430\u043b\u0441\u044f \u043f\u0440\u0435\u0434\u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u0448\u0430\u0433: \u0437\u0430\u043b\u0438\u0442\u044c \u0432\u0441\u0451 \u0432 Vertica. \u0410, \u043a\u0430\u043a \u043d\u0438 \u0441\u0442\u0440\u0430\u043d\u043d\u043e, \u043e\u0434\u0438\u043d \u0438\u0437 \u0441\u0430\u043c\u044b\u0445 \u044d\u0444\u0444\u0435\u043a\u0442\u043d\u044b\u0445 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u0432 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u2014 \u0447\u0435\u0440\u0435\u0437 CSV!<\/p>\n<pre><code class=\"python\"># Export data to CSV buffer\nbuffer = StringIO()\ndf.to_csv(buffer,\n          index=False, sep='|', na_rep='NUL', quoting=csv.QUOTE_MINIMAL,\n          header=False, float_format='%.8f', doublequote=False, escapechar='\\')\nbuffer.seek(0)\n\n# Push CSV\ntarget_conn = VerticaHook(vertica_conn_id=target_conn_id).get_conn()\n\ncopy_stmt = f\"\"\"\n    COPY {target_table}({df.columns.to_list()}) \n    FROM STDIN \n    DELIMITER '|' \n    ENCLOSED '\"' \n    ABORT ON ERROR \n    NULL 'NUL'\n    \"\"\"\n\ncursor = target_conn.cursor()\ncursor.copy(copy_stmt, buffer)<\/code><\/pre>\n<ol>\n<li>\u041c\u044b \u0434\u0435\u043b\u0430\u0435\u043c \u0441\u043f\u0435\u0446\u043f\u0440\u0438\u0451\u043c\u043d\u0438\u043a <code>StringIO<\/code>.<\/li>\n<li><code>pandas<\/code> \u043b\u044e\u0431\u0435\u0437\u043d\u043e \u0441\u043b\u043e\u0436\u0438\u0442 \u0432 \u043d\u0435\u0433\u043e \u043d\u0430\u0448 <code>DataFrame<\/code> \u0432 \u0432\u0438\u0434\u0435 <code>CSV<\/code>-\u0441\u0442\u0440\u043e\u043a.<\/li>\n<li>\u041e\u0442\u043a\u0440\u043e\u0435\u043c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u043a \u043d\u0430\u0448\u0435\u0439 \u043b\u044e\u0431\u0438\u043c\u043e\u0439 Vertica \u0445\u0443\u043a\u043e\u043c.<\/li>\n<li>\u0410 \u0442\u0435\u043f\u0435\u0440\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>copy()<\/code> \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u043c \u043d\u0430\u0448\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u0440\u044f\u043c\u043e \u0432 \u0412\u0435\u0440\u0442\u0438\u043a\u0443!<\/li>\n<\/ol>\n<p>\u0418\u0437 \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430 \u0437\u0430\u0431\u0435\u0440\u0435\u043c, \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0442\u0440\u043e\u0447\u0435\u043a \u0437\u0430\u0441\u044b\u043f\u0430\u043b\u043e\u0441\u044c, \u0438 \u0441\u043a\u0430\u0436\u0435\u043c \u043c\u0435\u043d\u0435\u0434\u0436\u0435\u0440\u0443 \u0441\u0435\u0441\u0441\u0438\u0438, \u0447\u0442\u043e \u0432\u0441\u0451 \u041e\u041a:<\/p>\n<pre><code class=\"python\">session.loaded_rows = cursor.rowcount\nsession.successful = True<\/code><\/pre>\n<p>\u0412\u043e\u0442 \u0438 \u0432\u0441\u0451.<\/p>\n<blockquote><p>\u041d\u0430 \u043f\u0440\u043e\u0434\u0435 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0446\u0435\u043b\u0435\u0432\u0443\u044e \u0442\u0430\u0431\u043b\u0438\u0447\u043a\u0443 \u0432\u0440\u0443\u0447\u043d\u0443\u044e. \u0417\u0434\u0435\u0441\u044c \u0436\u0435 \u044f \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u043b \u0441\u0435\u0431\u0435 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0430\u0432\u0442\u043e\u043c\u0430\u0442:<\/p><\/blockquote>\n<pre><code class=\"python\">create_schema_query = f'CREATE SCHEMA IF NOT EXISTS {target_schema};'\ncreate_table_query = f\"\"\"\n    CREATE TABLE IF NOT EXISTS {target_schema}.{target_table} (\n         id         INT,\n         start_time TIMESTAMP,\n         end_time   TIMESTAMP,\n         type       INT,\n         data       VARCHAR(32),\n         etl_source VARCHAR(200),\n         etl_id     INT,\n         hash_id    INT PRIMARY KEY\n     );\"\"\"\n\ncreate_table = VerticaOperator(\n    task_id='create_target',\n    sql=[create_schema_query,\n         create_table_query],\n    vertica_conn_id=target_conn_id,\n    task_concurrency=1,\n    dag=dag)<\/code><\/pre>\n<blockquote><p>\u042f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>VerticaOperator()<\/code> \u0441\u043e\u0437\u0434\u0430\u044e \u0441\u0445\u0435\u043c\u0443 \u0411\u0414 \u0438 \u0442\u0430\u0431\u043b\u0438\u0446\u0443 (\u0435\u0441\u043b\u0438 \u0438\u0445 \u0435\u0449\u0435 \u043d\u0435\u0442, \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e). \u0413\u043b\u0430\u0432\u043d\u043e\u0435, \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0440\u0430\u0441\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438:<\/p><\/blockquote>\n<pre><code class=\"python\">for conn_id, schema in sql_server_ds:\n    load = PythonOperator(\n        task_id=schema,\n        python_callable=workflow,\n        op_kwargs={\n            'src_conn_id': conn_id,\n            'src_schema': schema,\n            'dt': '{{ ds }}',\n            'target_conn_id': target_conn_id,\n            'target_table': f'{target_schema}.{target_table}'},\n        dag=dag)\n\n    create_table &gt;&gt; load<\/code><\/pre>\n<h3 id=\"podvodim-itogi\">\u041f\u043e\u0434\u0432\u043e\u0434\u0438\u043c \u0438\u0442\u043e\u0433\u0438<\/h3>\n<blockquote><p>\u2014 \u041d\u0443 \u0432\u043e\u0442, \u2014 \u0441\u043a\u0430\u0437\u0430\u043b \u043c\u044b\u0448\u043e\u043d\u043e\u043a, \u2014 \u043d\u0435 \u043f\u0440\u0430\u0432\u0434\u0430 \u043b\u0438, \u0442\u0435\u043f\u0435\u0440\u044c<br \/>\n\u0422\u044b \u0443\u0431\u0435\u0434\u0438\u043b\u0441\u044f, \u0447\u0442\u043e \u0432 \u043b\u0435\u0441\u0443 \u044f \u0441\u0430\u043c\u044b\u0439 \u0441\u0442\u0440\u0430\u0448\u043d\u044b\u0439 \u0437\u0432\u0435\u0440\u044c?<\/p><\/blockquote>\n<p><em>\u0414\u0436\u0443\u043b\u0438\u044f \u0414\u043e\u043d\u0430\u043b\u044c\u0434\u0441\u043e\u043d, \u00ab\u0413\u0440\u0443\u0444\u0444\u0430\u043b\u043e\u00bb<\/em><\/p>\n<p>\u0414\u0443\u043c\u0430\u044e, \u0435\u0441\u043b\u0438 \u0431\u044b \u043c\u044b \u0441 \u043c\u043e\u0438\u043c\u0438 \u043a\u043e\u043b\u043b\u0435\u0433\u0430\u043c\u0438 \u0443\u0441\u0442\u0440\u043e\u0438\u043b\u0438 \u0441\u043e\u0440\u0435\u0432\u043d\u043e\u0432\u0430\u043d\u0438\u0435: \u043a\u0442\u043e \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u0441\u043e\u0441\u0442\u0430\u0432\u0438\u0442 \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442 \u0441 \u043d\u0443\u043b\u044f ETL-\u043f\u0440\u043e\u0446\u0435\u0441\u0441: \u043e\u043d\u0438 \u0441\u043e \u0441\u0432\u043e\u0438\u043c\u0438 SSIS \u0438 \u043c\u044b\u0448\u043a\u043e\u0439 \u0438 \u044f \u0441 Airflow\u2026 \u0410 \u043f\u043e\u0442\u043e\u043c \u0431\u044b \u043c\u044b \u0435\u0449\u0435 \u0441\u0440\u0430\u0432\u043d\u0438\u043b\u0438 \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u043e \u0441\u043e\u043f\u0440\u043e\u0432\u043e\u0436\u0434\u0435\u043d\u0438\u044f\u2026 \u0423\u0445, \u0434\u0443\u043c\u0430\u044e, \u0432\u044b \u0441\u043e\u0433\u043b\u0430\u0441\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u044f \u043e\u0431\u043e\u0439\u0434\u0443 \u0438\u0445 \u043f\u043e \u0432\u0441\u0435\u043c \u0444\u0440\u043e\u043d\u0442\u0430\u043c!<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0436\u0435 \u0447\u0443\u0442\u044c-\u0447\u0443\u0442\u044c \u043f\u043e\u0441\u0435\u0440\u044c\u0435\u0437\u043d\u0435\u0435, \u0442\u043e Apache Airflow \u2014 \u0437\u0430 \u0441\u0447\u0435\u0442 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0432 \u0432 \u0432\u0438\u0434\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u2014 \u0441\u0434\u0435\u043b\u0430\u043b \u043c\u043e\u044e \u0440\u0430\u0431\u043e\u0442\u0443 <strong>\u0433\u043e\u0440\u0430\u0437\u0434\u043e<\/strong> \u0443\u0434\u043e\u0431\u043d\u0435\u0435 \u0438 \u043f\u0440\u0438\u044f\u0442\u043d\u0435\u0435.<\/p>\n<p>\u0415\u0433\u043e \u0436\u0435 \u043d\u0435\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u0430\u044f \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0435\u043c\u043e\u0441\u0442\u044c: \u043a\u0430\u043a \u0432 \u043f\u043b\u0430\u043d\u0435 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432, \u0442\u0430\u043a \u0438 \u043f\u0440\u0435\u0434\u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u043a \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u043e\u0441\u0442\u0438 \u2014 \u0434\u0430\u0451\u0442 \u0432\u0430\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c Airflow \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432 \u043b\u044e\u0431\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438: \u0445\u043e\u0442\u044c \u0432 \u043f\u043e\u043b\u043d\u043e\u043c \u0446\u0438\u043a\u043b\u0435 \u0441\u0431\u043e\u0440\u0430, \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0438 \u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445, \u0445\u043e\u0442\u044c \u0432 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u0440\u0430\u043a\u0435\u0442 (\u043d\u0430 \u041c\u0430\u0440\u0441, \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0436\u0435).<\/p>\n<h2 id=\"chast-zaklyuchitelnaya-spravochno-informacionnaya\">\u0427\u0430\u0441\u0442\u044c \u0437\u0430\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f, \u0441\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u043e-\u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u043e\u043d\u043d\u0430\u044f<\/h2>\n<h3 id=\"grabli-kotorye-my-sobrali-za-vas\">\u0413\u0440\u0430\u0431\u043b\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u0441\u043e\u0431\u0440\u0430\u043b\u0438 \u0437\u0430 \u0432\u0430\u0441<\/h3>\n<ul>\n<li><strong><code>start_date<\/code><\/strong>. \u0414\u0430, \u044d\u0442\u043e \u0443\u0436\u0435 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u043c\u0435\u043c\u0430\u0441\u0438\u043a. \u0427\u0435\u0440\u0435\u0437 \u0433\u043b\u0430\u0432\u043d\u044b\u0439 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 \u0434\u0430\u0433\u0430 <code>start_date<\/code> \u043f\u0440\u043e\u0445\u043e\u0434\u044f\u0442 \u0432\u0441\u0435. \u041a\u0440\u0430\u0442\u043a\u043e, \u0435\u0441\u043b\u0438 \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0432 <code>start_date<\/code> \u0442\u0435\u043a\u0443\u0449\u0443\u044e \u0434\u0430\u0442\u0443, \u0430 \u0432 <code>schedule_interval<\/code> \u2014 \u043e\u0434\u0438\u043d \u0434\u0435\u043d\u044c, \u0442\u043e DAG \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0441\u044f \u0437\u0430\u0432\u0442\u0440\u0430 \u043d\u0435 \u0440\u0430\u043d\u044c\u0448\u0435.\n<pre><code class=\"python\">start_date = datetime(2020, 7, 7, 0, 1, 2)<\/code><\/pre>\n<p>\u0418 \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u043f\u0440\u043e\u0431\u043b\u0435\u043c.<\/p>\n<p>\u0421 \u043d\u0438\u043c \u0436\u0435 \u0441\u0432\u044f\u0437\u0430\u043d\u0430 \u0438 \u0435\u0449\u0435 \u043e\u0434\u043d\u0430 \u043e\u0448\u0438\u0431\u043a\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f: <code>Task is missing the start_date parameter<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0447\u0430\u0449\u0435 \u0432\u0441\u0435\u0433\u043e \u0433\u043e\u0432\u043e\u0440\u0438\u0442 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u0432\u044b \u0437\u0430\u0431\u044b\u043b\u0438 \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u0442\u044c \u043a \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0443 \u0434\u0430\u0433.<\/li>\n<li><strong>\u0412\u0441\u0451 \u043d\u0430 \u043e\u0434\u043d\u043e\u0439 \u043c\u0430\u0448\u0438\u043d\u0435.<\/strong> \u0414\u0430, \u0438 \u0431\u0430\u0437\u044b (\u0441\u0430\u043c\u043e\u0433\u043e Airflow \u0438 \u043d\u0430\u0448\u0435\u0439 \u043e\u0431\u043c\u0430\u0437\u043a\u0438), \u0438 \u0432\u0435\u0431-\u0441\u0435\u0440\u0432\u0435\u0440, \u0438 \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0449\u0438\u043a, \u0438 \u0432\u043e\u0440\u043a\u0435\u0440\u044b. \u0418 \u043e\u043d\u043e \u0434\u0430\u0436\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e. \u041d\u043e \u0441\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u0434\u0430\u0447 \u0443 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0440\u043e\u0441\u043b\u043e, \u0438 \u043a\u043e\u0433\u0434\u0430 PostgreSQL \u0441\u0442\u0430\u043b \u043e\u0442\u0434\u0430\u0432\u0430\u0442\u044c \u043e\u0442\u0432\u0435\u0442 \u043f\u043e \u0438\u043d\u0434\u0435\u043a\u0441\u0443 \u0437\u0430 20 \u0441 \u0432\u043c\u0435\u0441\u0442\u043e 5 \u043c\u0441, \u043c\u044b \u0435\u0433\u043e \u0432\u0437\u044f\u043b\u0438 \u0438 \u0443\u043d\u0435\u0441\u043b\u0438.<\/li>\n<li><strong>LocalExecutor.<\/strong> \u0414\u0430, \u043c\u044b \u0441\u0438\u0434\u0438\u043c \u043d\u0430 \u043d\u0451\u043c \u0434\u043e \u0441\u0438\u0445 \u043f\u043e\u0440, \u0438 \u043c\u044b \u0443\u0436\u0435 \u043f\u043e\u0434\u043e\u0448\u043b\u0438 \u043a \u043a\u0440\u0430\u044e \u043f\u0440\u043e\u043f\u0430\u0441\u0442\u0438. LocalExecutor\u2019\u0430 \u043d\u0430\u043c \u0434\u043e \u0441\u0438\u0445 \u043f\u043e\u0440 \u0445\u0432\u0430\u0442\u0430\u043b\u043e, \u043d\u043e \u0441\u0435\u0439\u0447\u0430\u0441 \u043f\u0440\u0438\u0448\u043b\u0430 \u043f\u043e\u0440\u0430 \u0440\u0430\u0441\u0448\u0438\u0440\u0438\u0442\u044c\u0441\u044f \u043c\u0438\u043d\u0438\u043c\u0443\u043c \u043e\u0434\u043d\u0438\u043c \u0432\u043e\u0440\u043a\u0435\u0440\u043e\u043c, \u0438 \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u043f\u043e\u0434\u043d\u0430\u043f\u0440\u044f\u0447\u044c\u0441\u044f, \u0447\u0442\u043e\u0431\u044b \u043f\u0435\u0440\u0435\u0435\u0445\u0430\u0442\u044c \u043d\u0430 CeleryExecutor. \u0410 \u0432\u0432\u0438\u0434\u0443 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0441 \u043d\u0438\u043c \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0438 \u043d\u0430 \u043e\u0434\u043d\u043e\u0439 \u043c\u0430\u0448\u0438\u043d\u043e\u0439, \u0442\u043e \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u043e\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f Celery \u0434\u0430\u0436\u0435 \u043d\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u00ab\u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u043f\u043e\u0439\u0434\u0435\u0442 \u0432 \u043f\u0440\u043e\u0434, \u0447\u0435\u0441\u0441\u043b\u043e\u0432\u043e!\u00bb<\/li>\n<li>\u041d\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 <strong>\u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0445 \u0441\u0440\u0435\u0434\u0441\u0442\u0432<\/strong>:\n<ul>\n<li><strong>Connections<\/strong> \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0443\u0447\u0435\u0442\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432,<\/li>\n<li><strong>SLA Misses<\/strong> \u0434\u043b\u044f \u0440\u0435\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0430 \u0442\u0430\u0441\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u043e\u0442\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 \u0432\u043e\u0432\u0440\u0435\u043c\u044f,<\/li>\n<li><strong>XCom<\/strong> \u0434\u043b\u044f \u043e\u0431\u043c\u0435\u043d\u0430 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u043c\u0438 (\u044f \u0441\u043a\u0430\u0437\u0430\u043b <strong>\u043c\u0435\u0442\u0430<\/strong>\u0434\u0430\u043d\u043d\u044b\u043c\u0438!) \u043c\u0435\u0436\u0434\u0443 \u0442\u0430\u0441\u043a\u0430\u043c\u0438 \u0434\u0430\u0433\u0430.<\/li>\n<\/ul>\n<\/li>\n<li>\u0417\u043b\u043e\u0443\u043f\u043e\u0442\u0440\u0435\u0431\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u043e\u0439. \u041d\u0443 \u0447\u0442\u043e \u0442\u0443\u0442 \u0441\u043a\u0430\u0437\u0430\u0442\u044c? \u0411\u044b\u043b\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u044b \u043e\u043f\u043e\u0432\u0435\u0449\u0435\u043d\u0438\u044f \u043d\u0430 \u0432\u0441\u0435 \u043f\u043e\u0432\u0442\u043e\u0440\u044b \u0443\u043f\u0430\u0432\u0448\u0438\u0445 \u0442\u0430\u0441\u043a\u043e\u0432. \u0422\u0435\u043f\u0435\u0440\u044c \u0432 \u043c\u043e\u0451\u043c \u0440\u0430\u0431\u043e\u0447\u0435\u043c Gmail &gt;90k \u043f\u0438\u0441\u0435\u043c \u043e\u0442 Airflow, \u0438 \u0432\u0435\u0431-\u043c\u043e\u0440\u0434\u0430 \u043f\u043e\u0447\u0442\u044b \u043e\u0442\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0431\u0440\u0430\u0442\u044c \u0438 \u0443\u0434\u0430\u043b\u044f\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0435 \u0447\u0435\u043c \u043f\u043e 100 \u0448\u0442\u0443\u043a \u0437\u0430 \u0440\u0430\u0437.<\/li>\n<\/ul>\n<blockquote><p>\u0411\u043e\u043b\u044c\u0448\u0435 \u043f\u043e\u0434\u0432\u043e\u0434\u043d\u044b\u0445 \u043a\u0430\u043c\u043d\u0435\u0439: <noindex><a rel=\"nofollow\" href=\"https:\/\/cwiki.apache.org\/confluence\/display\/AIRFLOW\/Common+Pitfalls\">Apache Airflow Pitfails<\/a><\/noindex><\/p><\/blockquote>\n<h3 id=\"sredstva-eschyo-bolshey-avtomatizacii\">\u0421\u0440\u0435\u0434\u0441\u0442\u0432\u0430 \u0435\u0449\u0451 \u0431\u043e\u043b\u044c\u0448\u0435\u0439 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438<\/h3>\n<p>\u0414\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u043c \u0435\u0449\u0435 \u0431\u043e\u043b\u044c\u0448\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0433\u043e\u043b\u043e\u0432\u043e\u0439, \u0430 \u043d\u0435 \u0440\u0443\u043a\u0430\u043c\u0438, Airflow \u0437\u0430\u0433\u043e\u0442\u043e\u0432\u0438\u043b\u0430 \u0434\u043b\u044f \u043d\u0430\u0441 \u0432\u043e\u0442 \u0447\u0442\u043e:<\/p>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/airflow.apache.org\/docs\/stable\/rest-api-ref.html\">REST API<\/a><\/noindex> \u2014 \u043e\u043d \u0434\u043e \u0441\u0438\u0445 \u043f\u043e\u0440 \u0438\u043c\u0435\u0435\u0442 \u0441\u0442\u0430\u0442\u0443\u0441 Experimental, \u0447\u0442\u043e \u043d\u0435 \u043c\u0435\u0448\u0430\u0435\u0442 \u0435\u043c\u0443 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c. \u0421 \u0435\u0433\u043e \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u043e\u0436\u043d\u043e \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0434\u0430\u0433\u0430\u0445 \u0438 \u0442\u0430\u0441\u043a\u0430\u0445, \u043d\u043e \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c\/\u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0434\u0430\u0433, \u0441\u043e\u0437\u0434\u0430\u0442\u044c DAG Run \u0438\u043b\u0438 \u043f\u0443\u043b.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/airflow.apache.org\/docs\/stable\/cli-ref.html\">CLI<\/a><\/noindex> \u2014 \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u043c\u043d\u043e\u0433\u0438\u0435 \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0435\u0443\u0434\u043e\u0431\u043d\u044b \u0432 \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u0438 \u0447\u0435\u0440\u0435\u0437 WebUI, \u0430 \u0432\u043e\u043e\u0431\u0449\u0435 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0442. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440:\n<ul>\n<li><code>backfill<\/code> \u043d\u0443\u0436\u0435\u043d \u0434\u043b\u044f \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u043e\u0432 \u0442\u0430\u0441\u043a\u043e\u0432.<br \/>\n\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u0440\u0438\u0448\u043b\u0438 \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0438, \u0433\u043e\u0432\u043e\u0440\u044f\u0442: \u00ab\u0410 \u0443 \u0432\u0430\u0441, \u0442\u043e\u0432\u0430\u0440\u0438\u0449, \u0435\u0440\u0443\u043d\u0434\u0430 \u0432 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441 1 \u043f\u043e 13 \u044f\u043d\u0432\u0430\u0440\u044f! \u0427\u0438\u043d\u0438-\u0447\u0438\u043d\u0438-\u0447\u0438\u043d\u0438-\u0447\u0438\u043d\u0438!\u00bb. \u0410 \u0442\u044b \u0442\u0430\u043a\u043e\u0439 \u0445\u043e\u0431\u0430:<\/p>\n<pre><code class=\"bash\">airflow backfill -s '2020-01-01' -e '2020-01-13' orders<\/code><\/pre>\n<\/li>\n<li>\u041e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u043d\u0438\u0435 \u0431\u0430\u0437\u044b: <code>initdb<\/code>, <code>resetdb<\/code>, <code>upgradedb<\/code>, <code>checkdb<\/code>.<\/li>\n<li><code>run<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043e\u0434\u0438\u043d \u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u0442\u0430\u0441\u043a\u0430, \u0434\u0430 \u0435\u0449\u0435 \u0438 \u0437\u0430\u0431\u0438\u0442\u044c \u043d\u0430 \u0432\u0441\u0451 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438. \u0411\u043e\u043b\u0435\u0435 \u0442\u043e\u0433\u043e, \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0435\u0433\u043e \u0447\u0435\u0440\u0435\u0437 <code>LocalExecutor<\/code>, \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u0443 \u0432\u0430\u0441 Celery-\u043a\u043b\u0430\u0441\u0442\u0435\u0440.<\/li>\n<li>\u041f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435 \u0434\u0435\u043b\u0430\u0435\u0442 <code>test<\/code>, \u0442\u043e\u043b\u044c\u043a\u043e \u0435\u0449\u0435 \u0438 \u0432 \u0431\u0430\u0437 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043f\u0438\u0448\u0435\u0442.<\/li>\n<li><code>connections<\/code> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043c\u0430\u0441\u0441\u043e\u0432\u043e \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0438\u0437 \u0448\u0435\u043b\u043b\u0430.<\/li>\n<\/ul>\n<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/airflow.apache.org\/docs\/stable\/_api\/index.html\">Python API<\/a><\/noindex> \u2014 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0445\u0430\u0440\u0434\u043a\u043e\u0440\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d \u0434\u043b\u044f \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432, \u0430 \u043d\u0435 \u043a\u043e\u043f\u043e\u0448\u0435\u043d\u0438\u044f \u0432 \u043d\u0451\u043c \u0440\u0443\u0447\u0451\u043d\u043a\u0430\u043c\u0438. \u041d\u043e \u043a\u0442\u043e \u0436 \u043d\u0430\u043c \u043f\u043e\u043c\u0435\u0448\u0430\u0435\u0442 \u043f\u043e\u0439\u0442\u0438 \u0432 <code>\/home\/airflow\/dags<\/code>, \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c <code>ipython<\/code> \u0438 \u043d\u0430\u0447\u0430\u0442\u044c \u0431\u0435\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u044c\u043d\u0438\u0447\u0430\u0442\u044c? \u041c\u043e\u0436\u043d\u043e, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0442\u0430\u043a\u043e\u043c \u043a\u043e\u0434\u043e\u043c:\n<pre><code class=\"python\">from airflow import settings\nfrom airflow.models import Connection\n\nfields = 'conn_id conn_type host port schema login password extra'.split()\n\nsession = settings.Session()\nfor conn in session.query(Connection).order_by(Connection.conn_id):\n  d = {field: getattr(conn, field) for field in fields}\n  print(conn.conn_id, '=', d)<\/code><\/pre>\n<\/li>\n<li>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043a \u0431\u0430\u0437\u0435 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445 Airflow. \u041f\u0438\u0441\u0430\u0442\u044c \u0432 \u043d\u0435\u0451 \u044f \u043d\u0435 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e, \u0430 \u0432\u043e\u0442 \u0434\u043e\u0441\u0442\u0430\u0432\u0430\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0442\u0430\u0441\u043a\u043e\u0432 \u0434\u043b\u044f \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043c\u0435\u0442\u0440\u0438\u043a \u043c\u043e\u0436\u043d\u043e \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u0438 \u043f\u0440\u043e\u0449\u0435, \u0447\u0435\u043c \u0447\u0435\u0440\u0435\u0437 \u043b\u044e\u0431\u043e\u0439 \u0438\u0437 API.\n<p>\u0421\u043a\u0430\u0436\u0435\u043c, \u0434\u0430\u043b\u0435\u043a\u043e \u043d\u0435 \u0432\u0441\u0435 \u043d\u0430\u0448\u0438 \u0442\u0430\u0441\u043a\u0438 \u0438\u0434\u0435\u043c\u043f\u043e\u0442\u0435\u043d\u0442\u043d\u044b, \u0430 \u043c\u043e\u0433\u0443\u0442 \u0438\u043d\u043e\u0433\u0434\u0430 \u043f\u0430\u0434\u0430\u0442\u044c \u0438 \u044d\u0442\u043e \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e. \u041d\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u0432\u0430\u043b\u043e\u0432 \u2014 \u044d\u0442\u043e \u0443\u0436\u0435 \u043f\u043e\u0434\u043e\u0437\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u043e, \u0438 \u043d\u0430\u0434\u043e \u0431\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c.<\/p>\n<p><b class=\"spoiler_title\">\u041e\u0441\u0442\u043e\u0440\u043e\u0436\u043d\u043e, SQL!<\/b><\/p>\n<pre><code class=\"sql\">WITH last_executions AS (\nSELECT\n    task_id,\n    dag_id,\n    execution_date,\n    state,\n        row_number()\n        OVER (\n            PARTITION BY task_id, dag_id\n            ORDER BY execution_date DESC) AS rn\nFROM public.task_instance\nWHERE\n    execution_date &gt; now() - INTERVAL '2' DAY\n),\nfailed AS (\n    SELECT\n        task_id,\n        dag_id,\n        execution_date,\n        state,\n        CASE WHEN rn = row_number() OVER (\n            PARTITION BY task_id, dag_id\n            ORDER BY execution_date DESC)\n                 THEN TRUE END AS last_fail_seq\n    FROM last_executions\n    WHERE\n        state IN ('failed', 'up_for_retry')\n)\nSELECT\n    task_id,\n    dag_id,\n    count(last_fail_seq)                       AS unsuccessful,\n    count(CASE WHEN last_fail_seq\n        AND state = 'failed' THEN 1 END)       AS failed,\n    count(CASE WHEN last_fail_seq\n        AND state = 'up_for_retry' THEN 1 END) AS up_for_retry\nFROM failed\nGROUP BY\n    task_id,\n    dag_id\nHAVING\n    count(last_fail_seq) &gt; 0<\/code><\/pre>\n<\/li>\n<\/ul>\n<h2 id=\"ssylki\">\u0421\u0441\u044b\u043b\u043a\u0438<\/h2>\n<p>\u041d\u0443 \u0438 \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043f\u0435\u0440\u0432\u044b\u0435 \u0434\u0435\u0441\u044f\u0442\u044c \u0441\u0441\u044b\u043b\u043e\u043a \u0438\u0437 \u0432\u044b\u0434\u0430\u0447\u0438 \u0433\u0443\u0433\u043b\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043f\u0430\u043f\u043a\u0438 Airflow \u0438\u0437 \u043c\u043e\u0438\u0445 \u0437\u0430\u043a\u043b\u0430\u0434\u043e\u043a.<\/p>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/airflow.apache.org\/docs\/stable\/\">Apache Airflow Documentation<\/a><\/noindex> \u2014 \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u043d\u0430\u0434\u043e \u043d\u0430\u0447\u0430\u0442\u044c \u0441 \u043e\u0444. \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438, \u043d\u043e \u043a\u0442\u043e \u0436\u0435 \u0447\u0438\u0442\u0430\u0435\u0442 \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438?<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/airflow.apache.org\/docs\/stable\/best-practices.html\">Best Practices<\/a><\/noindex> \u2014 \u043d\u0443 \u0445\u043e\u0442\u044f \u0431\u044b \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u0438 \u043e\u0442 \u0441\u043e\u0437\u0434\u0430\u0442\u0435\u043b\u0435\u0439 \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0439\u0442\u0435.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/www.astronomer.io\/guides\/airflow-ui\/\">The Airflow UI<\/a><\/noindex> \u2014 \u0441\u0430\u043c\u043e\u0435 \u043d\u0430\u0447\u0430\u043b\u043e: \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0432 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0430\u0445<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/medium.com\/@dustinstansbury\/understanding-apache-airflows-key-concepts-a96efed52b1a\">Understanding Apache Airflow\u2019s key concepts<\/a><\/noindex> \u2014 \u0445\u043e\u0440\u043e\u0448\u043e \u0440\u0430\u0441\u043f\u0438\u0441\u0430\u043d\u044b \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u043f\u043e\u043d\u044f\u0442\u0438\u044f, \u0435\u0441\u043b\u0438 (\u0432\u0434\u0440\u0443\u0433!) \u0432\u044b \u0447\u0442\u043e-\u0442\u043e \u043d\u0435 \u043f\u043e\u043d\u044f\u043b\u0438 \u0443 \u043c\u0435\u043d\u044f.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/stlong0521.github.io\/20161023%20-%20Airflow.html\">Tianlong&#8217;s Blog \u2014 A Guide On How To Build An Airflow Server\/Cluster<\/a><\/noindex> \u2014 \u043a\u0440\u0430\u0442\u043a\u0438\u0439 \u0433\u0430\u0439\u0434 \u043f\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0435 Airflow-\u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0430.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/eng.lyft.com\/running-apache-airflow-at-lyft-6e53bb8fccff\">Running Apache Airflow At Lyft<\/a><\/noindex> \u2014 \u043f\u043e\u0447\u0442\u0438 \u0442\u0430\u043a\u0430\u044f \u0436\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f, \u0440\u0430\u0437\u0432\u0435 \u0447\u0442\u043e \u0444\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u043c\u0430 \u043f\u043e\u0431\u043e\u043b\u044c\u0448\u0435, \u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432 \u043f\u043e\u043c\u0435\u043d\u044c\u0448\u0435.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/www.sicara.ai\/blog\/2019-04-08-apache-airflow-celery-workers\">How Apache Airflow Distributes Jobs on Celery workers<\/a><\/noindex> \u2014 \u043e \u0440\u0430\u0431\u043e\u0442\u0435 \u0432 \u0441\u0432\u044f\u0437\u043a\u0435 \u0441 Celery.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/www.astronomer.io\/guides\/dag-best-practices\/\">DAG Writing Best Practices in Apache Airflow<\/a><\/noindex> \u2014 \u043f\u0440\u043e \u0438\u0434\u0435\u043c\u043f\u043e\u0442\u0435\u043d\u0442\u043d\u043e\u0441\u0442\u044c \u0442\u0430\u0441\u043a\u043e\u0432, \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u043f\u043e ID \u0432\u043c\u0435\u0441\u0442\u043e \u0434\u0430\u0442\u044b, \u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438, \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0444\u0430\u0439\u043b\u043e\u0432 \u0438 \u043f\u0440\u043e\u0447\u0438\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0435 \u0432\u0435\u0449\u0438.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/www.astronomer.io\/guides\/managing-dependencies\/\">Managing Dependencies in Apache Airflow<\/a><\/noindex> \u2014 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0442\u0430\u0441\u043a\u043e\u0432 \u0438 Trigger Rule, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u044f \u0443\u043f\u043e\u043c\u044f\u043d\u0443\u043b \u043b\u0438\u0448\u044c \u0432\u0441\u043a\u043e\u043b\u044c\u0437\u044c.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/medium.com\/@hafizbadrie\/airflow-when-your-dag-is-far-behind-the-schedule-ea11bf02e44c\">Airflow: When Your DAG is Far Behind The Schedule<\/a><\/noindex> \u2014 \u043a\u0430\u043a \u043f\u0440\u0435\u043e\u0434\u043e\u043b\u0435\u0432\u0430\u0442\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u00ab\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043a\u0430\u043a \u0437\u0430\u0434\u0443\u043c\u0430\u043d\u043e\u00bb \u0443 \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u0430, \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u043f\u043e\u0442\u0435\u0440\u044f\u043d\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u0440\u0430\u0441\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u044b \u0442\u0430\u0441\u043a\u043e\u0432.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/www.astronomer.io\/guides\/airflow-queries\/\">Useful SQL queries for Apache Airflow<\/a><\/noindex> \u2014 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 SQL-\u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043a \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u043c Airflow.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/technofob.com\/2019\/05\/30\/get-started-developing-workflows-with-apache-airflow\/\">Get started developing workflows with Apache Airflow<\/a><\/noindex> \u2014 \u0435\u0441\u0442\u044c \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0439 \u0440\u0430\u0437\u0434\u0435\u043b \u043f\u0440\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u043e\u0433\u043e \u0441\u0435\u043d\u0441\u043e\u0440\u0430.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"http:\/\/bytepawn.com\/fetchr-airflow.html\">Building the Fetchr Data Science Infra on AWS with Presto and Airflow<\/a><\/noindex> \u2014 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0430\u044f \u043a\u043e\u0440\u043e\u0442\u043a\u0430\u044f \u0437\u0430\u043c\u0435\u0442\u043a\u0430 \u043e \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0438 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u043d\u0430 AWS \u0434\u043b\u044f Data Science.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/www.astronomer.io\/blog\/7-common-errors-to-check-when-debugging-airflow-dag\/\">7 Common Errors to Check when Debugging Airflow DAGs<\/a><\/noindex> \u2014 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u043d\u044b\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 (\u043a\u043e\u0433\u0434\u0430 \u043a\u043e\u0435-\u043a\u0442\u043e \u0432\u0441\u0451-\u0442\u0430\u043a\u0438 \u043d\u0435 \u0447\u0438\u0442\u0430\u0435\u0442 \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0439).<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/stackoverflow.com\/questions\/45280650\/store-and-access-password-using-apache-airflow\">Store and access password using Apache Airflow<\/a><\/noindex> \u2014 \u0443\u043b\u044b\u0431\u043d\u0438\u0442\u0435\u0441\u044c, \u043a\u0430\u043a \u043b\u044e\u0434\u0438 \u043a\u043e\u0441\u0442\u044b\u043b\u044f\u0442 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u043e\u043b\u0435\u0439, \u0445\u043e\u0442\u044f \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Connections.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/godatadriven.com\/blog\/the-zen-of-python-and-apache-airflow\/\">The Zen of Python and Apache Airflow<\/a><\/noindex> \u2014 \u043d\u0435\u044f\u0432\u043d\u044b\u0439 \u043f\u0440\u043e\u0431\u0440\u043e\u0441 DAG, \u0437\u0430\u0431\u0440\u043e\u0441 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0441\u043d\u043e\u0432\u0430 \u043f\u0440\u043e \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438, \u0430 \u0435\u0449\u0435 \u043f\u0440\u043e \u043f\u0440\u043e\u043f\u0443\u0441\u043a \u0437\u0430\u043f\u0443\u0441\u043a\u043e\u0432 \u0442\u0430\u0441\u043a\u043e\u0432.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/medium.com\/datareply\/airflow-lesser-known-tips-tricks-and-best-practises-cf4d4a90f8f\">Airflow: Lesser Known Tips, Tricks, and Best Practises<\/a><\/noindex> \u2014 \u043e\u0431 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 <code>default arguments<\/code> \u0438 <code>params<\/code> \u0432 \u0448\u0430\u0431\u043b\u043e\u043d\u0430\u0445, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043e Variables \u0438 Connections.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/www.astronomer.io\/blog\/profiling-the-airflow-scheduler\/\">Profiling the Airflow Scheduler<\/a><\/noindex> \u2014 \u0440\u0430\u0441\u0441\u043a\u0430\u0437 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0449\u0438\u043a \u0433\u043e\u0442\u043e\u0432\u044f\u0442 \u043a Airflow 2.0.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/medium.com\/@xnuinside\/quick-tutorial-apache-airflow-with-3-celery-workers-in-docker-composer-9f2f3b445e4\">Apache Airflow with 3 Celery workers in docker-compose<\/a><\/noindex> \u2014 \u043d\u0435\u043c\u043d\u043e\u0436\u043a\u043e \u0443\u0441\u0442\u0430\u0440\u0435\u0432\u0448\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u043f\u0440\u043e \u0434\u0435\u043f\u043b\u043e\u0439 \u043d\u0430\u0448\u0435\u0433\u043e \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0430 \u0432 <code>docker-compose<\/code>.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/livebook.manning.com\/book\/data-pipelines-with-apache-airflow\/chapter-4\/v-4\/36\">4 Templating Tasks Using the Airflow Context<\/a><\/noindex> \u2014 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0442\u0430\u0441\u043a \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0448\u0430\u0431\u043b\u043e\u043d\u043e\u0432 \u0438 \u043f\u0440\u043e\u0431\u0440\u043e\u0441\u0430 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/www.astronomer.io\/guides\/error-notifications-in-airflow\/\">Error Notifications in Airflow<\/a><\/noindex> \u2014 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 \u0438 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0435 \u043e\u043f\u043e\u0432\u0435\u0449\u0435\u043d\u0438\u044f \u043f\u043e\u0447\u0442\u043e\u0439 \u0438 Slack.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/mailru\/blog\/344398\/\">Airflow Workshop: \u0441\u043b\u043e\u0436\u043d\u044b\u0435 DAG\u2019\u0438 \u0431\u0435\u0437 \u043a\u043e\u0441\u0442\u044b\u043b\u0435\u0439<\/a><\/noindex> \u2014 \u0412\u0435\u0442\u0432\u043b\u0435\u043d\u0438\u044f \u0442\u0430\u0441\u043a\u043e\u0432, \u043c\u0430\u043a\u0440\u043e\u0441\u044b \u0438 XCom.<\/li>\n<\/ul>\n<p>\u0418 \u0441\u0441\u044b\u043b\u043a\u0438, \u0437\u0430\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0432 \u0441\u0442\u0430\u0442\u044c\u0435:<\/p>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/airflow.apache.org\/docs\/stable\/macros-ref.html\">Macros reference<\/a><\/noindex> \u2014 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u0448\u0430\u0431\u043b\u043e\u043d\u0430\u0445 \u043f\u043b\u0435\u0439\u0441\u0445\u043e\u043b\u0434\u0435\u0440\u044b.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/cwiki.apache.org\/confluence\/display\/AIRFLOW\/Common+Pitfalls\">Common Pitfalls \u2014 Airflow<\/a><\/noindex> \u2014 \u0420\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u043d\u044b\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0434\u0430\u0433\u043e\u0432.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/puckel\/docker-airflow\">puckel\/docker-airflow: Docker Apache Airflow<\/a><\/noindex> \u2014 <code>docker-compose<\/code> \u0434\u043b\u044f \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u043e\u0432, \u043e\u0442\u043b\u0430\u0434\u043a\u0438 \u0438 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/python-telegram-bot\/python-telegram-bot\">python-telegram-bot\/python-telegram-bot: We have made you a wrapper you can&#8217;t refuse<\/a><\/noindex> \u2014 Python-\u043e\u0431\u0435\u0440\u0442\u043a\u0430 \u0434\u043b\u044f Telegram REST API.<\/li>\n<\/ul>\n<p>\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/512386\/\">habr.com<\/a><\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u044f \u0414\u043c\u0438\u0442\u0440\u0438\u0439 \u041b\u043e\u0433\u0432\u0438\u043d\u0435\u043d\u043a\u043e \u2014 Data Engineer \u043e\u0442\u0434\u0435\u043b\u0430 \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0438 \u0433\u0440\u0443\u043f\u043f\u044b \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0439 \u00ab\u0412\u0435\u0437\u0451\u0442\u00bb. \u042f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u0432\u0430\u043c \u043e \u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u043c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0435 \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 ETL-\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0432 \u2014 Apache Airflow. \u041d\u043e Airflow \u043d\u0430\u0441\u0442\u043e\u043b\u044c\u043a\u043e \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u0435\u043d \u0438 \u043c\u043d\u043e\u0433\u043e\u0433\u0440\u0430\u043d\u0435\u043d, \u0447\u0442\u043e \u0432\u0430\u043c \u0441\u0442\u043e\u0438\u0442 \u043f\u0440\u0438\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c\u0441\u044f \u043a \u043d\u0435\u043c\u0443 \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u0432\u044b \u043d\u0435 \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442\u0435\u0441\u044c \u043f\u043e\u0442\u043e\u043a\u0430\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u0445, \u0430 \u0438\u043c\u0435\u0435\u0442\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u044c \u043f\u0435\u0440\u0438\u043e\u0434\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043a\u0430\u043a\u0438\u0435-\u043b\u0438\u0431\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u044b \u0438 \u0441\u043b\u0435\u0434\u0438\u0442\u044c \u0437\u0430 \u0438\u0445 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435\u043c. [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":90013,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-90012","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 4.9.10 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041f\u0440\u0438\u0432\u0435\u0442, \u044f \u0414\u043c\u0438\u0442\u0440\u0438\u0439 \u041b\u043e\u0433\u0432\u0438\u043d\u0435\u043d\u043a\u043e \u2014 Data Engineer \u043e\u0442\u0434\u0435\u043b\u0430 \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0438 \u0433\u0440\u0443\u043f\u043f\u044b \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0439 \u00ab\u0412\u0435\u0437\u0451\u0442\u00bb. \u042f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u0432\u0430\u043c \u043e \u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u043c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0435 \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 ETL-\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0432 \u2014 Apache Airflow. \u041d\u043e Airflow \u043d\u0430\u0441\u0442\u043e\u043b\u044c\u043a\u043e \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u0435\u043d \u0438 \u043c\u043d\u043e\u0433\u043e\u0433\u0440\u0430\u043d\u0435\u043d, \u0447\u0442\u043e \u0432\u0430\u043c \u0441\u0442\u043e\u0438\u0442 \u043f\u0440\u0438\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c\u0441\u044f \u043a \u043d\u0435\u043c\u0443 \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u0432\u044b \u043d\u0435 \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442\u0435\u0441\u044c \u043f\u043e\u0442\u043e\u043a\u0430\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u0445, \u0430 \u0438\u043c\u0435\u0435\u0442\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u044c \u043f\u0435\u0440\u0438\u043e\u0434\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043a\u0430\u043a\u0438\u0435-\u043b\u0438\u0431\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u044b \u0438 \u0441\u043b\u0435\u0434\u0438\u0442\u044c \u0437\u0430 \u0438\u0445 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435\u043c.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/apache-airflow-delaem-etl-proshhe\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 4.9.10\" \/>\n\t\t<meta property=\"og:locale\" content=\"it_IT\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47Apache Airflow: \u0434\u0435\u043b\u0430\u0435\u043c ETL \u043f\u0440\u043e\u0449\u0435 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041f\u0440\u0438\u0432\u0435\u0442, \u044f \u0414\u043c\u0438\u0442\u0440\u0438\u0439 \u041b\u043e\u0433\u0432\u0438\u043d\u0435\u043d\u043a\u043e \u2014 Data Engineer \u043e\u0442\u0434\u0435\u043b\u0430 \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0438 \u0433\u0440\u0443\u043f\u043f\u044b \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0439 \u00ab\u0412\u0435\u0437\u0451\u0442\u00bb. \u042f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u0432\u0430\u043c \u043e \u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u043c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0435 \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 ETL-\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0432 \u2014 Apache Airflow. \u041d\u043e Airflow \u043d\u0430\u0441\u0442\u043e\u043b\u044c\u043a\u043e \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u0435\u043d \u0438 \u043c\u043d\u043e\u0433\u043e\u0433\u0440\u0430\u043d\u0435\u043d, \u0447\u0442\u043e \u0432\u0430\u043c \u0441\u0442\u043e\u0438\u0442 \u043f\u0440\u0438\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c\u0441\u044f \u043a \u043d\u0435\u043c\u0443 \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u0432\u044b \u043d\u0435 \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442\u0435\u0441\u044c \u043f\u043e\u0442\u043e\u043a\u0430\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u0445, \u0430 \u0438\u043c\u0435\u0435\u0442\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u044c \u043f\u0435\u0440\u0438\u043e\u0434\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043a\u0430\u043a\u0438\u0435-\u043b\u0438\u0431\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u044b \u0438 \u0441\u043b\u0435\u0434\u0438\u0442\u044c \u0437\u0430 \u0438\u0445 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435\u043c.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/apache-airflow-delaem-etl-proshhe\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-07-28T11:42:19+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2021-02-15T16:59:36+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Apache Airflow: rendiamo l'ETL pi\u00f9 semplice | ProHoster","description":"Ciao, sono Dmitrij Logvinenko \u2014 Data Engineer nel dipartimento di analytics del gruppo di aziende 'Vezet'. Ti parler\u00f2 di un fantastico strumento per lo sviluppo di processi ETL \u2014 Apache Airflow. Ma Airflow \u00e8 cos\u00ec versatile e sfaccettato che dovresti prestargli attenzione anche se non ti occupi di flussi di dati, ma hai bisogno di avviare periodicamente alcuni processi e monitorarne l'esecuzione.","canonical_url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/apache-airflow-delaem-etl-proshhe","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"it_IT","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47Apache Airflow: \u0434\u0435\u043b\u0430\u0435\u043c ETL \u043f\u0440\u043e\u0449\u0435 | ProHoster","og:description":"\u041f\u0440\u0438\u0432\u0435\u0442, \u044f \u0414\u043c\u0438\u0442\u0440\u0438\u0439 \u041b\u043e\u0433\u0432\u0438\u043d\u0435\u043d\u043a\u043e \u2014 Data Engineer \u043e\u0442\u0434\u0435\u043b\u0430 \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0438 \u0433\u0440\u0443\u043f\u043f\u044b \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0439 \u00ab\u0412\u0435\u0437\u0451\u0442\u00bb. \u042f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u0432\u0430\u043c \u043e \u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u043c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0435 \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 ETL-\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0432 \u2014 Apache Airflow. \u041d\u043e Airflow \u043d\u0430\u0441\u0442\u043e\u043b\u044c\u043a\u043e \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u0435\u043d \u0438 \u043c\u043d\u043e\u0433\u043e\u0433\u0440\u0430\u043d\u0435\u043d, \u0447\u0442\u043e \u0432\u0430\u043c \u0441\u0442\u043e\u0438\u0442 \u043f\u0440\u0438\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c\u0441\u044f \u043a \u043d\u0435\u043c\u0443 \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u0432\u044b \u043d\u0435 \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442\u0435\u0441\u044c \u043f\u043e\u0442\u043e\u043a\u0430\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u0445, \u0430 \u0438\u043c\u0435\u0435\u0442\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u044c \u043f\u0435\u0440\u0438\u043e\u0434\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043a\u0430\u043a\u0438\u0435-\u043b\u0438\u0431\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u044b \u0438 \u0441\u043b\u0435\u0434\u0438\u0442\u044c \u0437\u0430 \u0438\u0445 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435\u043c.","og:url":"https:\/\/prohoster.info\/it\/blog\/administrirovanie\/apache-airflow-delaem-etl-proshhe","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-07-28T11:42:19+00:00","article:modified_time":"2021-02-15T16:59:36+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"90012","title":null,"description":"","keywords":"","keyphrases":null,"primary_term":null,"canonical_url":"","og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 13:00:30","updated":"2022-09-27 15:09:44"},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/90012","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/comments?post=90012"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/90012\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media\/90013"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media?parent=90012"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/categories?post=90012"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/tags?post=90012"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}