{"id":336900,"date":"2022-08-11T15:00:16","date_gmt":"2022-08-11T15:00:16","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=336900"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=336900","title":{"rendered":"<span>\u0421\u043e\u0437\u0434\u0430\u0451\u043c \u0441\u0432\u043e\u0451 \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u043e\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u0437\u0430 \u0447\u0430c<\/span>"},"content":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/webt\/be\/jx\/jh\/bejxjhzohyztvgjokq8tjuwwcdy.jpeg\" data-src=\"https:\/\/habrastorage.org\/webt\/be\/jx\/jh\/bejxjhzohyztvgjokq8tjuwwcdy.jpeg\" data-blurred=\"true\"\/><\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u0438\u0432\u0435\u0442! \u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0410\u0440\u0442\u0435\u043c \u0413\u0430\u0432\u0440\u0438\u043b\u043e\u0432 \u0438 \u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e \u0432 Tarantool. \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443, \u043a\u0430\u043a \u0431\u044b\u0441\u0442\u0440\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u043e\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b in-memory \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439 <a href=\"https:\/\/www.Tarantool.io\/ru\/\">Tarantool<\/a> \u0438 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u043e\u0439 \u0444\u0430\u0439\u043b\u043e\u0432\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b <a href=\"https:\/\/ru.wikipedia.org\/wiki\/IPFS\">IPFS<\/a> (InterPlanetary File System). <\/p>\n<p>  <\/p>\n<p>\u041c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043f\u0440\u0438\u043c\u0435\u0440 \u0448\u0430\u0440\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Tarantool \u0438 \u0441\u0434\u0435\u043b\u0430\u0435\u043c MVP \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u043e\u0433\u043e \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0441 \u043e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u044c\u044e \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u0426\u041e\u0414\u0430, \u0432 \u0442\u043e \u0432\u0440\u0435\u043c\u044f \u043a\u0430\u043a \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0441\u0442\u044b\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u0432.<\/p>\n<p>  <\/p>\n<p>\u0422\u0435\u043c, \u043a\u0442\u043e \u0437\u043d\u0430\u043a\u043e\u043c \u0441 IPFS, \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e, \u0431\u0443\u0434\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e \u0447\u0438\u0442\u0430\u0442\u044c \u043d\u0430\u0447\u0438\u043d\u0430\u044f \u0441 \u0440\u0430\u0437\u0434\u0435\u043b\u0430 \u00ab<em>\u0421 \u0447\u0435\u043c \u043c\u044b \u0441\u0442\u043e\u043b\u043a\u043d\u0451\u043c\u0441\u044f<\/em>\u00bb.<\/p>\n<p><a name=\"habracut\"><\/a>  <\/p>\n<h3 id=\"ipfs--eto-voobsche-chto\">IPFS \u2014 \u044d\u0442\u043e \u0432\u043e\u043e\u0431\u0449\u0435 \u0447\u0442\u043e?<\/h3>\n<p>  <\/p>\n<p>\u0415\u0441\u043b\u0438 \u043a\u0440\u0430\u0442\u043a\u043e, IPFS (\u043e\u0442 \u0430\u043d\u0433\u043b. InterPlanetary File System) \u2014 \u044d\u0442\u043e \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u043e\u0435 \u0444\u0430\u0439\u043b\u043e\u0432\u043e\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435. \u041e\u043d\u043e \u043e\u0431\u043b\u0430\u0434\u0430\u0435\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u0445\u0430\u0440\u0430\u043a\u0442\u0435\u0440\u043d\u044b\u043c\u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430\u043c\u0438:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u0414\u043e\u0441\u0442\u0443\u043f \u043a \u0434\u0430\u043d\u043d\u044b\u043c \u043f\u043e \u0438\u0445 \u0445\u0435\u0448\u0443.<\/li>\n<li>\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0438 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0444\u0430\u0439\u043b\u0430\u043c \u0447\u0435\u0440\u0435\u0437 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b HTTP.<\/li>\n<li>\u0412\u0441\u0435 \u0444\u0430\u0439\u043b\u044b \u043d\u0430 \u043d\u043e\u0434\u0435 \u0434\u0435\u043b\u044f\u0442\u0441\u044f \u043d\u0430 \u0437\u0430\u043a\u0440\u0435\u043f\u043b\u0451\u043d\u043d\u044b\u0435 (pinned) \u0438 \u043d\u0435\u0437\u0430\u043a\u0440\u0435\u043f\u043b\u0451\u043d\u043d\u044b\u0435. \u0420\u0430\u0437\u043b\u0438\u0447\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 \u043d\u0438\u043c\u0438 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043f\u0435\u0440\u0432\u044b\u0435 \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u0443\u0434\u0430\u043b\u044f\u044e\u0442\u0441\u044f \u0438\u0437 \u043d\u043e\u0434\u044b. \u041f\u043e-\u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u043c\u0443 \u043d\u043e\u0434\u0430 \u0445\u0440\u0430\u043d\u0438\u0442 \u0438\u043c\u0435\u043d\u043d\u043e \u0437\u0430\u043a\u0440\u0435\u043f\u043b\u0451\u043d\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b, \u0430 \u0432\u0441\u0435 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u2014 \u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u043a\u0435\u0448 \u043d\u0430 \u0434\u0438\u0441\u043a\u0435.<br \/>  \u041f\u0440\u0438 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0438 \u0444\u0430\u0439\u043b\u0430 \u043d\u0430 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u043d\u043e\u0434\u0435 IPFS \u0441\u043a\u0430\u0447\u0430\u0435\u0442 \u0435\u0433\u043e \u0441 \u0434\u0440\u0443\u0433\u043e\u0439. \u0417\u0430\u043a\u0440\u0435\u043f\u043b\u0435\u043d\u0438\u0435 \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u0447\u0435\u0440\u0435\u0437 API.<\/li>\n<li>\u0415\u0441\u043b\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u0443 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0444\u0430\u0439\u043b, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430 \u043d\u0451\u043c \u043d\u0435 \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f, \u0442\u043e \u0441\u0435\u0440\u0432\u0435\u0440 \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u043a\u0430\u0447\u0430\u0435\u0442 \u0435\u0433\u043e \u043a\u0430\u043a \u043d\u0435\u0437\u0430\u043a\u0440\u0435\u043f\u043b\u0451\u043d\u043d\u044b\u0439, \u0430 \u043f\u043e\u0442\u043e\u043c \u043e\u0442\u0434\u0430\u0441\u0442 \u043f\u043e HTTP. \u0410 \u0435\u0441\u043b\u0438 \u0435\u043c\u0443 \u043d\u0435 \u0445\u0432\u0430\u0442\u0438\u0442 \u043c\u0435\u0441\u0442\u0430, \u0442\u043e \u0432\u044b\u0442\u0435\u0441\u043d\u0438\u0442 \u043e\u0434\u0438\u043d \u0438\u0437 \u043d\u0435\u0437\u0430\u043a\u0440\u0435\u043f\u043b\u0451\u043d\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432.<\/li>\n<li>\u0425\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u043e, \u0432\u0441\u0435 \u043d\u043e\u0434\u044b \u0441\u0432\u044f\u0437\u0430\u043d\u044b \u0438 \u043e\u0431\u0440\u0430\u0437\u0443\u044e\u0442 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0442\u0435\u0440. \u041e\u0434\u043d\u0430\u043a\u043e \u0434\u0430\u043d\u043d\u044b\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0438\u043a\u0442\u043e \u043d\u0435 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442, \u043f\u043e \u043b\u043e\u0433\u0438\u043a\u0435 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0433\u043e \u043f\u0443\u043d\u043a\u0442\u0430 \u0441\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c \u0443\u0439\u0434\u0443\u0442 \u0438\u0437 \u0432\u0441\u0435\u0445 \u043d\u043e\u0434 \u0438 \u043d\u0430\u0432\u0441\u0435\u0433\u0434\u0430 \u043f\u043e\u0442\u0435\u0440\u044f\u044e\u0442\u0441\u044f. <\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043a\u0430\u0436\u0434\u0430\u044f \u043d\u043e\u0434\u0430 IPFS \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u0440\u0430\u0437\u0443 \u0448\u043b\u044e\u0437\u043e\u043c \u0432 HTTP, \u043a\u0435\u0448\u0435\u043c \u0438 \u0445\u043e\u043b\u043e\u0434\u043d\u044b\u043c \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435\u043c. \u0418\u0437 \u044d\u0442\u043e\u0433\u043e \u0441\u043b\u0435\u0434\u0443\u0435\u0442, \u0447\u0442\u043e \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0441\u0430\u043c\u0430 \u043c\u043e\u0436\u0435\u0442 \u043f\u0435\u0440\u0435\u043d\u043e\u0441\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043c\u0435\u0436\u0434\u0443 \u043d\u043e\u0434\u0430\u043c\u0438. \u041d\u043e IPFS \u043d\u0443\u0436\u043d\u0430 \u043f\u043e\u043c\u043e\u0449\u044c \u0432 \u0432\u044b\u0431\u043e\u0440\u0435 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u0445\u043e\u043b\u043e\u0434\u043d\u043e\u0433\u043e \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f. \u0422\u0430\u043a\u0436\u0435 \u043a\u0440\u0430\u0439\u043d\u0435 \u0436\u0435\u043b\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0432\u0441\u0435\u0433\u0434\u0430 \u043e\u0431\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0443, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0437\u0430\u043a\u0440\u0435\u043f\u043b\u0451\u043d \u043d\u0443\u0436\u043d\u044b\u0439 \u0444\u0430\u0439\u043b.<\/p>\n<p>  <\/p>\n<h3 id=\"pochemu-my-vybrali-ipfs\">\u041f\u043e\u0447\u0435\u043c\u0443 \u043c\u044b \u0432\u044b\u0431\u0440\u0430\u043b\u0438 IPFS?<\/h3>\n<p>  <\/p>\n<p>\u041d\u0430 \u0442\u043e \u0435\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438\u0447\u0438\u043d. <\/p>\n<p>  <\/p>\n<ol>\n<li>IPFS \u2014 \u0437\u0430\u043a\u043e\u043d\u0447\u0435\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0434\u0443\u043a\u0442, \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u043e\u0431\u044a\u0451\u043c\u044b \u0434\u0430\u043d\u043d\u044b\u0445. <\/li>\n<li>IPFS \u0448\u0438\u0440\u043e\u043a\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u0432 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0441\u0444\u0435\u0440\u0430\u0445. \u0422\u0430\u043a, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043e\u043d \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043a\u0440\u0438\u043f\u0442\u043e\u0432\u0430\u043b\u044e\u0442\u043e\u0439 Ethereum \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 NFT \u0442\u043e\u043a\u0435\u043d\u043e\u0432: \u0432 \u0431\u043b\u043e\u043a\u0447\u0435\u0439\u043d\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u044e\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e 256 \u0431\u0438\u0442 \u0445\u0435\u0448\u0430 \u0444\u0430\u0439\u043b\u0430, \u0430 \u0441\u0430\u043c \u0444\u0430\u0439\u043b \u043f\u0443\u0431\u043b\u0438\u043a\u0443\u0435\u0442\u0441\u044f \u0432 IPFS, \u043d\u0435 \u0437\u0430\u043d\u0438\u043c\u0430\u044f \u043c\u0435\u0441\u0442\u043e \u0432 \u0431\u043b\u043e\u043a\u0447\u0435\u0439\u043d\u0435. <\/li>\n<li>\u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043a\u0440\u0443\u043f\u043d\u044b\u0435 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u044b, \u0434\u043b\u044f \u043a\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0432\u043e\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 (\u0438\u043b\u0438 \u0434\u043b\u044f \u043e\u0431\u0445\u043e\u0434\u0430 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043e\u043a). \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <a href=\"https:\/\/developers.cloudflare.com\/distributed-web\/ipfs-gateway\/\">Cloudflare<\/a>. <\/li>\n<li>IPFS \u0442\u0430\u043a\u0436\u0435 \u0443\u0441\u0442\u0440\u0430\u043d\u044f\u0435\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438. \u0412 \u0447\u0430\u0441\u0442\u043d\u043e\u0441\u0442\u0438, \u0430\u0434\u0440\u0435\u0441\u0430\u0446\u0438\u044f \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0433\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0438 \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u0445\u0435\u0448\u0438 \u0432 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u0431\u0435\u0437 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u044f.<\/li>\n<\/ol>\n<p>  <\/p>\n<p>\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435 \u043f\u0440\u043e \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430 IPFS <a href=\"https:\/\/habr.com\/ru\/post\/268275\/\">\u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0437\u0434\u0435\u0441\u044c<\/a>.<\/p>\n<p>  <\/p>\n<h3 id=\"pri-chyom-tut-tarantool\">\u041f\u0440\u0438 \u0447\u0451\u043c \u0442\u0443\u0442 Tarantool?<\/h3>\n<p>  <\/p>\n<p>\u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Tarantool (\u0442\u043e\u0447\u043d\u0435\u0435, Tarantool Cartridge) \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0448\u0430\u0440\u0434\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u0438\u0441\u043a\u0430\u0442\u044c IPFS-\u043d\u043e\u0434\u044b, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u044d\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u044b.<\/p>\n<p>  <\/p>\n<p>Tarantool \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f \u044d\u0442\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0438, \u0442\u0430\u043a \u043a\u0430\u043a:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u0423 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b \u0435\u0441\u0442\u044c \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0448\u0430\u0440\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f (vshard), \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u0432\u043e\u044e \u043b\u043e\u0433\u0438\u043a\u0443.<\/li>\n<li>Tarantool \u043c\u043e\u0436\u0435\u0442 \u043e\u0431\u0449\u0430\u0442\u044c\u0441\u044f \u043f\u043e HTTP \u0441 IPFS.<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430 Tarantool \u2014 \u044d\u0442\u043e \u0431\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u043e \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439, \u0447\u0442\u043e \u0442\u0430\u043a\u0436\u0435 \u0441\u0438\u043b\u044c\u043d\u043e \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e.<\/p>\n<p>  <\/p>\n<h3 id=\"pochemu-ne-ipfs-cluster\">\u041f\u043e\u0447\u0435\u043c\u0443 \u043d\u0435 IPFS Cluster?<\/h3>\n<p>  <\/p>\n<p>\u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u043d\u0430\u0442\u0438\u0432\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 IPFS Cluster, \u043e\u0434\u043d\u0430\u043a\u043e \u0443 \u043d\u0435\u0433\u043e \u0435\u0441\u0442\u044c \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u0438. \u041e\u043d \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u0447\u0438\u0442\u0430\u0435\u0442 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043a\u043e\u043f\u0438\u0439 \u0437\u0430\u043a\u0440\u0435\u043f\u043b\u0451\u043d\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445, \u0430 \u043d\u0435 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u0438\u0445 \u043f\u043e \u043d\u0430\u0431\u043e\u0440\u0430\u043c \u043c\u0435\u0442\u0440\u0438\u043a, \u043a\u0430\u043a \u0442\u0438\u043f\u043e\u0432\u043e\u0439 \u043c\u043e\u0434\u0443\u043b\u044c \u0448\u0430\u0440\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f Tarantool vshard. \u042d\u0442\u043e \u0432\u043b\u0438\u044f\u0435\u0442 \u043d\u0430 \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u043e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u0438: \u0435\u0441\u043b\u0438 \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c \u043d\u0430\u0431\u043e\u0440 \u0440\u0435\u043f\u043b\u0438\u043a \u0438\u0437 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u0432 \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u0426\u041e\u0414\u0430\u0445, \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u043e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u0438 \u0434\u0430\u0436\u0435 \u043f\u0440\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0435 \u0441 \u043e\u0434\u043d\u0438\u043c \u0438\u0437 \u0426\u041e\u0414\u043e\u0432 (<a href=\"https:\/\/habr.com\/ru\/news\/t\/546264\/\">\u0430 \u0442\u0430\u043a\u0438\u0435 \u0431\u044b\u0432\u0430\u044e\u0442<\/a>). \u041f\u043e\u043c\u0438\u043c\u043e \u043f\u0440\u043e\u0447\u0435\u0433\u043e, IPFS-\u043a\u043b\u0430\u0441\u0442\u0435\u0440 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0435\u0442 \u043d\u0430\u0441 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435\u043c \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u044b\u043c\u0438 \u0438\u043d\u0434\u0435\u043a\u0441\u0430\u043c\u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e \u0445\u0435\u0448\u0443.<\/p>\n<p>  <\/p>\n<h3 id=\"s-chem-my-stolknyomsya-problems\">\u0421 \u0447\u0435\u043c \u043c\u044b \u0441\u0442\u043e\u043b\u043a\u043d\u0451\u043c\u0441\u044f? <\/h3>\n<p>  <\/p>\n<p><strong>\u0414\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438<\/strong><br \/>  \u0420\u0430\u0431\u043e\u0442\u0430 \u0441 \u0431\u043e\u043b\u044c\u0448\u0438\u043c\u0438 \u0444\u0430\u0439\u043b\u0430\u043c\u0438 \u2014 \u0432\u0441\u0435\u0433\u0434\u0430 \u0434\u043e\u043b\u0433\u0430\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u044b \u0442\u0430\u043a\u0436\u0435 \u043d\u0430\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u044e\u0442 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435: \u043e\u043d\u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043e\u0434\u043d\u043e\u0439 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438 \u0438 \u043a\u0430\u043a \u0441\u043b\u0435\u0434\u0441\u0442\u0432\u0438\u0435 \u043d\u0435 \u043c\u043e\u0433\u0443\u0442 \u0434\u0435\u043b\u0430\u0442\u044c \u0441\u0435\u0442\u0435\u0432\u044b\u0435 \u0432\u044b\u0437\u043e\u0432\u044b. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0430\u0434\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0435\u0434\u0443\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435.<\/p>\n<p>  <\/p>\n<p>\u0410\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u0430\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u043e\u0447\u0435\u0440\u0435\u0434\u044f\u043c\u0438, \u0438 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 <a href=\"https:\/\/github.com\/Tarantool\/queue\">Tarantool-queue<\/a>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0437\u0430\u0432\u043e\u0434\u0438\u0442\u044c \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0435 (\u043d\u0435 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0435) \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u0437\u0430\u0434\u0430\u0447.<\/p>\n<p>  <\/p>\n<p><strong>\u0411\u043e\u043b\u044c\u0448\u043e\u0439 \u043e\u0431\u044a\u0451\u043c \u0442\u0440\u0430\u0444\u0438\u043a\u0430<\/strong><\/p>\n<p>  <\/p>\n<p>\u041d\u0430\u0434\u043e \u0431\u0443\u0434\u0435\u0442 \u043e\u0447\u0435\u043d\u044c \u0430\u043a\u043a\u0443\u0440\u0430\u0442\u043d\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f HTTP, \u043d\u0435 \u0447\u0438\u0442\u0430\u044f \u043b\u0438\u0448\u043d\u0438\u0439 \u0440\u0430\u0437 \u0442\u0435\u043b\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0438 \u0430\u043a\u0442\u0438\u0432\u043d\u043e \u043f\u043e\u043b\u044c\u0437\u0443\u044f\u0441\u044c \u0440\u0435\u0434\u0438\u0440\u0435\u043a\u0442\u0430\u043c\u0438.<\/p>\n<p>  <\/p>\n<p><strong>\u0421\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u0439 API, \u043f\u043e\u0434 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u0434\u043e \u043f\u043e\u0434\u0441\u0442\u0440\u043e\u0438\u0442\u044c\u0441\u044f<\/strong><\/p>\n<p>  <\/p>\n<p>IPFS \u2014 \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u0434\u0443\u043a\u0442, \u043c\u0435\u043d\u044f\u0442\u044c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u044b \u043d\u0435 \u043c\u043e\u0436\u0435\u043c. \u042d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043d\u0430\u0448\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044f\u043c\u0438 \u0435\u0433\u043e API.<\/p>\n<p>  <\/p>\n<h2 id=\"bazovaya-koncepciya-resheniya\">\u0411\u0430\u0437\u043e\u0432\u0430\u044f \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f<\/h2>\n<p>  <\/p>\n<p>\u041c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u0440\u0438\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u0442\u0430\u043a\u043e\u0439 \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u0438:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u0420\u0430\u0437\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u043c \u0440\u044f\u0434\u043e\u043c \u0441 \u043a\u0430\u0436\u0434\u044b\u043c \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435\u043c Tarantool \u043d\u043e\u0434\u0443 IPFS.<\/li>\n<li>\u0423\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c IPFS-\u043d\u043e\u0434\u043e\u0439 \u0442\u043e\u043b\u044c\u043a\u043e \u0441 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430.<\/li>\n<li>\u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u043d\u0430 IPFS-\u043d\u043e\u0434\u0435 \u043b\u0435\u0436\u0430\u0442 \u0442\u0435 \u0436\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b, \u0447\u0442\u043e \u0438 \u0432 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u043c \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435.<\/li>\n<li>\u0417\u0430\u0434\u0430\u0447\u0438, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0441 IPFS, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044f\u0445.<\/li>\n<li>\u041a\u043e\u0433\u0434\u0430 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0437\u0430\u043a\u0440\u0435\u043f\u0438\u0442\u044c \u0438\u043b\u0438 \u043e\u0442\u043a\u0440\u0435\u043f\u0438\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u0444\u0430\u0439\u043b, \u043c\u044b \u0437\u0430\u043f\u0438\u0448\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u043e \u043d\u0451\u043c \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u0438 \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u043c \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0437\u0430\u0434\u0430\u0447\u0443.<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0412 \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u043c \u0438\u0442\u043e\u0433\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f \u0442\u0430\u043a\u0430\u044f \u0442\u043e\u043f\u043e\u043b\u043e\u0433\u0438\u044f:<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/2u\/n7\/ai\/2un7ainykeluampf3rtx3egivru.png\" data-src=\"https:\/\/habrastorage.org\/webt\/2u\/n7\/ai\/2un7ainykeluampf3rtx3egivru.png\"\/><\/p>\n<p>  <\/p>\n<h2 id=\"minimalnyy-variant-poisk-po-hesham\">\u041c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442: \u043f\u043e\u0438\u0441\u043a \u043f\u043e \u0445\u0435\u0448\u0430\u043c<\/h2>\n<p>  <\/p>\n<h3 id=\"shema-dannyh-i-ocheredi-zadach\">\u0421\u0445\u0435\u043c\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u0437\u0430\u0434\u0430\u0447<\/h3>\n<p>  <\/p>\n<p>\u0414\u0435\u043b\u0430\u0435\u043c \u0434\u0432\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 \u043e \u0445\u0435\u0448\u0435:<\/p>\n<p>  <\/p>\n<ol>\n<li>\u0428\u0430\u0440\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0443\u044e \u2014 \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043d\u0430 \u0442\u0435\u0445 \u0441\u0435\u0440\u0432\u0435\u0440\u0430\u0445, \u043d\u0430 \u0447\u044c\u0438\u0445 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0445 \u043d\u043e\u0434\u0430\u0445 IPFS \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0437\u0430\u043a\u0440\u0435\u043f\u0438\u0442\u044c \u0444\u0430\u0439\u043b\u044b (\u0436\u0435\u043b\u0430\u0435\u043c\u043e\u0435 \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445).<\/li>\n<li>\u041d\u0435\u0448\u0430\u0440\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0443\u044e \u2014 \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u043c\u0443 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044e (\u0437\u0430\u043a\u0440\u0435\u043f\u043b\u0451\u043d\u043d\u043e\u0441\u0442\u0438) \u0432 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u043c \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 (\u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445).<\/li>\n<\/ol>\n<p>  <\/p>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0434\u0432\u0435 \u043e\u0447\u0435\u0440\u0435\u0434\u0438: \u043d\u0430 \u0437\u0430\u043a\u0440\u0435\u043f\u043b\u0435\u043d\u0438\u0435 (\u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435) \u0438 \u043e\u0442\u043a\u0440\u0435\u043f\u043b\u0435\u043d\u0438\u0435 (\u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435) \u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u041a\u043e\u0434<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"lua\">local queue = require('queue')  local function init_schema(is_master)   local pinned = box.schema.space.create('pinned',{format={       {'ipfs_id', 'string'},       {'bucket_id', 'unsigned'}     }, if_not_exists=true})    pinned:create_index('primary', {parts={{1, 'string'}}, unique=true, if_not_exists=true})   pinned:create_index('bucket_id', {parts={{2, 'unsigned'}}, unique=false, if_not_exists=true})    if is_master then     queue.create_tube('ipfs_add', 'fifottl', {if_not_exists = true})     queue.create_tube('ipfs_remove', 'fifottl', {if_not_exists = true})   end    local pinned_no_shard = box.schema.space.create('pinned_no_shard',{format={       {'ipfs_id', 'string'},       {'status', 'string'}     }, if_not_exists=true})    pinned_no_shard:create_index('primary', {parts={{1, 'string'}}, unique=true, if_not_exists=true}) end  return {   init_schema=init_schema }<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<p>\u0417\u0430\u0434\u0430\u0447\u0438 \u043d\u0430 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0441 IPFS \u0431\u0443\u0434\u0435\u043c \u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043f\u0440\u0438 \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 \u0448\u0430\u0440\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c, \u0430 \u043f\u0440\u0438 \u0438\u0445 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438 \u0431\u0443\u0434\u0435\u043c \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u043d\u0435\u0448\u0430\u0440\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439.<\/p>\n<p>  <\/p>\n<h3 id=\"nemnogo-tehnicheskih-poleznostey\">\u041d\u0435\u043c\u043d\u043e\u0433\u043e \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043f\u043e\u043b\u0435\u0437\u043d\u043e\u0441\u0442\u0435\u0439<\/h3>\n<p>  <\/p>\n<h4 id=\"nebolshoy-modul-dlya-vzaimodeystviya-s-ipfs\">\u041d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043c\u043e\u0434\u0443\u043b\u044c \u0434\u043b\u044f \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 IPFS<\/h4>\n<p>  <\/p>\n<p>\u041d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u044f\u0442\u0441\u044f:<\/p>\n<p>  <\/p>\n<ul>\n<li><a href=\"https:\/\/docs.ipfs.io\/reference\/http\/api\/#api-v0-config-show\">\u0447\u0442\u0435\u043d\u0438\u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 IPFS<\/a> (\u0447\u0442\u043e\u0431\u044b \u0443\u0437\u043d\u0430\u0442\u044c, \u043a\u0443\u0434\u0430 \u043a\u0438\u0434\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441);<\/li>\n<li>get_gateway_address \u2014 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0430\u0434\u0440\u0435\u0441\u0430 \u0448\u043b\u044e\u0437\u0430; \u043d\u0435 \u043c\u0443\u0434\u0440\u0438\u043c, \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e IPFS-\u043d\u043e\u0434\u044b \u0441\u0432\u043e\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 gateway_pub_address;<\/li>\n<li>\u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0437\u0430\u043a\u0440\u0435\u043f\u043b\u0435\u043d\u0438\u0435\u043c \u0444\u0430\u0439\u043b\u043e\u0432(\u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435).<\/li>\n<\/ul>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u041a\u043e\u0434<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"lua\">local http = require('http.client').new() local json = require('json')  local api_prefix = 'http:\/\/127.0.0.1:5001'  local function get_config()   local resp = http:post(api_prefix..'\/api\/v0\/config\/show')   if resp.status == 200 then     return json.decode(resp.body)   else     error(resp.reason)   end end  local function get_address()   local config, err = get_config()   if err ~= nil then     return nil, err   end    return assert(config.gateway_pub_address, 'no gateway_pub_address in ipfs config') end  local function pin_add(ipfs_id)   local resp = http:post(api_prefix..'\/api\/v0\/pin\/add?arg='..ipfs_id)   assert(resp.status == 200, resp.reason) end  local function pin_rm(ipfs_id)   local resp = http:post(api_prefix..'\/api\/v0\/pin\/rm?arg='..ipfs_id)   assert(resp.status == 200, resp.reason) end  return {   get_config = get_config,   get_address = get_address,   pin_add = pin_add,   pin_rm = pin_rm }<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<h4 id=\"vypolnenie-operacii-na-vsyom-nabore-replik-odnovremenno\">\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u043d\u0430 \u0432\u0441\u0451\u043c \u043d\u0430\u0431\u043e\u0440\u0435 \u0440\u0435\u043f\u043b\u0438\u043a \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e<\/h4>\n<p>  <\/p>\n<p>\u041d\u0430\u0448\u0430 \u043e\u0447\u0435\u0440\u0435\u0434\u044c, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0441\u043f\u0435\u0439\u0441 \u0441 \u043d\u0435\u0448\u0430\u0440\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0431\u0443\u0434\u0443\u0442 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e \u0440\u0435\u043f\u043b\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0432\u0435\u0441\u044c \u043d\u0430\u0431\u043e\u0440 \u0440\u0435\u043f\u043b\u0438\u043a. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u0434\u043b\u044f \u043f\u043e\u043b\u043d\u043e\u0433\u043e \u043f\u043e\u0432\u0442\u043e\u0440\u0435\u043d\u0438\u044f \u0442\u043e\u043f\u043e\u043b\u043e\u0433\u0438\u0438 \u043d\u0430\u043c \u043d\u0430\u0434\u043e \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c \u0440\u044f\u0434\u043e\u043c \u0441 \u043a\u0430\u0436\u0434\u044b\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u043e\u043c Tarantool \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 IPFS. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438 \u0437\u0430\u0434\u0430\u0447\u0438 \u0438\u0437 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u043d\u0430\u0434\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u043d\u0430 \u0432\u0441\u0451\u043c \u043d\u0430\u0431\u043e\u0440\u0435 \u0440\u0435\u043f\u043b\u0438\u043a. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e:<\/p>\n<p>  <\/p>\n<pre><code class=\"lua\">local function get_curr_replicaset()   local me = cartridge_lua_api_topology.get_self()   return cartridge.admin_get_servers(me.uuid)[1].replicaset end  local function call_on_whole_replicaset(func, params, options)   local servers_uri = {}   for _, server in pairs(get_curr_replicaset().servers) do     table.insert(servers_uri, server.uri)   end    local map_results, map_errors = cartridge_pool.map_call(func, params, {uri_list = servers_uri, timeout = options.timeout})   assert(map_errors == nil, map_errors)   return map_results end<\/code><\/pre>\n<p>  <\/p>\n<h3 id=\"kak-sdelat-otlozhennuyu-sinhronizaciyu-s-ipfs\">\u041a\u0430\u043a \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043e\u0442\u043b\u043e\u0436\u0435\u043d\u043d\u0443\u044e \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044e \u0441 IPFS<\/h3>\n<p>  <\/p>\n<p>\u041f\u043e\u043a\u0430\u0436\u0435\u043c \u0432 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0430\u0445, \u043a\u0430\u043a \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u043c \u0434\u0430\u043d\u043d\u044b\u043c\u0438. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u043f\u043e\u043c\u0438\u043c\u043e \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 \u0437\u0430\u043f\u0438\u0441\u0438 \u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u0440\u0435\u0448\u0430\u0440\u0434\u0438\u043d\u0433\u0430.\u0427\u0442\u043e\u0431\u044b \u0435\u0451 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c, \u0431\u0443\u0434\u0435\u043c \u043f\u0440\u0438 \u043e\u0431\u044b\u0447\u043d\u043e\u043c \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0438 \u0434\u0435\u043b\u0430\u0442\u044c \u043f\u043e\u043c\u0435\u0442\u043a\u0438 \u0432 \u043d\u0435\u0448\u0430\u0440\u0434\u0438\u0440\u0443\u0435\u043c\u043e\u043c \u0441\u043f\u0435\u0439\u0441\u0435. \u0415\u0441\u043b\u0438 \u043f\u043e\u043c\u0435\u0442\u043a\u0430 \u0435\u0441\u0442\u044c, \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0443\u0434\u0430\u043b\u044f\u0442\u044c \u0441\u0440\u0430\u0437\u0443, \u0438\u043d\u0430\u0447\u0435 \u043d\u0430\u0434\u043e \u0434\u043e\u0436\u0434\u0430\u0442\u044c\u0441\u044f \u0437\u0430\u043a\u0440\u0435\u043f\u043b\u0435\u043d\u0438\u044f \u043f\u0438\u043d\u0430 \u043d\u0430 \u043d\u043e\u0432\u043e\u043c \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435.<\/p>\n<p>  <\/p>\n<h4 id=\"dobavlenie\">\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435<\/h4>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/cw\/le\/qq\/cwleqqvrgkmgxdebbaesjnboxgc.png\" data-src=\"https:\/\/habrastorage.org\/webt\/cw\/le\/qq\/cwleqqvrgkmgxdebbaesjnboxgc.png\"\/><\/p>\n<p>  <\/p>\n<h4 id=\"udalenie\">\u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435<\/h4>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/d5\/gs\/s9\/d5gss9zgqnbjxl1x5ixutl_ze-e.png\" data-src=\"https:\/\/habrastorage.org\/webt\/d5\/gs\/s9\/d5gss9zgqnbjxl1x5ixutl_ze-e.png\"\/><\/p>\n<p>  <\/p>\n<h4 id=\"resharding\">\u0420\u0435\u0448\u0430\u0440\u0434\u0438\u043d\u0433<\/h4>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/g3\/5s\/h9\/g35sh9m2heuqtdajc0vzjplbshe.png\" data-src=\"https:\/\/habrastorage.org\/webt\/g3\/5s\/h9\/g35sh9m2heuqtdajc0vzjplbshe.png\"\/><\/p>\n<p>  <\/p>\n<h3 id=\"realizaciya\">\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f<\/h3>\n<p>  <\/p>\n<p>\u041d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043a \u0440\u043e\u0443\u0442\u0435\u0440\u0443:<\/p>\n<p>  <\/p>\n<ol>\n<li>HTTP-\u0437\u0430\u043f\u0440\u043e\u0441, \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043d\u0430 \u043e\u0431\u044a\u0435\u043a\u0442 \u0432 IPFS: <code>GET \/tnt_ipfs\/pin\/:ipfs_id<\/code><\/li>\n<li>HTTP-\u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0438\u043d\u0430: <code>PUT \/tnt_ipfs\/pin\/:ipfs_id<\/code><\/li>\n<li>HTTP-\u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u043f\u0438\u043d\u0430: <code>DELETE \/tnt_ipfs\/pin\/:ipfs_id<\/code><\/li>\n<li>HTTP-\u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0441\u0442\u0430\u0442\u0443\u0441\u0430 \u043f\u0438\u043d\u0430: <code>GET \/tnt_ipfs\/pin\/:ipfs_id\/status<\/code><\/li>\n<\/ol>\n<p>  <\/p>\n<p>\u0410 \u0442\u0430\u043a\u0436\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043a \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0443:<\/p>\n<p>  <\/p>\n<ol>\n<li>\u0417\u0430\u043f\u0440\u043e\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0442\u0434\u0430\u0441\u0442 \u043d\u0430\u043c \u0430\u0434\u0440\u0435\u0441 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0433\u043e \u0435\u043c\u0443 \u0448\u043b\u044e\u0437\u0430: <code>ipfs.get_local_ipfs_addr<\/code><\/li>\n<li>\u0417\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0438\u043d\u0430: <code>ipfs.pin_write<\/code><\/li>\n<li>\u0417\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u043f\u0438\u043d\u0430: <code>ipfs.pin_delete<\/code><\/li>\n<li>\u0417\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0441\u0442\u0430\u0442\u0443\u0441\u0430 \u043f\u0438\u043d\u0430: <code>ipfs.pin_status<\/code><\/li>\n<li>\u0417\u0430\u043f\u0440\u043e\u0441 \u043c\u0435\u0436\u0434\u0443 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430\u043c\u0438 \u043d\u0430 \u0432\u044b\u0437\u043e\u0432: <code>ipfs.pin_add<\/code> \u2014 <code>ipfs.internal.pin_add<\/code><\/li>\n<li>\u0417\u0430\u043f\u0440\u043e\u0441 \u043c\u0435\u0436\u0434\u0443 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430\u043c\u0438 \u043d\u0430 \u0432\u044b\u0437\u043e\u0432: <code>ipfs.pin_rm<\/code> \u2014 <code>ipfs.internal.pin_rm<\/code><\/li>\n<\/ol>\n<p>  <\/p>\n<h4 id=\"kod-dlya-roli-routera\">\u041a\u043e\u0434 \u0434\u043b\u044f \u0440\u043e\u043b\u0438 \u0440\u043e\u0443\u0442\u0435\u0440\u0430<\/h4>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u041a\u043e\u0434<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"lua\">local function init(opts) -- luacheck: no unused args   local httpd = assert(cartridge.service_get('httpd'), \"Failed to get httpd service\")   httpd:route({method = 'GET', path = '\/tnt_ipfs\/pin\/:ipfs_id', public = true}, function(req)       local ipfs_id = req:stash('ipfs_id')       local bucket_id = vshard.router.bucket_id_mpcrc32(ipfs_id)       local gateway_addr, err = vshard.router.callbro(bucket_id, 'ipfs.get_local_ipfs_addr')       if err ~= nil then         return {           status = 500,           body = err         }       end       return req:redirect_to(gateway_addr..'\/ipfs\/'..ipfs_id)     end)    httpd:route({method = 'PUT', path = '\/tnt_ipfs\/pin\/:ipfs_id', public = true}, function(req)       local ipfs_id = req:stash('ipfs_id')       local bucket_id = vshard.router.bucket_id_mpcrc32(ipfs_id)       local _, err = vshard.router.callrw(bucket_id, 'ipfs.pin_write', {{ipfs_id, bucket_id}})       if err ~= nil then         return {           status = 500,           body = err         }       end       return {status = 200}     end)    httpd:route({method = 'DELETE', path = '\/tnt_ipfs\/pin\/:ipfs_id', public = true}, function(req)       local ipfs_id = req:stash('ipfs_id')       local bucket_id = vshard.router.bucket_id_mpcrc32(ipfs_id)       local _, err = vshard.router.callrw(bucket_id, 'ipfs.pin_delete', {ipfs_id})       if err ~= nil then         return {           status = 500,           body = err         }       end       return {status = 200}     end)    httpd:route({method = 'GET', path = '\/tnt_ipfs\/pin\/:ipfs_id\/status', public = true}, function(req)       local ipfs_id = req:stash('ipfs_id')       local bucket_id = vshard.router.bucket_id_mpcrc32(ipfs_id)       local pin_status, err = vshard.router.callro(bucket_id, 'ipfs.pin_status', {ipfs_id})       if err ~= nil then         return {           status = 500,           body = err         }       end       return {         status = 200,         body = pin_status       }     end)    return true end<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<h4 id=\"kod-dlya-roli-hranilischa\">\u041a\u043e\u0434 \u0434\u043b\u044f \u0440\u043e\u043b\u0438 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430<\/h4>\n<p>  <\/p>\n<p>\u0422\u0443\u0442 \u0432\u0441\u0451 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0441\u043b\u043e\u0436\u043d\u0435\u0435:<\/p>\n<p>  <\/p>\n<ol>\n<li>\u041d\u0430\u043f\u0438\u0448\u0435\u043c \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c \u0444\u0430\u0439\u043b\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0432\u0441\u0435\u0445 API-\u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432:<\/li>\n<\/ol>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u041a\u043e\u0434<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"lua\">local ipfs = require('app.ipfs')  local function get_local_ipfs_addr()   return ipfs.get_address() end  local function pin_write(tuple)   box.space.pinned:put(tuple) end  local function pin_delete(ipfs_id)   box.space.pinned_no_shard:put({ipfs_id, 'CAN_UNPIN'})   box.space.pinned:delete(ipfs_id) end  local function pin_status(ipfs_id)   if box.space.pinned:get(ipfs_id) ~= nil then     -- Want to pin     if box.space.pinned_no_shard:get(ipfs_id) ~= nil then       return 'Pinned'     else       return 'Wait pining'     end   else     -- Want to unpin     local pns = box.space.pinned_no_shard:get(ipfs_id)     if pns ~= nil then       if pns.status == 'CAN_UNPIN' then         return 'Wait unpining'       else         return 'Wait reshard'       end     else       return 'Not found'     end   end end  return {   ipfs = {     get_local_ipfs_addr = get_local_ipfs_addr,     pin_write = pin_write,     pin_delete = pin_delete,     pin_status = pin_status,      internal = {       pin_add = ipfs.pin_add,       pin_rm = ipfs.pin_rm     }   } }<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<ol>\n<li>\u041d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0442\u0440\u0438\u0433\u0433\u0435\u0440 \u0434\u043b\u044f \u043f\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0437\u0430\u0434\u0430\u0447 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c:<\/li>\n<\/ol>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u041a\u043e\u0434<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"lua\">local function on_replace(old, new, s, op)   if old == nil then     if new == nil then       -- \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0434\u0435\u043b\u0430\u0435\u043c     else       queue.tube.ipfs_add:put(new.ipfs_id, {delay=1})     end   else     if new == nil then       queue.tube.ipfs_remove:put(old.ipfs_id, {delay=1})     else       if old.ipfs_id ~= new.ipfs_id then         queue.tube.ipfs_add:put(new.ipfs_id, {delay=1})         queue.tube.ipfs_remove:put(old.ipfs_id, {delay=1})       end     end   end end<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<ol>\n<li>\u0415\u0449\u0451 \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u044f\u0442\u0441\u044f \u0432\u043e\u0440\u043a\u0435\u0440\u044b \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0437\u0430\u0434\u0430\u0447:<\/li>\n<\/ol>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u041a\u043e\u0434<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"lua\">local ran = false  local function add_queue_worker()   while ran do     local task = queue.tube.ipfs_add:take()      -- \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e \u043b\u0438 \u0437\u0430\u0434\u0430\u043d\u0438\u0435     local p = box.space.pinned:get(task[3])     local pns = box.space.pinned_no_shard:get(task[3])     if p == nil or pns ~= nil then       queue.tube.ipfs_add:ack(task[1])     else       -- \u043f\u044b\u0442\u0430\u0435\u043c\u0441\u044f \u0437\u0430\u043a\u0440\u0435\u043f\u0438\u0442\u044c       local ok, err = pcall(function()           call_on_whole_replicaset('ipfs.internal.pin_add', {task[3]})         end)        if ok then -- \u0443\u0434\u0430\u043b\u043e\u0441\u044c         box.space.pinned_no_shard:put({task[3], 'PINNED'})         queue.tube.ipfs_add:ack(task[1])       else -- \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c         log.error(err)         queue.tube.ipfs_add:release(task[1], {delay=10})       end     end   end end  local function rm_queue_worker()   while ran do     local task = queue.tube.ipfs_remove:take()      -- \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e \u043b\u0438 \u0437\u0430\u0434\u0430\u043d\u0438\u0435     local p = box.space.pinned:get(task[3])     local pns = box.space.pinned_no_shard:get(task[3])     if p ~= nil or pns == nil then       queue.tube.ipfs_add:ack(task[1])     else       local ok, err        -- \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f \u043b\u0438 \u043e\u0431\u044a\u0435\u043a\u0442 \u043d\u0430 \u043d\u043e\u0432\u043e\u043c \u043c\u0435\u0441\u0442\u0435       ok, err = pcall(function()           local pns = box.space.pinned_no_shard:get(task[3])           if pns and pns.status == 'PINNED' then             -- \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f \u043b\u0438 \u043f\u0438\u043d \u043d\u0430 \u043d\u043e\u0432\u043e\u043c \u043c\u0435\u0441\u0442\u0435             local bucket_id = vshard.router.bucket_id_mpcrc32(task[3])             assert(vshard.router.callro(bucket_id, 'ipfs.pin_status', {task[3]}) == 'Pinned')           end         end)        if ok == nil then --\u0440\u0430\u043d\u043e \u043e\u0442\u043a\u0440\u0435\u043f\u043b\u044f\u0442\u044c         queue.tube.ipfs_remove:release(task[1], {delay=10})       else -- \u043f\u044b\u0442\u0430\u0435\u043c\u0441\u044f \u043e\u0442\u043a\u0440\u0435\u043f\u0438\u0442\u044c         ok, err = pcall(function()           call_on_whole_replicaset('ipfs.internal.pin_rm', {task[3]})         end)          if ok ~= nil then -- \u0443\u0434\u0430\u043b\u043e\u0441\u044c           box.space.pinned_no_shard:delete(task[3])           queue.tube.ipfs_remove:ack(task[1])         else -- \u043d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c           log.error(err)           queue.tube.ipfs_remove:release(task[1], {delay=10})         end       end     end   end end<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<ol>\n<li>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u043b\u044f \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0438 \u0432\u044b\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u0430 \u0438 \u0432\u043e\u0440\u043a\u0435\u0440\u043e\u0432:<\/li>\n<\/ol>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u041a\u043e\u0434<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"lua\">local function activate()   if not ran then     -- \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0432\u043e\u0440\u043a\u0435\u0440\u044b     ran = true     fiber.create(add_queue_worker)     fiber.create(rm_queue_worker)      -- \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u044b     if #box.space.pinned:on_replace() == 0 then       box.space.pinned:on_replace(on_replace)     end   end end  local function deactivate()   if ran then     -- \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0432\u043e\u0440\u043a\u0435\u0440\u044b     ran = false      -- \u0432\u044b\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u044b     if #box.space.pinned:on_replace() == 1 then       box.space.pinned:on_replace(nil, on_replace)     end   end end<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<ol>\n<li>\u041d\u0443 \u0438 \u043d\u0430\u043a\u043e\u043d\u0435\u0446 \u0437\u0430\u043f\u0438\u0445\u043d\u0451\u043c \u0432 \u0440\u043e\u043b\u044c \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u0430 \u0438 \u0432\u043e\u0440\u043a\u0435\u0440\u043e\u0432 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u043c\u0430\u0441\u0442\u0435\u0440\u0430:<\/li>\n<\/ol>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u041a\u043e\u0434<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"lua\">local function init(opts) -- luacheck: no unused args   init_schema.init_schema(opts.is_master)    rawset(_G, 'ipfs', storage_api)    if opts.is_master then     storage_master_service.activate()   else     storage_master_service.deactivate()   end    return true end  local function stop() -- luacheck: no unused args   rawset(_G, 'ipfs')    storage_master_service.deactivate()    return true end  local function apply_config(conf, opts) -- luacheck: no unused args   init_schema.init_schema(opts.is_master)    if opts.is_master then     storage_master_service.activate()   else     storage_master_service.deactivate()   end   return true end<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<h3 id=\"zapuskaem-i-testiruem\">\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c<\/h3>\n<p>  <\/p>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0431\u0443\u0434\u0435\u043c \u0432 Docker. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u0432 \u043e\u0434\u0438\u043d \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u043c \u0441\u0440\u0430\u0437\u0443 \u0438 Tarantool, \u0438 IPFS (\u043f\u043e \u043e\u0434\u043d\u043e\u043c\u0443 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0443). \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f <code>cartridge pack docker<\/code> \u0438 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c Docker-\u0444\u0430\u0439\u043b\u043e\u043c:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">FROM centos:7  RUN yum -y update; yum -y install wget; \\     wget https:\/\/dist.ipfs.io\/go-ipfs\/v0.12.2\/go-ipfs_v0.12.2_linux-amd64.tar.gz; \\     tar -xvzf go-ipfs_v0.12.2_linux-amd64.tar.gz; \\     cd go-ipfs; \\     .\/install.sh<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e docker-compose \u0441\u043e\u0431\u0435\u0440\u0451\u043c \u043a\u043b\u0430\u0441\u0442\u0435\u0440 (\u043f\u043e\u043b\u043d\u044b\u0439 Docker-\u0444\u0430\u0439\u043b \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):<\/p>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u041a\u043e\u0434<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"plaintext\">version: '2.1'  services:   Tarantool-ipfs1:     image: tnt_ipfs:0.1.0.0     container_name: Tarantool-ipfs1     environment:       - IPFS_PATH=\/data-ipfs       - CARTRIDGE_DATA_DIR=\/data       - TARANTOOL_INSTANCE_NAME=r1-router       - TARANTOOL_ADVERTISE_URI=172.19.1.1:3301       - TARANTOOL_CLUSTER_COOKIE=secret       - TARANTOOL_HTTP_PORT=8001     ports:       - 4001:4001 # IPFS p2p       - 5001:5001 # IPFS API       - 8081:8081 # IPFS Gateway       - 3301:3301 # Tarantool Iproto       - 8001:8001 # Tarantool HTTP     volumes:       - ..\/data\/Tarantool-ipfs1:\/data       - ..\/data\/Tarantool-ipfs1-ipfs:\/data-ipfs     networks: # \u041d\u0443\u0436\u043d\u043e. \u0447\u0442\u043e\u0431\u044b Tarantool \u043d\u0435 \u0440\u0443\u0433\u0430\u043b\u0441\u044f \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u043d\u0430 \u0441\u043c\u0435\u043d\u0443 IP       main:         ipv4_address: 172.19.1.1  ...  networks:   main:     ipam:       config:         - subnet: 172.19.1.0\/16<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<p>\u0427\u0442\u043e\u0431\u044b IPFS \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u043b\u0430\u0441\u044c \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 Tarantool, \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432 \u043d\u0430\u0447\u0430\u043b\u043e init.lua \u0441\u0442\u0440\u043e\u043a\u0443 <code>require('os').execute('ipfs daemon --init --writable --enable-gc &amp;')<\/code><\/p>\n<p>  <\/p>\n<p>\u041e\u0441\u0442\u0430\u0451\u0442\u0441\u044f \u0441\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c IPFS. \u0421\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0438\u0437 Docker, \u0442\u0430\u043a \u043a\u0430\u043a \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e API \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0442 127.0.0.1. \u0422\u0430\u043a\u0436\u0435 \u043d\u0430\u0434\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c IP, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u044b \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u043b\u0438 \u043f\u043e\u0440\u0442 \u0434\u043b\u044f \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439.<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">#!\/usr\/bin\/env bash  my_ip=\"X.X.X.X\"  for i in 1 2 3 4 5; do   docker-compose exec \"Tarantool-ipfs$i\" curl --request POST -L --url \"http:\/\/127.0.0.1:5001\/api\/v0\/config?arg=gateway_pub_address&amp;arg=http:\/\/192.168.1.69:808$i\"   docker-compose exec \"Tarantool-ipfs$i\" curl --request POST -L --url \"http:\/\/127.0.0.1:5001\/api\/v0\/config?arg=Addresses.API&amp;arg=\/ip4\/0.0.0.0\/tcp\/5001\"   docker-compose exec \"Tarantool-ipfs$i\" curl --request POST -L --url \"http:\/\/127.0.0.1:5001\/api\/v0\/config?arg=Addresses.Announce&amp;arg=\\[\\\"\/ip4\/$my_ip\/tcp\/400$i\\\"\\]&amp;json=1\"   docker-compose exec \"Tarantool-ipfs$i\" curl --request POST -L --url \"http:\/\/127.0.0.1:5001\/api\/v0\/config?arg=Addresses.Gateway&amp;arg=\/ip4\/0.0.0.0\/tcp\/8081\"   docker-compose exec \"Tarantool-ipfs$i\" curl --request POST -L --url \"http:\/\/127.0.0.1:5001\/api\/v0\/config\/show\"   docker-compose restart \"Tarantool-ipfs$i\" done<\/code><\/pre>\n<p>  <\/p>\n<p>\u0417\u0430\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u043e. \u0422\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0438\u0433\u0440\u0430\u0442\u044c, \u043f\u043e\u043b\u0443\u0447\u0438\u0432, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u043e\u0442 \u044d\u0442\u043e\u0442 \u043e\u0431\u044a\u0435\u043a\u0442: <code>Qme7ss3ARVgxv6rXqVPiikMJ8u2NLgmgszg13pYrDKEoiu<\/code>. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c IPFS \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043d\u0430\u0447\u0430\u043b\u0443 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0434\u043e\u043b\u0433\u043e \u0435\u0433\u043e \u0438\u0441\u043a\u0430\u0442\u044c, \u043f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u0437\u0430\u043a\u0440\u0435\u043f\u0438\u0442\u044c, \u043d\u043e \u0437\u0430\u043a\u0440\u0435\u043f\u0438\u0432, \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0434\u0430\u0432\u0430\u0442\u044c \u043c\u0433\u043d\u043e\u0432\u0435\u043d\u043d\u043e.<\/p>\n<p>  <\/p>\n<p>\u0418 \u0435\u0449\u0451 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u043e\u0432. \u0414\u043b\u044f REST API \u044f \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0438\u0442\u0430\u044e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Insomnia. \u0424\u0430\u0439\u043b\u0438\u043a \u0441 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0435\u0439 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0432 \u043a\u043e\u043d\u0446\u0435 \u0441\u0442\u0430\u0442\u044c\u0438.<\/p>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0442\u0435\u0441\u0442\u0430 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u043e\u0442 \u044d\u0442\u043e\u0442 \u0445\u0435\u0448: <code>Qme7ss3ARVgxv6rXqVPiikMJ8u2NLgmgszg13pYrDKEoiu<\/code>. <\/p>\n<p>  <\/p>\n<ol>\n<li>\u041f\u043e\u043b\u0443\u0447\u0438\u043c \u043f\u043e API IPFS \u0441\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u043a\u0440\u0435\u043f\u043b\u0451\u043d\u043d\u044b\u0445 \u0441\u0435\u0439\u0447\u0430\u0441 \u0444\u0430\u0439\u043b\u043e\u0432. \u0418\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u043e\u043d \u043d\u0435 \u043f\u0443\u0441\u0442\u043e\u0439, \u044d\u0442\u043e \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e.<br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/qu\/yi\/pm\/quyipmrimcgjqm7cjsocu0-yyr8.png\" data-src=\"https:\/\/habrastorage.org\/webt\/qu\/yi\/pm\/quyipmrimcgjqm7cjsocu0-yyr8.png\"\/><\/li>\n<li>\u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0441\u0442\u0430\u0442\u0443\u0441 \u0437\u0430\u043a\u0440\u0435\u043f\u043b\u0435\u043d\u0438\u044f: <code>GET \/tnt_ipfs\/pin\/Qme7ss3ARVgxv6rXqVPiikMJ8u2NLgmgszg13pYrDKEoiu\/status<\/code>.<br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/yc\/do\/rr\/ycdorr80kk_pa027mdzvl1wboow.png\" data-src=\"https:\/\/habrastorage.org\/webt\/yc\/do\/rr\/ycdorr80kk_pa027mdzvl1wboow.png\"\/><br \/>  \u041a\u0430\u043a \u0438 \u043e\u0436\u0438\u0434\u0430\u043b\u043e\u0441\u044c, \u043e \u0437\u0430\u043a\u0440\u0435\u043f\u043b\u0435\u043d\u0438\u0438 \u043f\u043e\u043a\u0430 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e.<\/li>\n<li>\u0412\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u043d\u0430\u0448\u0438\u043c API \u0438 \u0437\u0430\u043a\u0440\u0435\u043f\u0438\u043c \u043d\u0430\u0448 \u043e\u0431\u044a\u0435\u043a\u0442 <code>PUT \/tnt_ipfs\/pin\/Qme7ss3ARVgxv6rXqVPiikMJ8u2NLgmgszg13pYrDKEoiu<\/code>.<br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/ok\/bl\/vp\/okblvpkxnbhwhxldvcprfkflzem.png\" data-src=\"https:\/\/habrastorage.org\/webt\/ok\/bl\/vp\/okblvpkxnbhwhxldvcprfkflzem.png\"\/><\/li>\n<li>\n<p>\u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0441\u0442\u0430\u0442\u0443\u0441 \u0437\u0430\u043a\u0440\u0435\u043f\u043b\u0435\u043d\u0438\u044f \u0441\u043d\u043e\u0432\u0430, \u0435\u0441\u043b\u0438 \u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u043e\u0447\u0435\u043d\u044c \u0431\u044b\u0441\u0442\u0440\u043e, \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0439\u043c\u0430\u0442\u044c \u043c\u043e\u043c\u0435\u043d\u0442, \u043a\u043e\u0433\u0434\u0430 \u043e\u043d \u0431\u0443\u0434\u0435\u0442 <code>Wait pining<\/code>, \u043d\u043e \u043f\u043e\u0442\u043e\u043c \u0441\u0442\u0430\u043d\u0435\u0442 <code>Pinned<\/code>:<br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/nr\/z0\/4s\/nrz04sqm4vf0imrku6x3hdgjzia.png\" data-src=\"https:\/\/habrastorage.org\/webt\/nr\/z0\/4s\/nrz04sqm4vf0imrku6x3hdgjzia.png\"\/><\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/ta\/oe\/in\/taoeinxahgulsjzk8ncawgpobiw.png\" data-src=\"https:\/\/habrastorage.org\/webt\/ta\/oe\/in\/taoeinxahgulsjzk8ncawgpobiw.png\"\/><\/p>\n<p>  <\/li>\n<li>\u0421\u043d\u043e\u0432\u0430 \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u043f\u043e API IPFS \u0441\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u043a\u0440\u0435\u043f\u043b\u0451\u043d\u043d\u044b\u0445 \u0441\u0435\u0439\u0447\u0430\u0441 \u0444\u0430\u0439\u043b\u043e\u0432.<br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/8w\/_t\/qr\/8w_tqranzl3isfe3dvks2wk4zdk.png\" data-src=\"https:\/\/habrastorage.org\/webt\/8w\/_t\/qr\/8w_tqranzl3isfe3dvks2wk4zdk.png\"\/><br \/>  \u0424\u0430\u0439\u043b \u0437\u0430\u043a\u0440\u0435\u043f\u043b\u0451\u043d \u0438 \u0442\u0435\u043f\u0435\u0440\u044c \u0442\u043e\u0447\u043d\u043e \u043d\u0438\u043a\u0443\u0434\u0430 \u043d\u0435 \u0443\u0439\u0434\u0451\u0442 \u0438\u0437 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430.<\/li>\n<li>\u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u0441\u0430\u043c \u0444\u0430\u0439\u043b <code>GET \/tnt_ipfs\/pin\/Qme7ss3ARVgxv6rXqVPiikMJ8u2NLgmgszg13pYrDKEoiu<\/code>:<br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/b3\/f_\/jx\/b3f_jxrkzwmjk_ijbihh2bfl6mk.png\" data-src=\"https:\/\/habrastorage.org\/webt\/b3\/f_\/jx\/b3f_jxrkzwmjk_ijbihh2bfl6mk.png\"\/><br \/>  \u0415\u0441\u043b\u0438 \u0440\u0430\u0441\u043a\u0440\u044b\u0442\u044c \u0440\u0430\u0437\u0434\u0435\u043b Timeline, \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0442\u043e\u0442 \u0441\u0430\u043c\u044b\u0439 \u0440\u0435\u0434\u0438\u0440\u0435\u043a\u0442.<br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/ha\/-9\/3t\/ha-93t-d0dcrozp2ctkthkn9-ts.png\" data-src=\"https:\/\/habrastorage.org\/webt\/ha\/-9\/3t\/ha-93t-d0dcrozp2ctkthkn9-ts.png\"\/><\/li>\n<li>\u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u043e\u0442\u043a\u0440\u0435\u043f\u0438\u0442\u044c <code>DELETE \/tnt_ipfs\/pin\/Qme7ss3ARVgxv6rXqVPiikMJ8u2NLgmgszg13pYrDKEoiu<\/code>:<br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/hk\/lq\/ih\/hklqihwid5i2jkec57mcx7ufzry.png\" data-src=\"https:\/\/habrastorage.org\/webt\/hk\/lq\/ih\/hklqihwid5i2jkec57mcx7ufzry.png\"\/><\/li>\n<li>\n<p>\u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0441\u0442\u0430\u0442\u0443\u0441 \u0437\u0430\u043a\u0440\u0435\u043f\u043b\u0435\u043d\u0438\u044f \u0441\u043d\u043e\u0432\u0430, \u0435\u0441\u043b\u0438 \u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u043e\u0447\u0435\u043d\u044c \u0431\u044b\u0441\u0442\u0440\u043e, \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0439\u043c\u0430\u0442\u044c \u043c\u043e\u043c\u0435\u043d\u0442, \u043a\u043e\u0433\u0434\u0430 \u043e\u043d \u0431\u0443\u0434\u0435\u0442 <code>Wait pining<\/code>, \u043d\u043e \u043f\u043e\u0442\u043e\u043c \u0441\u0442\u0430\u043d\u0435\u0442 <code>Pinned<\/code>:<br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/06\/p6\/s5\/06p6s5nmk6hhtpznscdrqucjuvu.png\" data-src=\"https:\/\/habrastorage.org\/webt\/06\/p6\/s5\/06p6s5nmk6hhtpznscdrqucjuvu.png\"\/><\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/2p\/bs\/w3\/2pbsw38f_icvz3uzwc1niepbpyu.png\" data-src=\"https:\/\/habrastorage.org\/webt\/2p\/bs\/w3\/2pbsw38f_icvz3uzwc1niepbpyu.png\"\/><\/p>\n<p>  <\/li>\n<\/ol>\n<p>  <\/p>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e <code>GET \/tnt_ipfs\/pin\/Qme7ss3ARVgxv6rXqVPiikMJ8u2NLgmgszg13pYrDKEoiu<\/code> \u0432\u043f\u043e\u043b\u043d\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u0441\u044f, \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u0444\u0430\u0439\u043b \u043d\u0435 \u0437\u0430\u043a\u0440\u0435\u043f\u043b\u0451\u043d. \u041e\u0434\u043d\u0430\u043a\u043e, \u0435\u0441\u043b\u0438 \u0432\u044b \u0440\u0430\u043d\u0435\u0435 \u043d\u0435 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u043b\u0438 \u0438\u043b\u0438 \u043d\u0435 \u0437\u0430\u043a\u0440\u0435\u043f\u043b\u044f\u043b\u0438 \u0444\u0430\u0439\u043b, \u0437\u0430\u043f\u0440\u043e\u0441 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u0434\u043e\u043b\u044c\u0448\u0435. \u0414\u0435\u043b\u043e \u0432 \u0442\u043e\u043c \u0447\u0442\u043e IPFS Gateway \u0431\u0443\u0434\u0435\u0442 \u043f\u044b\u0442\u0430\u0442\u044c\u0441\u044f \u043d\u0430\u0439\u0442\u0438 \u0444\u0430\u0439\u043b \u043d\u0430 \u0447\u0443\u0436\u0438\u0445 \u043d\u043e\u0434\u0430\u0445. \u0410 \u043d\u0435\u0437\u0430\u043a\u0440\u0435\u043f\u043b\u0435\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0441\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0432\u044b\u0442\u0435\u0441\u043d\u0435\u043d \u0438\u0437 \u043d\u0430\u0448\u0435\u0439 \u043d\u043e\u0434\u044b. \u0418 \u0435\u0441\u043b\u0438 \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043d\u0438\u043a\u0442\u043e \u0432 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0435 \u0435\u0433\u043e \u043d\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442, \u0442\u043e \u043e\u043d \u0438 \u0432\u043e\u0432\u0441\u0435 \u0431\u0443\u0434\u0435\u0442 \u0431\u0435\u0437\u0432\u043e\u0437\u0432\u0440\u0430\u0442\u043d\u043e \u0443\u0442\u0440\u0430\u0447\u0435\u043d.<\/p>\n<p>  <\/p>\n<h2 id=\"dobavlyaem-indeksnyy-sloy\">\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0438\u043d\u0434\u0435\u043a\u0441\u043d\u044b\u0439 \u0441\u043b\u043e\u0439<\/h2>\n<p>  <\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u043d\u0435 \u0437\u043d\u0430\u043a\u043e\u043c\u044b \u0441 \u0438\u043d\u0434\u0435\u043a\u0441\u043d\u044b\u043c\u0438 \u0441\u043b\u043e\u044f\u043c\u0438, \u0442\u043e \u043e\u0431\u0449\u0438\u0435 \u0438\u0434\u0435\u0438 \u0438\u0445 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0437\u0434\u0435\u0441\u044c: <a href=\"https:\/\/habr.com\/ru\/company\/vk\/blog\/657789\/\">https:\/\/habr.com\/ru\/company\/vk\/blog\/657789\/<\/a>.<\/p>\n<p>  <\/p>\n<h3 id=\"shema-dannyh\">\u0421\u0445\u0435\u043c\u0430 \u0434\u0430\u043d\u043d\u044b\u0445<\/h3>\n<p>  <\/p>\n<p>\u0418\u043d\u0434\u0435\u043a\u0441\u043d\u044b\u0439 \u0441\u043b\u043e\u0439 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u0442\u044c \u0438\u0437 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0437\u0430\u043f\u0438\u0441\u0435\u0439:<\/p>\n<p>  <\/p>\n<div class=\"scrollable-table\">\n<table>\n<thead>\n<tr>\n<th>path<\/th>\n<th>bucket_id<\/th>\n<th>name<\/th>\n<th>is_dir<\/th>\n<th>ipfs_id<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>\u043f\u043e\u043b\u043d\u044b\u0439 \u043f\u0443\u0442\u044c \u0434\u043e \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0430<\/td>\n<td>bucket_id<\/td>\n<td>\u0438\u043c\u044f<\/td>\n<td>\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043b\u0438 \u0437\u0430\u043f\u0438\u0441\u044c \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u043e\u043c<\/td>\n<td>\u0445\u0435\u0448 \u0432 IPFS<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>  <\/p>\n<p>*<em>bucket_id \u0441\u0442\u0440\u043e\u0438\u0442\u0441\u044f \u043f\u043e path<\/em><\/p>\n<p>  <\/p>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e \u0438\u0441\u043a\u0430\u0442\u044c \u0444\u0430\u0439\u043b\u044b.<\/p>\n<p>  <\/p>\n<p>\u0421\u0440\u0430\u0437\u0443 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432 \u043a\u043e\u0434 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0441\u043f\u0435\u0439\u0441\u043e\u0432:<\/p>\n<p>  <\/p>\n<pre><code class=\"lua\">  local objects = box.schema.space.create('objects',{format={       {'path', 'string'},       {'bucket_id', 'unsigned'},       {'name', 'string'},       {'is_dir', 'boolean'},       {'ipfs_id', 'string', is_nullable = true}     }, if_not_exists=true})   objects:create_index('primary', {parts={{1, 'string'},{3, 'string'}}, unique=true, if_not_exists=true})   objects:create_index('bucket_id', {parts={{2, 'unsigned'}}, unique=false, if_not_exists=true})<\/code><\/pre>\n<p>  <\/p>\n<h3 id=\"realizaciya-1\">\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f<\/h3>\n<p>  <\/p>\n<p>\u041d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0442\u0430\u043a\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043a \u0440\u043e\u0443\u0442\u0435\u0440\u0443:<\/p>\n<p>  <\/p>\n<ol>\n<li>HTTP-\u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438: <code>PUT \/tnt_ipfs\/storage\/*full_path?type=dir<\/code><\/li>\n<li>HTTP-\u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u0430: <code>PUT \/tnt_ipfs\/storage\/*full_path?type=object&amp;ipfs_id=...<\/code><\/li>\n<li>HTTP-\u0437\u0430\u043f\u0440\u043e\u0441, \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0439 \u043d\u0430 \u043e\u0431\u044a\u0435\u043a\u0442 \u0432 IPFS \u0438\u043b\u0438 \u043e\u0442\u0434\u0430\u044e\u0449\u0438\u0439 \u043b\u0438\u0441\u0442\u0438\u043d\u0433 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438: <code>GET \/tnt_ipfs\/storage\/*full_path<\/code><\/li>\n<li>HTTP-\u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u0438\u043b\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u0430: <code>DELETE \/tnt_ipfs\/storage\/*full_path<\/code><\/li>\n<\/ol>\n<p>  <\/p>\n<p>\u0418 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043a \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0443:<\/p>\n<p>  <\/p>\n<ol>\n<li>\u0417\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0439 \u0438\u043b\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432: <code>storage.add<\/code><\/li>\n<li>\u0417\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0439 \u0438\u043b\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432: <code>storage.del<\/code><\/li>\n<li>\u0417\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u0438\u043b\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u0435: <code>storage.get<\/code><\/li>\n<li>\u0417\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u043b\u0438\u0441\u0442\u0438\u043d\u0433 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438: <code>storage.ls<\/code><\/li>\n<\/ol>\n<p>  <\/p>\n<h4 id=\"kod-dlya-roli-routera-1\">\u041a\u043e\u0434 \u0434\u043b\u044f \u0440\u043e\u043b\u0438 \u0440\u043e\u0443\u0442\u0435\u0440\u0430<\/h4>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u041a\u043e\u0434<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"lua\">local function convert_path(full_path)   local path, name = full_path:match(\"^(.*)\/(.+)$\")   if not path then     return '', full_path   end   return path, name end  ...    httpd:route({method = 'PUT', path = '\/tnt_ipfs\/storage\/*full_path', public = true}, function(req)       local full_path = req:stash('full_path')       local path, name = convert_path(full_path)       local bucket_id = vshard.router.bucket_id_mpcrc32(path)       local type = req:query_param('type')       if type == 'dir' then         local _, err = vshard.router.callrw(bucket_id, 'storage.add', {path, bucket_id, name, true})         if err ~= nil then           return {             status = 500,             body = err           }         end         return {status = 200}       elseif type == 'object' then         local ipfs_id = req:query_param('ipfs_id')         local bucket_id2 = vshard.router.bucket_id_mpcrc32(ipfs_id)         local _, err = vshard.router.callrw(bucket_id2, 'ipfs.pin_write', {{ipfs_id, bucket_id2}})         if err ~= nil then           return {             status = 500,             body = err           }         end         _, err = vshard.router.callrw(bucket_id, 'storage.add', {path, bucket_id, name, false, ipfs_id})         if err ~= nil then           return {             status = 500,             body = err           }         end         return {status = 200}       end       return {status = 400}     end)    httpd:route({method = 'DELETE', path = '\/tnt_ipfs\/storage\/*full_path', public = true}, function(req)       local full_path = req:stash('full_path')       local path, name = convert_path(full_path)       local bucket_id = vshard.router.bucket_id_mpcrc32(path)       local deleted, err = vshard.router.callrw(bucket_id, 'storage.del', {path, name})       if deleted == nil or err ~= nil then         return {           status = 500,           body = err         }       end       if deleted.is_dir then         return {status = 200}       else         bucket_id = vshard.router.bucket_id_mpcrc32(deleted.ipfs_id)         local _, err2 = vshard.router.callrw(bucket_id, 'ipfs.pin_delete', {deleted.ipfs_id})         if err2 ~= nil then           return {             status = 500,             body = err2           }         end         return {status = 200}       end     end)    httpd:route({method = 'GET', path = '\/tnt_ipfs\/storage\/*full_path', public = true}, function(req)       local full_path = req:stash('full_path')       local path, name = convert_path(full_path)       local bucket_id = vshard.router.bucket_id_mpcrc32(path)       local main_record, err       if path == '' then --\u043a\u0430\u0442\u0430\u043b\u043e\u0433 \u0432 \u043a\u043e\u0440\u043d\u0435         main_record = {is_dir=true}       else         main_record, err = vshard.router.callro(bucket_id, 'storage.get', {path,name})         if err ~= nil then           return {             status = 500,             body = err           }         end         if main_record == nil then           return {status = 404}         end       end       if main_record.is_dir then         bucket_id = vshard.router.bucket_id_mpcrc32(full_path)         local result, err2 = vshard.router.callro(bucket_id, 'storage.ls', {full_path})         if err2 ~= nil then           return {             status = 500,             body = err2           }         end         return {           status = 200,           body = result         }       else         bucket_id = vshard.router.bucket_id_mpcrc32(main_record.ipfs_id)         local gateway_addr, err2 = vshard.router.callbro(bucket_id, 'ipfs.get_local_ipfs_addr')         if err2 ~= nil then           return {             status = 500,             body = err2           }         end         return req:redirect_to(gateway_addr..'\/ipfs\/'..main_record.ipfs_id)       end     end)<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<h4 id=\"api-hranilischa\">API \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430<\/h4>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u041a\u043e\u0434<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"lua\">local function storage_add(path,bucket_id,name,is_dir,ipfs_id)   if is_dir then     box.space.objects:put({path,bucket_id,name,true})   else     box.space.objects:put({path,bucket_id,name,false,ipfs_id})   end end  local function storage_del(path,name)   local data = box.space.objects:delete({path,name})   assert(data ~= nil)   return data:tomap({names_only=true}) end  local function storage_get(path,name)   local data = box.space.objects:get({path,name})   assert(data ~= nil)   return data:tomap({names_only=true}) end  local function storage_ls(path)   local result = {}   for _,i in box.space.objects:pairs({path}) do     table.insert(result, {name = i.name, is_dir = i.is_dir})   end   return result end<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<h3 id=\"zapuskaem-i-testiruem-1\">\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c<\/h3>\n<p>  <\/p>\n<ol>\n<li>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043a\u0430\u0442\u0430\u043b\u043e\u0433 <code>PUT \/tnt_ipfs\/storage\/a?type=dir<\/code>. \u0415\u0433\u043e \u043c\u044b \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u043d\u0435 \u0441\u043c\u043e\u0436\u0435\u043c, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043e\u043d \u043f\u0443\u0441\u0442\u043e\u0439.<\/li>\n<li>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0432\u0442\u043e\u0440\u043e\u0439 \u043a\u0430\u0442\u0430\u043b\u043e\u0433 \u0432\u043d\u0443\u0442\u0440\u0438 \u043f\u0435\u0440\u0432\u043e\u0433\u043e: <code>PUT \/tnt_ipfs\/storage\/a\/b?type=dir<\/code>.<\/li>\n<li>\u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0430: <code>GET \/tnt_ipfs\/storage\/a<\/code>.<br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/5t\/tc\/tx\/5ttctxmeit81zpm1o1rfa_v_fx0.png\" data-src=\"https:\/\/habrastorage.org\/webt\/5t\/tc\/tx\/5ttctxmeit81zpm1o1rfa_v_fx0.png\"\/><\/li>\n<li>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043e\u0431\u044a\u0435\u043a\u0442 \u0432\u043d\u0443\u0442\u0440\u0438 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0430: <code>PUT \/tnt_ipfs\/storage\/a\/c?type=object&amp;ipfs_id=Qme7ss3ARVgxv6rXqVPiikMJ8u2NLgmgszg13pYrDKEoiu<\/code>.<\/li>\n<li>\u0421\u043d\u043e\u0432\u0430 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0430: <code>GET \/tnt_ipfs\/storage\/a<\/code>.<br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/6x\/0w\/qs\/6x0wqsex6xotc_xh2lbmr9i8pkw.png\" data-src=\"https:\/\/habrastorage.org\/webt\/6x\/0w\/qs\/6x0wqsex6xotc_xh2lbmr9i8pkw.png\"\/><\/li>\n<li>\u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u0441\u0430\u043c \u0444\u0430\u0439\u043b: <code>GET \/tnt_ipfs\/storage\/a\/c<\/code>:<br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/ub\/mk\/ep\/ubmkepemh3z-l303hag-2vsb9x4.png\" data-src=\"https:\/\/habrastorage.org\/webt\/ub\/mk\/ep\/ubmkepemh3z-l303hag-2vsb9x4.png\"\/><br \/>  \u0415\u0441\u043b\u0438 \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 Timeline \u0432\u0441\u0451 \u0442\u043e\u0442 \u0436\u0435 \u0440\u0435\u0434\u0438\u0440\u0435\u043a\u0442.<br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/wh\/1u\/yt\/wh1uyt-6ssddfhfj72lrvvgfbrs.png\" data-src=\"https:\/\/habrastorage.org\/webt\/wh\/1u\/yt\/wh1uyt-6ssddfhfj72lrvvgfbrs.png\"\/><\/li>\n<li>\u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0443\u0434\u0430\u043b\u044f\u0442\u044c \u0444\u0430\u0439\u043b\u044b \u0438 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438:<br \/>  <code>DELETE \/tnt_ipfs\/storage\/a\/b<\/code>:<br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/te\/vv\/eu\/tevveutek4uxl5sicfajhgwrjiw.png\" data-src=\"https:\/\/habrastorage.org\/webt\/te\/vv\/eu\/tevveutek4uxl5sicfajhgwrjiw.png\"\/><br \/>  <code>DELETE \/tnt_ipfs\/storage\/a\/\u0441<\/code>:<br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/8n\/zd\/1q\/8nzd1qxtgyhivgeimfdvl3mj8dy.png\" data-src=\"https:\/\/habrastorage.org\/webt\/8n\/zd\/1q\/8nzd1qxtgyhivgeimfdvl3mj8dy.png\"\/><\/li>\n<\/ol>\n<p>  <\/p>\n<h2 id=\"smotrim-kak-vsyo-klassno-obsuzhdaem-chto-poluchilos\">\u0421\u043c\u043e\u0442\u0440\u0438\u043c, \u043a\u0430\u043a \u0432\u0441\u0451 \u043a\u043b\u0430\u0441\u0441\u043d\u043e. \u041e\u0431\u0441\u0443\u0436\u0434\u0430\u0435\u043c, \u0447\u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c<\/h2>\n<p>  <\/p>\n<h3 id=\"chem-horosho-eto-reshenie\">\u0427\u0435\u043c \u0445\u043e\u0440\u043e\u0448\u043e \u044d\u0442\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u0435?<\/h3>\n<p>  <\/p>\n<p>\u041f\u0440\u0438\u043b\u043e\u0436\u0438\u0432 \u043d\u0435 \u0442\u0430\u043a \u043c\u043d\u043e\u0433\u043e \u0443\u0441\u0438\u043b\u0438\u0439, \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0439 MVP \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u043e\u0433\u043e \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430. \u0418<br \/>  \u0435\u0441\u043b\u0438 \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u044c <code>gateway_pub_address<\/code>, \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440\u044b \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u0445 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u043e\u0432 \u0434\u043b\u044f \u043a\u0435\u0448\u0430 \u0432\u0430\u0448\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<p>  <\/p>\n<p>\u0420\u0435\u0448\u0435\u043d\u0438\u0435 \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u0443\u0435\u0442 \u043e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u044c \u043f\u0440\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430\u0445 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u0430\u043c\u0438 \u0432 n-1 \u0426\u041e\u0414\u0430\u0445 \u043f\u0440\u0438 \u0443\u0441\u043b\u043e\u0432\u0438\u0438, \u0447\u0442\u043e \u0432\u0441\u0435 \u043d\u0430\u0431\u043e\u0440\u044b \u0440\u0435\u043f\u043b\u0438\u043a \u0441\u043e\u0431\u0440\u0430\u043d\u044b \u0438\u0437 n \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449 \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u0426\u041e\u0414\u0430\u0445. \u0422\u0430\u043a\u0436\u0435 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438 \u0431\u0430\u043b\u0430\u043d\u0441\u0438\u0440\u043e\u0432\u043a\u0443 \u043f\u043e \u0432\u0441\u0435\u043c \u043d\u043e\u0434\u0430\u043c IPFS.<\/p>\n<p>  <\/p>\n<h3 id=\"kak-mozhno-primenit-eto-na-praktike\">\u041a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u044d\u0442\u043e \u043d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435?<\/h3>\n<p>  <\/p>\n<ul>\n<li>\u0425\u0440\u0430\u043d\u0438\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u043e\u0431\u044a\u0451\u043c\u044b \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445.<\/li>\n<li>\u0411\u0435\u043a\u0430\u043f\u0438\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u043e\u0431\u044a\u0451\u043c\u044b \u0434\u0430\u043d\u043d\u044b\u0445, \u0443\u0436\u0435 \u0437\u0430\u043b\u0438\u0442\u044b\u0445 \u0432 IPFS. \u041a \u043f\u0440\u0438\u043c\u0435\u0440\u0443, NFT-\u0442\u043e\u043a\u0435\u043d\u044b \u0437\u0430\u043f\u0438\u0441\u0430\u043d\u044b \u0432 \u0431\u043b\u043e\u043a\u0447\u0435\u0439\u043d\u0435 Ethereum \u043a\u0430\u043a \u0445\u0435\u0448\u0438, \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0441\u0430\u043c\u0438 \u0444\u0430\u0439\u043b\u044b \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432 IPFS.<\/li>\n<li>\u041f\u043e \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u043c \u0432 \u0441\u0442\u0430\u0442\u044c\u0435 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0430\u043c \u043c\u043e\u0436\u043d\u043e \u0448\u0430\u0440\u0434\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/li>\n<\/ul>\n<p>  <\/p>\n<h3 id=\"chego-nehvataet-chtoby-eto-reshenie-mozhno-bylo-nazvat-prod-ready\">\u0427\u0435\u0433\u043e \u043d\u0435\u0445\u0432\u0430\u0442\u0430\u0435\u0442, \u0447\u0442\u043e\u0431\u044b \u044d\u0442\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043d\u0430\u0437\u0432\u0430\u0442\u044c Prod-Ready?<\/h3>\n<p>  <\/p>\n<p>\u0415\u0441\u0442\u044c \u043c\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u0447\u0438\u043d \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u044d\u0442\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u0435, \u0441\u043a\u043e\u0440\u0435\u0435, MVP, \u043d\u0435\u0436\u0435\u043b\u0438 Prod-Ready. \u041e\u0434\u043d\u0430\u043a\u043e \u0435\u0433\u043e \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u044f\u0432\u043d\u043e \u0432\u044b\u0445\u043e\u0434\u0438\u0442 \u0437\u0430 \u0440\u0430\u043c\u043a\u0438 \u0441\u0442\u0430\u0442\u044c\u0438.<\/p>\n<p>  <\/p>\n<ul>\n<li>\n<p><strong>\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b<\/strong>. \u041d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u0435 Prod-Ready \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433\u0430, \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043e\u0448\u0438\u0431\u043e\u043a \u0438 \u0437\u0430\u043c\u0435\u0440\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u0430.<\/p>\n<p>  <\/li>\n<li>\n<p><strong>Reference counter<\/strong>. \u041f\u043e-\u0445\u043e\u0440\u043e\u0448\u0435\u043c\u0443, \u043d\u0430 \u0437\u0430\u043a\u0440\u0435\u043f\u043b\u0435\u043d\u0438\u044f\u0445 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c Reference counter, \u0447\u0442\u043e\u0431\u044b \u0438\u0445 \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0432 \u043f\u043e\u0438\u0441\u043a \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437 (\u0438\u043d\u0430\u0447\u0435 \u043f\u0440\u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0438 \u043e\u0434\u043d\u043e\u0433\u043e \u043c\u0435\u0441\u0442\u0430 \u0432 \u043f\u043e\u0438\u0441\u043a\u0435 \u043f\u0440\u043e\u0438\u0437\u043e\u0439\u0434\u0451\u0442 \u043e\u0442\u043a\u0440\u0435\u043f\u043b\u0435\u043d\u0438\u0435 \u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u043f\u043e\u0442\u0435\u0440\u044f\u0442\u044c\u0441\u044f).<\/p>\n<p>  <\/li>\n<li>\n<p><strong>\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0445<\/strong>. \u0412 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0438\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u044b\u0445 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430\u0445 \u0435\u0441\u0442\u044c \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430, \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c\u044e \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u043e\u0432 \u0438 \u043f\u0440\u043e\u0447\u0435\u0433\u043e.<\/p>\n<p>  <\/li>\n<li>\n<p><strong>\u0420\u0430\u0437\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u043f\u0440\u0430\u0432<\/strong>. \u0425\u043e\u0442\u044c \u044d\u0442\u043e \u0438 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u043e\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435, \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u0430\u0432\u0430\u043c\u0438 \u043d\u0430 \u0437\u0430\u043f\u0438\u0441\u044c \u0432 \u043f\u043e\u0438\u0441\u043a\u043e\u0432\u044b\u0439 \u0441\u043b\u043e\u0439 \u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u0430 \u0434\u043b\u044f \u0440\u0430\u0437\u043d\u044b\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0432\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u043e\u043b\u0435\u0437\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c\u044e.<\/p>\n<p>  <\/li>\n<li>\n<p><strong>\u0410\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0435 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u0448\u0430\u0440\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f<\/strong>. \u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u044b\u0435 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b \u0448\u0430\u0440\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u044e\u0449\u0438\u0435 \u043e\u0431\u044a\u0451\u043c \u0434\u0430\u043d\u043d\u044b\u0445, \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u043d\u0430 \u0434\u0438\u0441\u043a \u0438 \u0441\u0435\u0442\u044c. \u0418\u0445 \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u043a \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u043c\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e, \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0432 \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0438 \u043f\u043e\u0438\u0441\u043a\u0430 Tarantool. \u041e\u0434\u043d\u0430\u043a\u043e \u044d\u0442\u043e \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0441\u0442\u044b\u043c \u043f\u043e\u0432\u0442\u043e\u0440\u0435\u043d\u0438\u0435\u043c \u0448\u0430\u0440\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u0447\u0442\u043e \u043c\u043d\u043e\u0433\u043e\u043a\u0440\u0430\u0442\u043d\u043e \u0443\u0441\u043b\u043e\u0436\u043d\u0438\u0442 \u0437\u0430\u0434\u0430\u0447\u0443.<\/p>\n<p>  <\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0420\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0441 \u043f\u043e\u043b\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c: <a href=\"https:\/\/github.com\/Artem3213212\/TNT-IPFS\">https:\/\/github.com\/Artem3213212\/TNT-IPFS<\/a><\/p>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"v-portal\" style=\"display:none;\"><\/div>\n<\/div>\n<p> <!----> <!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/company\/vk\/blog\/681800\/\"> https:\/\/habr.com\/ru\/company\/vk\/blog\/681800\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/webt\/be\/jx\/jh\/bejxjhzohyztvgjokq8tjuwwcdy.jpeg\" data-src=\"https:\/\/habrastorage.org\/webt\/be\/jx\/jh\/bejxjhzohyztvgjokq8tjuwwcdy.jpeg\" data-blurred=\"true\"\/><\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u0438\u0432\u0435\u0442! \u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0410\u0440\u0442\u0435\u043c \u0413\u0430\u0432\u0440\u0438\u043b\u043e\u0432 \u0438 \u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e \u0432 Tarantool. \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443, \u043a\u0430\u043a \u0431\u044b\u0441\u0442\u0440\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u043e\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b in-memory \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439 <a href=\"https:\/\/www.Tarantool.io\/ru\/\">Tarantool<\/a> \u0438 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u043e\u0439 \u0444\u0430\u0439\u043b\u043e\u0432\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b <a href=\"https:\/\/ru.wikipedia.org\/wiki\/IPFS\">IPFS<\/a> (InterPlanetary File System). <\/p>\n<p>  <\/p>\n<p>\u041c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043f\u0440\u0438\u043c\u0435\u0440 \u0448\u0430\u0440\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Tarantool \u0438 \u0441\u0434\u0435\u043b\u0430\u0435\u043c MVP \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u043e\u0433\u043e \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0441 \u043e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u044c\u044e \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u0426\u041e\u0414\u0430, \u0432 \u0442\u043e \u0432\u0440\u0435\u043c\u044f \u043a\u0430\u043a \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0441\u0442\u044b\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u0432.<\/p>\n<p>  <\/p>\n<p>\u0422\u0435\u043c, \u043a\u0442\u043e \u0437\u043d\u0430\u043a\u043e\u043c \u0441 IPFS, \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e, \u0431\u0443\u0434\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e \u0447\u0438\u0442\u0430\u0442\u044c \u043d\u0430\u0447\u0438\u043d\u0430\u044f \u0441 \u0440\u0430\u0437\u0434\u0435\u043b\u0430 \u00ab<em>\u0421 \u0447\u0435\u043c \u043c\u044b \u0441\u0442\u043e\u043b\u043a\u043d\u0451\u043c\u0441\u044f<\/em>\u00bb.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-336900","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/336900","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=336900"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/336900\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=336900"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=336900"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=336900"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}