рдмреИрдХрдЕрдк рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдмрд╣реБ-рдереНрд░реЗрдбреЗрдб рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдмрдирд╛рдиреЗ рдореЗрдВ рдореЗрд░рд╛ рдЕрдиреБрднрд╡

рдЕрднреА, рдЖрдкрдиреЗ рдХрд┐рд╕реА рдХреЛ рдорд▓реНрдЯреАрдереНрд░реЗрдб рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рд╕рд╛рде рдЖрд╢реНрдЪрд░реНрдпрдЪрдХрд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рдЖрдк рдХреБрдЫ рджрд┐рд▓рдЪрд╕реНрдк рд╡рд┐рдЪрд╛рд░ рдкрд╛ рд╕рдХрддреЗ рд╣реИрдВред рдЬрд╛рд╡рд╛ рдХрд╛ рдореЗрд░рд╛ рдЕрдзреНрдпрдпрди рдЗрд╕ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рд╣реБрдЖ, рдЗрд╕рд▓рд┐рдП рд╢рд╛рдпрдж рдХреБрдЫ рдЬрдЧрд╣реЛрдВ рдкрд░ рдореИрдВ рдмрд╣реБрдд рдЧрд▓рдд рд╣реЛ рдЬрд╛рдКрдВрдЧрд╛ рдпрд╛ рдПрдХ рдмрдбрд╝реА рдмрд╛рдЗрдХ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░реВрдВрдЧрд╛, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдХрд┐рд╕реА рдХреЛ рдЬрд╛рд╡рд╛ рдореЗрдВ рд╢реБрд░реБрдЖрдд рдХреЗ рдЕрдиреБрднрд╡ рдореЗрдВ рджрд┐рд▓рдЪрд╕реНрдкреА рд╣реЛрдЧреАред рдореИрдВ рдЖрд╡реЗрджрди рдХреА рдХрдИ рд╡рд┐рд╢реЗрд╖рддрд╛рдПрдВ рджреВрдВрдЧрд╛:


  • рдпрд╣ рдмреИрдХрдЕрдк рдХреЗ рд╕рд╛рде рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдореЗрдореЛрд░реА рдореЗрдВ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рдмреИрдХрдЕрдк рдХреЗ рдЖрдХрд╛рд░ рдХреА рдкрд░рд╡рд╛рд╣ рдХрд┐рдП рдмрд┐рдирд╛
  • рдкреВрд░реЗ рдмреИрдХрдЕрдк рдХреЛ рдореЗрдореЛрд░реА рдореЗрдВ рд▓реЛрдб рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ
  • рдмреИрдХрдЕрдк / рдкреБрдирд░реНрд╕реНрдерд╛рдкрдирд╛ рд╕рдВрдЪрд╛рд▓рди рд░рджреНрдж рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ

рдХрдЯреМрддреА рдХреЗ рддрд╣рдд рдЖрд╡реЗрджрди рдХреА рд╡рд╛рд╕реНрддреБрдХрд▓рд╛, рд╕рд╛рде рд╣реА рд╕рд╛рде рдореБрдЦреНрдп рд╕рдорд╕реНрдпрд╛рдУрдВ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рдирд╛ рдкрдбрд╝рд╛ рдФрд░ рдЙрдирдХреЗ рд╕рдорд╛рдзрд╛рди рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред


рдЖрд╡реЗрджрди рдЕрд╡рд▓реЛрдХрди


рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рд╕рд╛рде рд╕рдВрдЪрд╛рд░ рд╡реЗрдм UI рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╣реЛрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рднрд╡рд┐рд╖реНрдп рдореЗрдВ рдпрджрд┐ рдЖрд╡рд╢реНрдпрдХ рд╣реЛ рддреЛ REST API рдЬреЛрдбрд╝рдирд╛ рд╕рдВрднрд╡ рд╣реЛрдЧрд╛ред


рдЖрд╡реЗрджрди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:


  1. рдмреИрдХрдЕрдк рдмрдирд╛рдПрдВ рдФрд░ рдЙрдиреНрд╣реЗрдВ рдПрдХ рдпрд╛ рдЕрдзрд┐рдХ рд╕реНрдЯреЛрд░реЗрдЬ рдкрд░ рдЕрдкрд▓реЛрдб рдХрд░реЗрдВ
  2. рдмреИрдХрдЕрдк рдХреЛ рд╕реНрдЯреЛрд░реЗрдЬ рд╕реЗ рд▓реЛрдб рдХрд░рдХреЗ рд░рд┐рд╕реНрдЯреЛрд░ рдХрд░реЗрдВ
  3. рд╕рднреА рд╕реНрдЯреЛрд░реЗрдЬ рд╕реЗ рдмреИрдХрдЕрдк рд╣рдЯрд╛рдПрдВ
  4. рд╕рдордп-рд╕рдордп рдкрд░ рдмреИрдХрдЕрдк рдмрдирд╛рдПрдВ

рд╡рд░реНрддрдорд╛рди рдореЗрдВ рд╕рдорд░реНрдерд┐рдд рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА:


  • рд╕реНрдерд╛рдиреАрдп рдлрд╝рд╛рдЗрд▓ рд╕рд┐рд╕реНрдЯрдо (рдбреЙрдХрд░ рд╕реЗ рд╕рдорд░реНрдерд┐рдд рдирд╣реАрдВ)
  • рдбреНрд░реЙрдкрдмреЙрдХреНрд╕

рд╡рд░реНрддрдорд╛рди рдореЗрдВ рд╕рдорд░реНрдерд┐рдд рдбреЗрдЯрд╛рдмреЗрд╕:


  • PostgreSQL

рдПрдХ рд╡рд┐рд╢реЗрд╖ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╕реЗ, рдореИрдВ рдиреЛрдЯ рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВ:


  1. рдХреНрд▓рд╕реНрдЯрд░ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдореЗрдВ рд╕рд╣реА рдХрд╛рд░реНрдп
  2. рдмреИрдХрдЕрдк рдХреЗ рдЖрдХрд╛рд░ рдХреА рдкрд░рд╡рд╛рд╣ рдХрд┐рдП рдмрд┐рдирд╛ рдПрдХ рдмреИрдХрдЕрдк рдХреЛ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдореЗрдореЛрд░реА рдореЗрдВ рд▓реЛрдб рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЕрд╕реНрдерд╛рдпреА рдмреИрдХрдЕрдк рд╕рдВрдЧреНрд░рд╣рдг рдХреЗ рд▓рд┐рдП рдлрд╝рд╛рдЗрд▓ рд╕рд┐рд╕реНрдЯрдо рднреА рд╢рд╛рдорд┐рд▓ рдирд╣реАрдВ рд╣реИред рдмреИрдХрдЕрдк рдФрд░ рдкреБрдирд░реНрд╕реНрдерд╛рдкрдирд╛ рджреЛрдиреЛрдВ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдФрд░ рдЗрд╕рд▓рд┐рдП рдмреИрдХрдЕрдк рдХрд╛ рд▓реЛрдбрд┐рдВрдЧ / рдЕрдирд▓реЛрдбрд┐рдВрдЧ, рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдореЗрдореЛрд░реА рдореЗрдВ рд╣реЛрддрд╛ рд╣реИред
  3. рдХреНрд░реЙрд╕-рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо - рд╡рд┐рдВрдбреЛрдЬ рдФрд░ рд▓рд┐рдирдХреНрд╕ рджреЛрдиреЛрдВ рдкрд░ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред
  4. рд╣рдо рд╕рднреА рдЪрд▓ рд░рд╣реЗ рдХрд╛рд░реНрдпреЛрдВ рдХреА рдирд┐рдЧрд░рд╛рдиреА рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдпрджрд┐ рдЖрд╡рд╢реНрдпрдХ рд╣реЛ рддреЛ рдЙрдиреНрд╣реЗрдВ рд░рджреНрдж рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рдиреАрдЪреЗ рд╡реЗрдм UI рдХреЗ рд╕реНрдХреНрд░реАрдирд╢реЙрдЯ рд╣реИрдВ рдЬреЛ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреА рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддреЗ рд╣реИрдВред


рднрдВрдбрд╛рд░рдг рдкреНрд░рдмрдВрдзрди



рдбреЗрдЯрд╛рдмреЗрд╕ рдкреНрд░рдмрдВрдзрди



рдмреИрдХрдЕрдк рдирд┐рд░реНрдорд╛рдг


рдмреИрдХрдЕрдк рд╡рд╕реВрд▓реА


рдмрдирд╛рдП рдЧрдП рдмреИрдХрдЕрдк рдкреНрд░рдмрдВрдзрд┐рдд рдХрд░реЗрдВ


рдЖрд╡рдзрд┐рдХ рдмреИрдХрдЕрдк


рдЪрд▓ рд░рд╣реЗ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдЯреНрд░реИрдХ рдХрд░реЗрдВ




рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░


рдореБрдЦреНрдп рдХрд╛рд░реНрдп 3 рд╕реЗрд╡рд╛рдУрдВ рдореЗрдВ рд╣реЛрдЧрд╛ - рдбреЗрдЯрд╛рдмреЗрд╕рдмреИрдХ , рдкреНрд░реЛрд╕реЗрд╕рд░ , рд╕реНрдЯреЛрд░реЗрдЬ , рдФрд░ рд╣рдо рдХрд╛рд░реНрдпреЛрдВ рдХреА рдЕрд╡рдзрд╛рд░рдгрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЙрдиреНрд╣реЗрдВ рдПрдХ рд╕рд╛рде рдЬреЛрдбрд╝ рджреЗрдВрдЧреЗред рдЗрд╕ рд╕рдм рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЖрдЧреЗред


DatabaseBackup


рдпрд╣ рд╕реЗрд╡рд╛ рд╕рд╛рджреЗ-рдкрд╛рда рдмреИрдХрдЕрдк рдмрдирд╛рдиреЗ рдФрд░ рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд╝рд┐рдореНрдореЗрджрд╛рд░ рд╣реИред


рд╕реЗрд╡рд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕:


public interface DatabaseBackup { InputStream createBackup(DatabaseSettings databaseSettings, Integer id); void restoreBackup(InputStream in, DatabaseSettings databaseSettings, Integer id); } 

рджреЛрдиреЛрдВ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдореЗрдердб рдЗрдирдкреБрдЯрд╕реНрдЯреНрд░реАрдо рдЗрдВрд╕реНрдЯреЗрдВрд╕ рдкрд░ рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВ, рдХреНрдпреЛрдВрдХрд┐ рд╣рдореЗрдВ рдореЗрдореЛрд░реА рдореЗрдВ рд▓реЛрдб рдирд╣реАрдВ рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП рдкреВрд░реЗ рдмреИрдХрдЕрдк рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рдмреИрдХрдЕрдк рдХреЛ рд╕реНрдЯреНрд░реАрдорд┐рдВрдЧ рдореЛрдб рдореЗрдВ рдкрдврд╝рд╛ / рд▓рд┐рдЦрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред DatabaseSettings рдЗрдХрд╛рдИ рд╡реЗрдм UI рд╕реЗ рдкреВрд░реНрд╡-рдирд┐рд░реНрдорд┐рдд рд╣реИ рдФрд░ рдбреЗрдЯрд╛рдмреЗрд╕ рддрдХ рдкрд╣реБрдБрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╡рд┐рднрд┐рдиреНрди рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рддрд╛ рд╣реИред рдпрд╣ рдкреИрд░рд╛рдореАрдЯрд░ рдХреНрдпрд╛ рд╣реИ - id - рдЖрдЧреЗ рдереЛрдбрд╝рд╛ рд╕рдордЭрд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛ред


рд╕реЗрд╡рд╛ рдЖрд╡рд╢реНрдпрдХрддрд╛рдПрдБ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реИрдВ:


  1. рджреЛрдиреЛрдВ рддрд░реАрдХреЛрдВ рдХреЛ рдкреВрд░реЗ рдмреИрдХрдЕрдк рдХреЛ рдореЗрдореЛрд░реА рдореЗрдВ рдирд╣реАрдВ рдкрдврд╝рдирд╛ рдЪрд╛рд╣рд┐рдПред
  2. restoreBackup() рд╡рд┐рдзрд┐ рдХреЛ рдПрдХрд▓ рд▓реЗрдирджреЗрди рдореЗрдВ рдмреИрдХрдЕрдк рдХреЛ рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП, рддрд╛рдХрд┐ рддреНрд░реБрдЯрд┐ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЛ рдЕрд╕рдВрдЧрдд рд╕реНрдерд┐рддрд┐ рдореЗрдВ рди рдЫреЛрдбрд╝реЗрдВред

PostgreSQL рдХреЗ рд▓рд┐рдП рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди (рдкрд╛рда рд╡рд┐рд╡рд░рдг)

рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ, PostgreSQL рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ, рд╕реЗрд╡рд╛ рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рд┐рдд рдХреА рдЬрд╛рддреА рд╣реИ:


  1. createBackup() : рдПрдХ pg_dump рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдмрдирд╛рдИ рдЬрд╛рддреА рд╣реИ рдЬреЛ рдПрдХ рдмреИрдХрдЕрдк рдмрдирд╛рдПрдЧреА рдФрд░ рдЗрд╕реЗ рдорд╛рдирдХ рдЖрдЙрдЯрдкреБрдЯ рд╕реНрдЯреНрд░реАрдо рдореЗрдВ рд▓рд┐рдЦ рджреЗрдЧреАред рдорд╛рдирдХ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдЖрдЙрдЯрдкреБрдЯ рд╕реНрдЯреНрд░реАрдо рд╡рд┐рдзрд┐ рд╕реЗ рд▓реМрдЯреА рд╣реИ ( https://docs.oracle.com/javase/8/docs/api/java/lang/Process.html#getInputStream-- рджреЗрдЦреЗрдВ )ред рд╕рд┐рд╕реНрдЯрдо рдореЗрдВ I / O рд╕реНрдЯреНрд░реАрдо рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рдЖрдХрд╛рд░ рдХреЗ рдмрдлрд░ рдкрд░ рдЖрдзрд╛рд░рд┐рдд рд╣реЛрддреЗ рд╣реИрдВ, рдФрд░ рдЬрдм рдХреЛрдИ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдЖрдЙрдЯрдкреБрдЯ рд╕реНрдЯреНрд░реАрдо рдХреЛ рд▓рд┐рдЦрддреА рд╣реИ, рддреЛ рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдореЗрдореЛрд░реА рдореЗрдВ рдмрдлрд░ рдХреЛ рд▓рд┐рдЦрддрд╛ рд╣реИред рдпрд╣рд╛рдВ рд╕рдмрд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдмрд╛рдд рдпрд╣ рд╣реИ рдХрд┐ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдзрд╛рдЧрд╛ рднрд░рд╛ рд╣реБрдЖ рдмрдлрд░ рддрдХ рдирд╣реАрдВ рд▓рд┐рдЦреЗрдЧрд╛, рдЬрдм рддрдХ рдХрд┐ рджреВрд╕рд░реА рддрд░рдл рд╕реЗ рдкрдврд╝рд╛ рдирд╣реАрдВ рдЧрдпрд╛ рд╣реИ, рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рдзрд╛рдЧрд╛ рдмрдВрдж рд╕реНрдерд┐рддрд┐ рдореЗрдВ рд╣реЛрдЧрд╛ рдФрд░ рдмреИрдХрдЕрдк рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдореЗрдореЛрд░реА рдореЗрдВ рд▓реЛрдб рдирд╣реАрдВ рд╣реЛрдЧрд╛ред рдЖрдкрдХреЛ рдРрд╕реА рд╕реНрдерд┐рддрд┐ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рдирд╛ рдкрдбрд╝ рд╕рдХрддрд╛ рд╣реИ рдЬрд╣рд╛рдВ рдЖрдкрдХреЗ рдЬрд╛рд╡рд╛ рдкреНрд░реЛрдЧреНрд░рд╛рдо рдиреЗ рдЗрд╕ рддрдереНрдп рдХреЗ рдХрд╛рд░рдг рдкреНрд░рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╕рдордп рдЧрддрд┐рд░реЛрдз рдкрдХрдбрд╝рд╛ рдерд╛ рдХрд┐ рдЖрдкрдиреЗ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЗ рд╕реНрдЯрдбрдЖрдЙрдЯ рдпрд╛ рд╕реНрдЯрдбрд░ рдХреЛ рдирд╣реАрдВ рдкрдврд╝рд╛ред рдЗрд╕рдХреА рдирд┐рдЧрд░рд╛рдиреА рдХрд░рдирд╛ рдмреЗрд╣рдж рдЬрд░реВрд░реА рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдкреВрд░реНрдг рдмрдлрд░ рдореЗрдВ рд▓рд┐рдЦрддреЗ рд╕рдордп I / O рдмреНрд▓реЙрдХрд┐рдВрдЧ рдХреЙрд▓ рдкрд░ рдмреНрд▓реЙрдХ рд╣реЛрдиреЗ рдкрд░ рдпрд╣ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдЬрд╛рд░реА рдирд╣реАрдВ рд░рд╣ рд╕рдХрддреА рд╣реИ рдФрд░ рдХреЛрдИ рднреА рдЗрд╕ рдмрдлрд░ рдХреЛ рдирд╣реАрдВ рдкрдврд╝рддрд╛ рд╣реИред
  2. restoreBackup() : рдПрдХ psql рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдмрдирд╛рдИ рдЬрд╛рддреА рд╣реИ, рдмреИрдХрдЕрдк рдкрджреНрдзрддрд┐ рд╕реЗ рдкрд╛рд░рд┐рдд restoreBackup() рд╕реЗ рдкрдврд╝рд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рд╕рд╛рде рдореЗрдВ psql рдорд╛рдирдХ рдЗрдирдкреБрдЯ рд╕реНрдЯреНрд░реАрдо ( https://docs.oracle.com/javase/8/docs/api/java/lang/Process) рдкрд░ рд▓рд┐рдЦрд╛ рдЬрд╛рддрд╛ рд╣реИ ред html # getOutputStream-- )ред рдпрд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рд╕рд╛рджрд╛-рдкрд╛рда PostgreSQL рдмреИрдХрдЕрдк рдХреЗрд╡рд▓ DDL рдФрд░ DML рдХрдорд╛рдВрдб рдХрд╛ рдПрдХ рд╕рдВрдЧреНрд░рд╣ рд╣реИ рдЬреЛ psql рдХреЛ рд╕рдордЭрдирд╛ рдЖрд╕рд╛рди рд╣реИред

рдмрд╣реБрдд рдХреЛрдб рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореИрдВрдиреЗ рдЗрд╕реЗ рдпрд╣рд╛рдВ рдирд╣реАрдВ рджрд┐рдпрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЖрдк рдЗрд╕реЗ рд▓реЗрдЦ рдХреЗ рдЕрдВрдд рдореЗрдВ рд▓рд┐рдВрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЧрд┐рдЯрд╣рдм рдкрд░ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВред


рдкреНрд░реЛрд╕реЗрд╕рд░


рдпрд╣ рд╕реЗрд╡рд╛ рдкреНрд░реЛрд╕реЗрд╕рд░ рдФрд░ рд░рд┐рд╡рд░реНрд╕ рдмреИрдХрдЕрдк рд░реАрдкреНрд░реЛрд╕реЗрд╕рд┐рдВрдЧ рдХреЗ рдЙрдкрдпреЛрдЧ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реИред рднрдВрдбрд╛рд░рдг рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдпрд╛ рднрдВрдбрд╛рд░рдг рд╕реЗ рдЙрддрд╛рд░рдиреЗ рдХреЗ рдмрд╛рдж рдкреНрд░реЛрд╕реЗрд╕рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдкреНрд░реЛрд╕реЗрд╕рд░ рдЙрджрд╛рд╣рд░рдг: рдХрдВрдкреНрд░реЗрд╕рд░, рдПрдиреНрдХреНрд░рд┐рдкреНрд╢рдиред


рд╕реЗрд╡рд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕:


 public interface Processor { InputStream process(InputStream in); InputStream deprocess(InputStream in); ProcessorType getType(); // ProcessorType -  Enum,     int getPrecedence(); //   } 

рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░реЛрд╕реЗрд╕рд░ рдореЗрдВ рдкреНрд░рд╛рдердорд┐рдХрддрд╛ рд╣реЛрддреА рд╣реИ - рдпрджрд┐ рдХрдИ рдкреНрд░реЛрд╕реЗрд╕рд░ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рд╣реИрдВ, рддреЛ рдЙрдиреНрд╣реЗрдВ рдкреНрд░рд╛рдердорд┐рдХрддрд╛ рдХреЗ рдЕрд╡рд░реЛрд╣реА рдХреНрд░рдо рдореЗрдВ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдЙрд▓рдЯрд╛ рдлрд╝рдВрдХреНрд╢рди рдЙрд╕реА рдХреНрд░рдо рдореЗрдВ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рдЬрд┐рд╕рдореЗрдВ рдкреНрд░реЛрд╕реЗрд╕рд░ рд▓рдЧрд╛рдП рдЧрдП рдереЗ, рд╣рдореЗрдВ рдореВрд▓ рдмреИрдХрдЕрдк рдорд┐рд▓рддрд╛ рд╣реИред


рднрдВрдбрд╛рд░рдг


рдпрд╣ рд╕реЗрд╡рд╛ рдмреИрдХрдЕрдк рдХреЛ рд▓реЛрдб рдХрд░рдиреЗ рдФрд░ рдЙрддрд╛рд░рдиреЗ рдХреЗ рд╕рд╛рде-рд╕рд╛рде рднрдВрдбрд╛рд░рдг рд╕реЗ рд╣рдЯрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реИред рднрдВрдбрд╛рд░рдг рдЙрджрд╛рд╣рд░рдг: рдбреНрд░реЙрдкрдмреЙрдХреНрд╕, рд╕реНрдерд╛рдиреАрдп рдлрд╝рд╛рдЗрд▓ рд╕рд┐рд╕реНрдЯрдоред


рд╕реЗрд╡рд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕:


 public interface Storage { void uploadBackup(InputStream in, StorageSettings storageSettings, String backupName, Integer id); InputStream downloadBackup(StorageSettings storageSettings, String backupName, Integer id); void deleteBackup(StorageSettings storageSettings, String backupName, Integer id); } 

рдкреНрд░рддреНрдпреЗрдХ рдмрдирд╛рдП рдЧрдП рдмреИрдХрдЕрдк рдХреЛ рдПрдХ рдЕрджреНрд╡рд┐рддреАрдп рдирд╛рдо рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ - рдЗрд╕рд▓рд┐рдП рд╣рдо рдЗрд╕реЗ рдХрд┐рд╕реА рднреА рд╕реНрдЯреЛрд░реЗрдЬ рдкрд░ рдкрд╛ рд╕рдХрддреЗ рд╣реИрдВ, рдЬрд┐рд╕реЗ рдпрд╣ рдбрд╛рдЙрдирд▓реЛрдб рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдЬрд┐рд╕ рддрд░рд╣ рд╕реЗ рдмреИрдХрдЕрдк рдХреЛ рд╕реНрдЯреЛрд░реЗрдЬ рдХреЗ рд▓рд┐рдП рдкреНрд░рд╕реНрддреБрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рд╡рд╣ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рд╕реЗрд╡рд╛ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХрд╛ рдорд╛рдорд▓рд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЬрдм рдмреИрдХрдЕрдк рдирд╛рдо рдХреЛ рдХрд┐рд╕реА рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рд╣рдореЗрдВ рд╕рд╣реА рд╡реНрдпрд╡рд╣рд╛рд░ рдХреА рдЙрдореНрдореАрдж рдХрд░рдиреА рдЪрд╛рд╣рд┐рдПред StorageSettings рдЗрдХрд╛рдИ рд╡реЗрдм UI рд╕реЗ рдкрд╣рд▓реЗ рд╕реЗ рдмрдирд╛рдИ рдЧрдИ рд╣реИ рдФрд░ рднрдВрдбрд╛рд░рдг рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рддреА рд╣реИред




рдХрд╛рд░реНрдп рдЕрд╡рдзрд╛рд░рдгрд╛


рд╣рдо рдЕрдкрдиреЗ рдХрд╛рд░реНрдпреЛрдВ рдХреА рд╕реНрдерд┐рддрд┐ рдХреЛ рдЯреНрд░реИрдХ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рдХрд╛рд░реНрдп рдХреА рдкреНрд░рдЧрддрд┐ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рд╕рдВрднрд╛рд╡рд┐рдд рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рд╕рдВрднрд╛рд▓ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рд░рджреНрдж рднреА рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЗрд╕рд▓рд┐рдП, рд╣рдо рдХреЗрд╡рд▓ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛ рдЬрд╛рд░реА рд░рдЦреЗрдВрдЧреЗред рдкреНрд░рддреНрдпреЗрдХ рдХрд╛рд░реНрдп рдХреЛ рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ рд░рд┐рдХреЙрд░реНрдб рджреНрд╡рд╛рд░рд╛ рдФрд░ рднрд╡рд┐рд╖реНрдп рдХреЗ рдЙрджрд╛рд╣рд░рдг (рдЬрд╛рд╡рд╛ рднрд╡рд┐рд╖реНрдп рдХреЛ рджреЗрдЦреЗрдВ) рджреНрд╡рд╛рд░рд╛ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдХ рд░реВрдк рд╕реЗ рджрд░реНрд╢рд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рд░рд┐рдХреЙрд░реНрдб рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рднрд╡рд┐рд╖реНрдп рд╕реЗ рдЬреБрдбрд╝рд╛ рд╣реБрдЖ рд╣реИ (рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдпрджрд┐ рдХрдИ рд╕рд░реНрд╡рд░ рдЪрд▓ рд░рд╣реЗ рд╣реИрдВ, рддреЛ рднрд╡рд┐рд╖реНрдп рдХреЗ рдЙрджрд╛рд╣рд░рдг рд╡рд┐рднрд┐рдиреНрди рд╕рд░реНрд╡рд░реЛрдВ рдХреА рд╕реНрдореГрддрд┐ рдореЗрдВ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ)ред


рдХреНрд░рдо рд╕реЗ рдЪрд▓рддреЗ рд╣реИрдВред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдореЗрдВ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рд▓реЙрдиреНрдЪ рдХрд░рдиреЗ, рдмреИрдХрдЕрдк рдмрдирд╛рдиреЗ, рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдФрд░ рд╣рдЯрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕реЗрд╡рд╛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред


рдХрд╛рд░реНрдп рдХрд╛ рд╢реБрднрд╛рд░рдВрдн


рдПрдХ рдмреИрдХрдЕрдк рдмрдирд╛рдирд╛:


 public Task startBackupTask(@NotNull Task.RunType runType, @NotNull List<String> storageSettingsNameList, @Nullable List<ProcessorType> processors, @NotNull DatabaseSettings databaseSettings) { Objects.requireNonNull(runType); Objects.requireNonNull(storageSettingsNameList); Objects.requireNonNull(processors); Objects.requireNonNull(databaseSettings); BackupProperties backupProperties = backupPropertiesManager.initNewBackupProperties(storageSettingsNameList, processors, databaseSettings.getName()); Task task = tasksManager.initNewTask(Task.Type.CREATE_BACKUP, runType, backupProperties.getId()); Integer taskId = task.getId(); Future future = tasksStarterExecutorService.submit(() -> { tasksManager.updateTaskState(taskId, Task.State.CREATING); logger.info("Creating backup..."); try (InputStream backupStream = databaseBackupManager.createBackup(databaseSettings, taskId)) { if (Thread.interrupted()) { throw new InterruptedException(); } tasksManager.updateTaskState(taskId, Task.State.APPLYING_PROCESSORS); logger.info("Applying processors on created backup. Processors: {}", processors); try (InputStream processedBackupStream = backupProcessorManager.process(backupStream, processors)) { if (Thread.interrupted()) { throw new InterruptedException(); } tasksManager.updateTaskState(taskId, Task.State.UPLOADING); logger.info("Uploading backup..."); backupLoadManager.uploadBackup(processedBackupStream, backupProperties, taskId); if (Thread.interrupted()) { throw new InterruptedException(); } tasksManager.updateTaskState(taskId, Task.State.COMPLETED); logger.info("Creating backup completed. Backup properties: {}", backupProperties); } } catch (IOException ex) { logger.error("Error occurred while closing input stream of created backup", ex); } catch (RuntimeException ex) { logger.error("Error occurred while creating backup. Backup properties: {}", backupProperties, ex); errorTasksManager.addErrorTask(taskId); } catch (InterruptedException ex) { tasksManager.setInterrupted(taskId); logger.error("Backup creating task was interrupted. Task ID: {}", taskId); } finally { futures.remove(taskId); } }); futures.put(taskId, future); return task; } 

рдПрдХ рдмреИрдХрдЕрдк рдмрдирд╛рдирд╛ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреНрд░рдо рдореЗрдВ 3 рдореБрдЦреНрдп рдЪрд░рдгреЛрдВ рд╕реЗ рдЧреБрдЬрд░рддрд╛ рд╣реИ: рдПрдХ рдмреИрдХрдЕрдк -> рдкреНрд░реЛрд╕реЗрд╕рд░ рдХрд╛ рдЕрдиреБрдкреНрд░рдпреЛрдЧ -> рд╕реНрдЯреЛрд░реЗрдЬ рдкрд░ рдЕрдкрд▓реЛрдб рдХрд░реЗрдВред рд▓рдЧрднрдЧ рд╕рднреА рд╕реЗрд╡рд╛ рд╡рд┐рдзрд┐рдпреЛрдВ рдореЗрдВ, рд╣рдо рд╡рд░реНрддрдорд╛рди рдХрд╛рд░реНрдп рдХреА рдЖрдИрдбреА рдХреЛ рдЕрдЧреНрд░реЗрд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ рддрд╛рдХрд┐ рд╕реЗрд╡рд╛ рдкреГрд╖реНрдарднреВрдорд┐ рдореЗрдВ рдХрд╛рдо рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдереНрд░реЗрдб рд╕реЗ рдПрдХ рддреНрд░реБрдЯрд┐ рдХреА рд░рд┐рдкреЛрд░реНрдЯ рдХрд░ рд╕рдХреЗред рддреНрд░реБрдЯрд┐ рд╕реЗ рдирд┐рдкрдЯрдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ, рдХреНрдпреЛрдВ рдпрд╣рд╛рдБ InterruptedException рд╣реИ рдФрд░ рдПрдХ RuntimeException рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рдПрдХ рддреНрд░реБрдЯрд┐ рдХреЗ рд╕рд╛рде рдХреНрдпрд╛ рд╣реЛрддрд╛ рд╣реИ, рдЗрд╕ рдкрд░ рдмрд╛рдж рдореЗрдВ рдЪрд░реНрдЪрд╛ рдХреА рдЬрд╛рдПрдЧреАред


рдФрд░ рдпрд╣рд╛рдВ рдмрддрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ рдХрд┐ рд╣рдо рдмреИрдХрдЕрдк рдмрдирд╛рдиреЗ рдХрд╛ рдХрд╛рд░реНрдп рдХреИрд╕реЗ рдХрд░реЗрдВрдЧреЗ:


 tasksStarterService.startBackupTask(Task.RunType.USER, storageSettingsNameList, processors, databaseSettings); 

рдкрд╣рд▓рд╛ рдкреИрд░рд╛рдореАрдЯрд░ рд╣рдо рдХрд╛рд░реНрдп рдХреЗ рд╕рд░реНрдЬрдХ рдХреЛ рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ: рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдпрд╛ рдЖрдВрддрд░рд┐рдХ рд╕рд░реНрд╡рд░ рдХрд╛рд░реНрдп (рдЖрдВрддрд░рд┐рдХ рдХрд╛рд░реНрдп рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдПрдХ рдЖрд╡рдзрд┐рдХ рдмреИрдХрдЕрдк рд╣реИ)ред рдХрд╛рд░реНрдп рдЖрд░рдВрднрдХрд░реНрддрд╛ рдХрд╛ рдЬреНрдЮрд╛рди рд╣рдореЗрдВ рд╡реЗрдм рдпреВрдЖрдИ рдореЗрдВ рдХреЗрд╡рд▓ рдЙрди рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рджрд┐рдЦрд╛рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ рдЬреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рджреНрд╡рд╛рд░рд╛ рд▓реЙрдиреНрдЪ рдХрд┐рдП рдЧрдП рдереЗред рд╢реЗрд╖ рдкреИрд░рд╛рдореАрдЯрд░ рд╕реАрдзреЗ рдмреИрдХрдЕрдк рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╣реИрдВ - рднрдВрдбрд╛рд░рдг рдХреА рдПрдХ рд╕реВрдЪреА, рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░реЛрд╕реЗрд╕рд░, рдПрдХ рдбреЗрдЯрд╛рдмреЗрд╕ рдЬрд┐рд╕рдХрд╛ рдбрдВрдк рдЖрдкрдХреЛ рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред


рдмреИрдХрдЕрдк рдмрдирд╛рддреЗ рд╕рдордп, рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рдПрдХ рд░рд┐рдХреЙрд░реНрдб рднреА рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬрд┐рд╕реЗ BackupProperties рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрд╣ рдЗрдХрд╛рдИ рдмреИрдХрдЕрдк рдЧреБрдг рдЬреИрд╕реЗ рдирд╛рдо, рдкреНрд░реЛрд╕реЗрд╕рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдФрд░ рднрдВрдбрд╛рд░ рдХреА рд╕реВрдЪреА, рдЬрд┐рд╕рдореЗрдВ рдмреИрдХрдЕрдк рдбрд╛рдЙрдирд▓реЛрдб рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдХреЛ рд╕рдВрдЧреНрд░рд╣рд┐рдд рдХрд░реЗрдЧреАред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдмреИрдХрдЕрдк рдХреЛ рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдпрд╛ рд╣рдЯрд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдЗрд╕ рд╡рд┐рд╢реЗрд╖ рдЗрдХрд╛рдИ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░реЗрдВрдЧреЗред


рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рдХрд╛рд░реНрдп рдирд┐рдореНрди рд░реВрдк рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рд╣реИ:


 @Entity @Table(name = "backup_tasks") public class Task { /** * Identifier of each backup task. Identifier is generated by PostgreSQL database after saving of entity. */ @Id @Column(insertable = false, updatable = false) @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; /** * Backup task type. * <p> * Type is set at the very start of any task and can't be changed. * * @see Type */ @Enumerated(EnumType.STRING) @Column(updatable = false) private Type type; /** * Who initiated a task: user or server. * <p> * We need to know it to show on front only these tasks that was started by user. * * @see RunType */ @Enumerated(EnumType.STRING) @Column(updatable = false) private RunType runType; /** * Backup task state. * <p> * State is updated with every new step in task being executed. * * @see Task.State */ @Enumerated(EnumType.STRING) private State state; /** * Whether task has been interrupted or not. * <p> * Default is {@literal false}. */ @Column(insertable = false) private boolean interrupted; /** * Identifier of {@link BackupProperties}. * <p> * We need to know backup ID to be able to handle occurred errors. */ @Column(updatable = false) private Integer backupPropertiesId; /** * Start time of the task. */ @Column(updatable = false) private LocalDateTime date; public enum RunType { USER, INTERNAL } public enum State { PLANNED, CREATING, RESTORING, DELETING, APPLYING_PROCESSORS, APPLYING_DEPROCESSORS, DOWNLOADING, UPLOADING, COMPLETED, } public enum Type { CREATE_BACKUP { @Override public String toString() { return "CREATE BACKUP"; } }, RESTORE_BACKUP { @Override public String toString() { return "RESTORE BACKUP"; } }, DELETE_BACKUP { @Override public String toString() { return "DELETE BACKUP"; } } } // getters & setters... } 

рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдЖрдк рдЪрд┐рддреНрд░ рдХреЗ рд░реВрдк рдореЗрдВ рдПрдХ рдмреИрдХрдЕрдк рдмрдирд╛рдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд╛ рд╡рд░реНрдгрди рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
рдмреИрдХрдЕрдк рдкреНрд░рдХреНрд░рд┐рдпрд╛




рдЕрдиреНрдп рдкреНрд░рдХрд╛рд░ рдХреЗ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рд╕рд╛рджреГрд╢реНрдп рджреНрд╡рд╛рд░рд╛ рд▓реЙрдиреНрдЪ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдХреЛрдб рдХреА рдПрдХ рдмрдбрд╝реА рд░рд╛рд╢рд┐ рдХреЗ рд╕рд╛рде рд▓реЗрдЦ рдХреЛ рдЕрд╡реНрдпрд╡рд╕реНрдерд┐рдд рдирд╣реАрдВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЬрд┐рдЬреНрдЮрд╛рд╕реБ рдХреЗ рд▓рд┐рдП рдореИрдВ рдХреЛрдб рдХреЛ рд╕реНрдкреЙрдЗрд▓рд░ рдореЗрдВ рдЕрд▓рдЧ рд╕реЗ рдмреИрдХрдЕрдк рдХреЛ рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдФрд░ рд╣рдЯрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд▓реЙрдиреНрдЪ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреЛрдб рджреВрдВрдЧрд╛ред


рдмреИрдХрдЕрдк рд╡рд╕реВрд▓реА
 public Task startRestoreTask(@NotNull Task.RunType runType, @NotNull BackupProperties backupProperties, @NotNull String storageSettingsName, @NotNull DatabaseSettings databaseSettings) { Objects.requireNonNull(runType); Objects.requireNonNull(backupProperties); Objects.requireNonNull(storageSettingsName); Objects.requireNonNull(databaseSettings); Task task = tasksManager.initNewTask(Task.Type.RESTORE_BACKUP, runType, backupProperties.getId()); Integer taskId = task.getId(); Future future = tasksStarterExecutorService.submit(() -> { tasksManager.updateTaskState(taskId, Task.State.DOWNLOADING); logger.info("Downloading backup..."); try (InputStream downloadedBackup = backupLoadManager.downloadBackup(backupProperties.getBackupName(), storageSettingsName, taskId)) { if (Thread.interrupted() || downloadedBackup == null) { throw new InterruptedException(); } tasksManager.updateTaskState(taskId, Task.State.APPLYING_DEPROCESSORS); logger.info("Deprocessing backup..."); try (InputStream deprocessedBackup = backupProcessorManager.deprocess(downloadedBackup, backupProperties.getProcessors())) { if (Thread.interrupted()) { throw new InterruptedException(); } tasksManager.updateTaskState(taskId, Task.State.RESTORING); logger.info("Restoring backup..."); databaseBackupManager.restoreBackup(deprocessedBackup, databaseSettings, taskId); if (Thread.interrupted()) { throw new InterruptedException(); } tasksManager.updateTaskState(taskId, Task.State.COMPLETED); logger.info("Restoring backup completed. Backup properties: {}", backupProperties); } } catch (IOException ex) { logger.error("Error occurred while closing input stream of downloaded backup", ex); } catch (RuntimeException ex) { logger.info("Error occurred while restoring backup. Backup properties: {}", backupProperties, ex); errorTasksManager.addErrorTask(taskId); } catch (InterruptedException ex) { tasksManager.setInterrupted(taskId); logger.error("Task was interrupted. Task ID: {}", taskId); } finally { futures.remove(taskId); } }); futures.put(taskId, future); return task; } 

рдПрдХ рдмреИрдХрдЕрдк рдХреЛ рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░рдирд╛ рдирд┐рдореНрди рдХреНрд░рдо рдореЗрдВ 3 рдореБрдЦреНрдп рдЪрд░рдгреЛрдВ рд╕реЗ рдЧреБрдЬрд░рддрд╛ рд╣реИ: рд╕реНрдЯреЛрд░реЗрдЬ рд╕реЗ рдмреИрдХрдЕрдк рдХреЛ рдЕрдирд▓реЛрдб рдХрд░рдирд╛ -> рдореВрд▓ рд╕рд╛рджреЗ-рдЯреЗрдХреНрд╕реНрдЯ рдмреИрдХрдЕрдк рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдбрд┐рдкреЙрдЬрд┐рдЯрд░реНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ -> рдмреИрдХрдЕрдк рдХреЛ рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░рдирд╛ред


рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рд╡рд╕реВрд▓реА рд╢реБрд░реВ рдХрд░реЗрдВ:


 tasksStarterService.startRestoreTask(Task.RunType.USER, backupProperties, storageSettingsName, databaseSettings); 

рдЖрд░реЗрдЦ рдХреЗ рд░реВрдк рдореЗрдВ рдПрдХ рдмреИрдХрдЕрдк рдХреЛ рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛:
рдмреИрдХрдЕрдк рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрддрд┐ рдкреНрд░рдХреНрд░рд┐рдпрд╛


рдмреИрдХрдЕрдк рд╣рдЯрд╛рдПрдВ
 public Task startDeleteTask(@NotNull Task.RunType runType, @NotNull BackupProperties backupProperties) { Objects.requireNonNull(runType); Objects.requireNonNull(backupProperties); Task task = tasksManager.initNewTask(Task.Type.DELETE_BACKUP, runType, backupProperties.getId()); Integer taskId = task.getId(); Future future = tasksStarterExecutorService.submit(() -> { try { logger.info("Deleting backup started. Backup properties: {}", backupProperties); tasksManager.updateTaskState(taskId, Task.State.DELETING); backupLoadManager.deleteBackup(backupProperties, taskId); if (Thread.interrupted()) { throw new InterruptedException(); } tasksManager.updateTaskState(taskId, Task.State.COMPLETED); logger.info("Deleting backup completed. Backup properties: {}", backupProperties); } catch (RuntimeException ex) { logger.error("Error occurred while deleting backup. Backup properties: {}", backupProperties, ex); errorTasksManager.addErrorTask(taskId); } catch (InterruptedException ex) { tasksManager.setInterrupted(taskId); logger.error("Task was interrupted. Task ID: {}", taskId); } finally { futures.remove(taskId); } }); futures.put(taskId, future); return task; } 

рдмреИрдХрдЕрдк рд╣рдЯрд╛рдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд╛рдлреА рд╕рд░рд▓ рд╣реИ: рдПрдХ рдмреИрдХрдЕрдк рдХреЛ рдЙрди рд╕рднреА рд╕реНрдЯреЛрд░реЗрдЬ рд╕реЗ рдбрд┐рд▓реАрдЯ рдХрд░ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬрд┐рдиреНрд╣реЗрдВ рдпрд╣ рдбрд╛рдЙрдирд▓реЛрдб рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред


рд╕реНрдерд╛рдкрдирд╛ рд░рджреНрдж рдХрд░реЗрдВ рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рдЪрд▓рд╛рдПрдБ:


 tasksStarterService.startDeleteTask(Task.RunType.USER, backupProperties); 

рдЖрд░реЗрдЦ рдХреЗ рд░реВрдк рдореЗрдВ рдПрдХ рдмреИрдХрдЕрдк рд╣рдЯрд╛рдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛:
рдмреИрдХрдЕрдк рд╣рдЯрд╛рдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛




рдХрд╛рд░реНрдп рд░рджреНрдж рдХрд░реЗрдВ


рдХрд╛рд░реНрдп рдирд┐рд░рд╕реНрддреАрдХрд░рдг рдХреНрдпрд╛ рд╣реИ? рдмреЗрд╢рдХ, рдпрд╣ рдПрдХ рдереНрд░реЗрдб рд╕рдорд╛рдкреНрддрд┐ рд╕реЗ рдЬреНрдпрд╛рджрд╛ рдХреБрдЫ рдирд╣реАрдВ рд╣реИред рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдлреНрдпреВрдЪрд░ рдореЗрдВ рдЪрд▓ рд░рд╣реЗ рд╕рднреА рдореБрдЦреНрдп рдХреЛрдб рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЯреНрд░рд╛рдЗ-рдХреИрдЪ рдирд┐рд░реНрдорд╛рдг рдореЗрдВ рд▓рд┐рдкрдЯреЗ рд╣реБрдП рд╣реИрдВ:


 try { ... } catch (InterruptedException ex) { ... tasksManager.setInterrupted(taskId); } 

рдФрд░ рдкреНрд░рддреНрдпреЗрдХ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╡рд┐рдзрд┐ рдХреЗ рдмрд╛рдж, рдирд┐рд╖реНрдкрд╛рджрди рдкреНрд░рд╡рд╛рд╣, рдЬрд┐рд╕реЗ рд╣рдо рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдирд┐рд░реНрдорд╛рдг рд╕реНрдерд╛рдкрд┐рдд рд╣реИ:


 if (Thread.interrupted()) { throw new InterruptedException(); } 

рдЖрдЧреЗ рдмрдврд╝рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рдЬреЗрд╡реАрдПрдо рдереНрд░реЗрдбреНрд╕ рдХреЗ рд░реБрдХрд╛рд╡рдЯреЛрдВ рдФрд░ рд░рд╛рдЬреНрдпреЛрдВ рдХрд╛ рдПрдХ рд╕рдВрдХреНрд╖рд┐рдкреНрдд рд╕рд┐рджреНрдзрд╛рдВрдд рджрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред


JVM рдореЗрдВ рдереНрд░реЗрдбреНрд╕ рдирд┐рдореНрди рдЕрд╡рд╕реНрдерд╛рдПрдБ рд╣реЛ рд╕рдХрддреА рд╣реИрдВ:


  1. рдирдИ
  2. runnable
  3. рд╕рдордп рдХрд╛ рдЗрдВрддрдЬрд╛рд░ рдХрд┐рдпрд╛
  4. рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░ рд░рд╣рд╛ рд╣реИ
  5. рдЕрд╡рд░реЛрдзрд┐рдд
  6. рд╕рдорд╛рдкреНрдд

рд╣рдо рдХреЗрд╡рд▓ рд╡реЗрдЯрд┐рдВрдЧ рдФрд░ рдЯрд╛рдЗрдорд┐рдВрдЧ рдкреНрд░рддреАрдХреНрд╖рд╛ рд╡рд╛рд▓реЗ рд░рд╛рдЬреНрдпреЛрдВ рдореЗрдВ рд░реБрдЪрд┐ рд░рдЦрддреЗ рд╣реИрдВред Object.wait() рд╡реЗрдЯрд┐рдВрдЧ рд╕реНрдерд┐рддрд┐ рдореЗрдВ Object.wait() рдЧрдпрд╛ рд╣реИ Object.wait() , Thread.join() рдФрд░ рдЕрдиреНрдп рддрд░реАрдХреЛрдВ рд╕реЗред рдереНрд░реЗрдб рдХреЛ рд╕рдордпрдмрджреНрдз рдкреНрд░рддреАрдХреНрд╖рд╛ рд╕реНрдерд┐рддрд┐ рдореЗрдВ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ (рдпрд╛рдиреА, рдПрдХ рдкреНрд░рддреАрдХреНрд╖рд╛ рдЬреЛ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рдЕрд╡рдзрд┐ рддрдХ рдЪрд▓рддреА рд╣реИ) Object.wait(timeout) , Thread.join(timeout) , Thread.sleep(sleeping) рдФрд░ рдЕрдиреНрдп рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдПред


рдпрд╣рд╛рдВ рд╕рдмрд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдмрд╛рдд рдпрд╣ рд╣реИ рдХрд┐ рдпрджрд┐ рдЖрдк рдкреНрд░рддреАрдХреНрд╖рд╛ рдпрд╛ рд╕рдордп рдХреА рдкреНрд░рддреАрдХреНрд╖рд╛ рдХреА рд╕реНрдерд┐рддрд┐ рдореЗрдВ рдкреНрд░рд╡реЗрд╢ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдзрд╛рдЧреЗ рдХреЛ рдмрд╛рдзрд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдпрд╛ рдЬрдм рдзрд╛рдЧрд╛ рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ рд╣реЛрддрд╛ рд╣реИ , рддреЛ рдереНрд░реЗрдб рдЬрд╛рдЧ рдЬрд╛рддрд╛ рд╣реИ, рдПрдХ рдЗрдВрдЯрд░рдкреНрдЯреЗрдбрдПрдХреНрд╕рд▓рд╛рдЗрдЯ рдХреЛ рдлреЗрдВрдХ рджреЗрддрд╛ рд╣реИред


рд▓реЗрдХрд┐рди рдпрд╣ рд╕рдм рдирд╣реАрдВ рд╣реИред рдпрд╣ рдмрд┐рд▓реНрдХреБрд▓ рднреА рдирд╣реАрдВ рд╣реИ рдХрд┐ рдПрдХ рдереНрд░реЗрдб рдмреИрдХрдЕрдк рдмрдирд╛рдиреЗ, рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдпрд╛ рд╣рдЯрд╛рдиреЗ рдХреЗ рджреНрд╡рд╛рд░рд╛ рдХрднреА рднреА рд╕реНрдЯреЗрдЯ рдбреЗрдЯрд╛ рдореЗрдВ рдЬрд╛рдПрдЧрд╛ред рдлрд┐рд░ рдереНрд░реЗрдб рдХреЛ рдХреИрд╕реЗ рд╕реВрдЪрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдП рдХрд┐ рдпрд╣ рдмрд╛рдзрд┐рдд рдерд╛?


рдкрд╣рд▓рд╛ рддрд░реАрдХрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдереНрд░реЗрдб.interrupted Thread.interrupted() рдпрд╛ Thread.currentThread.isInterrupted() рд╡рд┐рдзрд┐рдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдереНрд░реЗрдб рдХреЗ рд╕рд╛рде рдЗрдВрдЯрд░рдкреНрдЯ рдлрд╝реНрд▓реИрдЧ рдХреЛ рд╕реНрд╡рддрдВрддреНрд░ рд░реВрдк рд╕реЗ рджреЗрдЦреЗрдВред рджреЛрдиреЛрдВ рдХреЗ рдмреАрдЪ рдХрд╛ рдЕрдВрддрд░ рдпрд╣ рд╣реИ рдХрд┐ рдкрд╣рд▓реЗ рдирд┐рдЬреА рджреЗрд╢реА рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИ currentThread.isInterrupted(boolean ClearInterrupted) , рдпрд╣ true рд╣реИ, рдпрд╣ рджрд░реНрд╢рд╛рддрд╛ рд╣реИ рдХрд┐ рд░реБрдХрд╛рд╡рдЯ рдХрд╛ рдЭрдВрдбрд╛ рд╕рд╛рдл рд╣реЛ рдЬрд╛рдПрдЧрд╛, рдФрд░ рджреВрд╕рд░рд╛ рдЧреБрдЬрд░рдиреЗ рд╡рд╛рд▓рд╛ false , рдмреАрдЪ рдореЗрдВ рдЖрдиреЗ рд╡рд╛рд▓реЗ рдЭрдВрдбреЗ рдХреЛ рдЕрдЫреВрддрд╛ рдЫреЛрдбрд╝ рджреЗрдЧрд╛ред рдЗрди рджреЛ рддрд░реАрдХреЛрдВ рдХреЗ рдмреАрдЪ рдХрд╛ рдЪреБрдирд╛рд╡ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╕реНрдерд┐рддрд┐ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИред рдЬрдм рдПрдХ InterruptedException рдХреЛ рдлреЗрдВрдХ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдмрд╛рдзрд╛ рдЭрдВрдбрд╛ рднреА рд╕рд╛рдлрд╝ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ - рдпрд╣ рдпрд╛рдж рд░рдЦрдиреЗ рдпреЛрдЧреНрдп рд╣реИред


рд▓реЗрдХрд┐рди рдПрдХ рд░рд╛рд╕реНрддрд╛ рдЖрд╕рд╛рди рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП - рдФрд░ рдпрд╣ рд╣реИред рдЖрд╡реЗрджрди рдореЗрдВ, I / O рдзрд╛рд░рд╛рдУрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХреА рдПрдХ рдмрдбрд╝реА рдорд╛рддреНрд░рд╛ рд╣реИ, рдФрд░ рдЗрд╕рд▓рд┐рдП I / O рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рдеред рд╣рдорд╛рд░рд╛ рдХрд╛рд░реНрдп рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдирд╛ рд╣реИ рдХрд┐ рдЖрдИ / рдУ рд╕реНрдЯреНрд░реАрдо рдкрд░ read() рдпрд╛ write(int b) рддрд░реАрдХреЛрдВ рдХреЛ рдХреЙрд▓ рдХрд░рддреЗ рд╕рдордп, рдПрдХ рддреНрд░реБрдЯрд┐ рдХреЛ рд░реБрдХрд╛рд╡рдЯ рдХреЗ рджреМрд░рд╛рди рдлреЗрдВрдХ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдпрд╣ рд╕реВрдЪрд┐рдд рдХрд░рддреЗ рд╣реБрдП рдХрд┐ рдЕрд╡рд░реБрджреНрдз рдЖрдИ / рдУ рдХреЙрд▓ рдмрд╛рдзрд┐рдд рд╣реЛ рдЧрдпрд╛ рдерд╛ред рд╕реМрднрд╛рдЧреНрдп рд╕реЗ, рдЬрд╛рд╡рд╛ рдореЗрдВ рдРрд╕рд╛ рдЕрдкрд╡рд╛рдж рд╣реИ - InterruptedIOException ред рд╣рд╛рд▓рд╛рдБрдХрд┐, рд╕рднреА рдкрдарди / рд▓реЗрдЦрди рдзрд╛рд░рд╛ рд╡рд┐рдзрд┐рдпрд╛рдБ рдзрд╛рдЧрд╛ рдЕрд╡рд░реЛрдзреЛрдВ рдХреА рдирд┐рдЧрд░рд╛рдиреА рдирд╣реАрдВ рдХрд░рддреА рд╣реИрдВ, рдФрд░ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдХреЗрд╡рд▓ PipedInputStream рдЗрд╕рдХреА рдирд┐рдЧрд░рд╛рдиреА рдХрд░рддрд╛ рд╣реИред рдЗрд╕рд▓рд┐рдП, рдЙрди рдЬрдЧрд╣реЛрдВ рдкрд░ рдЬрд╣рд╛рдВ рдпрд╣ рдзрд╛рд░рд╛ рд╢рд╛рдорд┐рд▓ рдирд╣реАрдВ рд╣реИ, рд╣рдореЗрдВ рд░реАрдб / рд░рд╛рдЗрдЯ рд╡рд┐рдзрд┐ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП рддрд╛рдХрд┐ рдЬрдм рдХреЛрдИ рд░реБрдХрд╛рд╡рдЯ рд╣реЛ, рддреЛ рдПрдХ InterruptedIOException рдХреЛ рдлреЗрдВрдХ рджрд┐рдпрд╛ рдЬрд╛рдПред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рд░реАрдб () рдкрджреНрдзрддрд┐ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХреЗрд╡рд▓ рдПрдХ рд╣реА рд╕реНрдерд╛рди рдкрд░ рдореЗрд░реЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рдерд╛ - рдЬрдм рдЗрдирдкреБрдЯрд╕реНрдЯреНрд░реАрдо рдмреИрдХрдЕрдк рдЕрдкрд▓реЛрдб рд╡рд┐рдзрд┐ рд╕реЗ рд╡рд╛рдкрд╕ рдЖрдпрд╛ред рдЗрд╕ рддрд░рд╣ рд╕реЗ рд╣рдо рд╣рд░ рдЬрдЧрд╣ рдЭрдВрдбреЗ рдкрд░ рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреА рдЬрд╛рдВрдЪ рдХрд┐рдП рдмрд┐рдирд╛ рдПрдХ рд░реБрдХрд╛рд╡рдЯ рдХреА рдЙрддреНрдкрддреНрддрд┐ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рди рд╕рдХрддреЗ рд╣реИрдВред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдЗрд╕ рдЕрдкрд╡рд╛рдж рдХреЛ IOException рд╕реЗ рдЕрд▓рдЧ рд╕реЗ рдкрдХрдбрд╝рдирд╛ рдФрд░ рдЗрд╕реЗ рдЕрд▓рдЧ рд╕реЗ рд╕рдВрднрд╛рд▓рдирд╛ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИред рдмреЗрд╢рдХ, рдЖрдк рдХреБрдЫ рд╕реНрдерд╛рдиреЛрдВ рдкрд░ рдзреНрд╡рдЬ рдХреА рдЯреЗрдореНрдкреНрд▓реЗрдЯ рдЬрд╛рдВрдЪ рдХреА рдорджрдж рдХреЗ рдмрд┐рдирд╛ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ, рд▓реЗрдХрд┐рди рдпрд╣ рдкрд╣рд▓реЗ рд╕реЗ рдмреЗрд╣рддрд░ рд╣реЛ рдЧрдпрд╛ рд╣реИред


рдпрд╣ рднреА рдзреНрдпрд╛рди рд░рдЦрдирд╛ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ рдХрд┐ рдпрджрд┐ рдЭрдВрдЭрдЯ рдХреЛ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рджреМрд░рд╛рди рдЭрдВрдбреЗ рдХреЛ рд╕рд╛рдл рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рддреЛ рдЕрд╡рд░реЛрдзрдХ рдзреНрд╡рдЬ рдХреЛ рдлрд┐рд░ рд╕реЗ рд╕реЗрдЯ рдХрд░рдирд╛ рд╣рдореЗрд╢рд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реЛрддрд╛ рд╣реИ рддрд╛рдХрд┐ рд╡рд┐рдзрд┐ рд╕реЗ рд▓реМрдЯрдиреЗ рдХреЗ рдмрд╛рдж рд╣рдо рдЙрд╕ рд░реБрдХрд╛рд╡рдЯ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдкрддрд╛ рд▓рдЧрд╛ рд╕рдХреЗрдВ рдЬреЛ рдШрдЯрд┐рдд рд╣реБрдИ рдереАред


рдореБрдЭреЗ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд╕рд╛рде рд╕рдордЭрд╛рддрд╛ рд╣реВрдВ рдХрд┐ рдпрд╣ рдХреНрдпреЛрдВ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИред рдорд╛рди рд▓реАрдЬрд┐рдП рд╣рдо рдЕрдкрд▓реЛрдб () рд╡рд┐рдзрд┐ рдореЗрдВ рднрдВрдбрд╛рд░рдг рдХреЗ рд▓рд┐рдП рдПрдХ рдмреИрдХрдЕрдк рдЕрдкрд▓реЛрдб рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдПрдХ рд╡реНрдпрд╡рдзрд╛рди рдЙрддреНрдкрдиреНрди рд╣реЛрддрд╛ рд╣реИред рд╡реНрдпрд╡рдзрд╛рди рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдХрд╛рдо рдмрдВрдж рдХрд░ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рд╡рд┐рдзрд┐ рд╡рд╛рдкрд╕ рдЖ рдЬрд╛рддреА рд╣реИред рд░реБрдХрд╛рд╡рдЯ рдЖрдХрд╕реНрдорд┐рдХрддрд╛ рдХреЗ рд╕рд╛рде рдирд╣реАрдВ рд╣реЛрддреА рд╣реИ - рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдпрд╛ рддреЛ рдПрдХ рддреНрд░реБрдЯрд┐ рдХрд╣реАрдВ рд╣реБрдИ, рдпрд╛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдиреЗ рдХрд╛рд░реНрдп рдХреЛ рд░рджреНрдж рдХрд░ рджрд┐рдпрд╛ред рдХрд╛рд░рдг рдЪрд╛рд╣реЗ рдЬреЛ рднреА рд╣реЛ, рд╣рдореЗрдВ рдЗрд╕ Future рдореЗрдВ рд╕рднреА рдХрд╛рдо рдмрдВрдж рдХрд░рдиреЗ рдЪрд╛рд╣рд┐рдПред рд▓реЗрдХрд┐рди рдЕрдЧрд░ рдЖрдк рдмреВрдЯ рд╡рд┐рдзрд┐ рд╕реЗ рд▓реМрдЯрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдлрд┐рд░ рд╕реЗ рдмреАрдЪ рдореЗрдВ рдзреНрд╡рдЬ рдХреЛ рд╕реНрдерд╛рдкрд┐рдд рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рдореБрдЦреНрдп рдлреНрдпреВрдЪрд░ рдмреНрд▓реЙрдХ рдореЗрдВ рдХрднреА рднреА рдЙрд╕ рдЕрд╡рд░реЛрдз рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдирд╣реАрдВ рдЬрд╛рди рдкрд╛рдПрдВрдЧреЗред
рдПрдХ рд╣реА рдХреЛрдб рдЙрджрд╛рд╣рд░рдг:


 backupLoadManager.uploadBackup(processedBackupStream, backupProperties, taskId); <-   ,       if (Thread.interrupted()) { //      ,      - ,    throw new InterruptedException(); } 

рдЗрд╕рд▓рд┐рдП, InterruptedException рдпрд╛ InterruptedIOException рдХреЛ рд╣реИрдВрдбрд▓ рдХрд░рдирд╛ рдЕрдЪреНрдЫрд╛ рдЕрднреНрдпрд╛рд╕ рд╣реИ:


 try { ... } catch (InterruptedException e) { //  InterruptedIOException ... // re-interrupt the thread Thread.currentThread().interrupt(); } 

рдареАрдХ рд╣реИ, рд╣рдо рд░реБрдХрд╛рд╡рдЯ рдХреЛ рд╕рдВрднрд╛рд▓ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдереНрд░реЗрдбреНрд╕ рдХреЛ рдмрд╛рдзрд┐рдд рдХреМрди рдХрд░реЗрдЧрд╛?
рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдПрдХ рдЕрдиреНрдп рд╕рдВрд╕реНрдерд╛ рдмрдирд╛рдПрдБрдЧреЗ рдЬрд┐рд╕реЗ CancelTask рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬреЛ рд░рджреНрдж рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╛рд░реНрдп рдХреА рдЖрдИрдбреА рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░реЗрдЧрд╛, рдФрд░ рдПрдХ рдШрдбрд╝реА рднреА рд▓рд┐рдЦреЗрдЧрд╛ рдЬреЛ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдмрд╛рдзрд┐рдд рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдЧреАред рдХреНрдпреЛрдВ рдХреЛрд╢рд┐рд╢ рдХрд░реЗрдВ? рдХреНрдпреЛрдВрдХрд┐:


  1. рдХрд┐рд╕реА рдЕрдиреНрдп рд╕рд░реНрд╡рд░ рдХреА рд╕реНрдореГрддрд┐ рдореЗрдВ рдереНрд░реЗрдб рдХреЛ рд╕рдорд╛рдкреНрдд рдХрд░рдиреЗ рдореЗрдВ рдЕрд╕рдорд░реНрдеред рдХрдИ рд╕рд░реНрд╡рд░ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдлреНрдпреВрдЪрд░ рдЕрд▓рдЧ-рдЕрд▓рдЧ рд╕рд░реНрд╡рд░ рдкрд░ рдмрд┐рдЦрд░рд╛ рд╣реБрдЖ рд╣реИред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдЬрдм рдХрд┐рд╕реА рдХрд╛рд░реНрдп рдХреЛ рд░рджреНрдж рдХрд░рдиреЗ рдХрд╛ рдЕрдиреБрд░реЛрдз рд╕рд░реНрд╡рд░ рдореЗрдВ рд╕реЗ рдХрд┐рд╕реА рдПрдХ рдкрд░ рдЖрддрд╛ рд╣реИ, рддреЛ рд╡рд╛рдВрдЫрд┐рдд рднрд╡рд┐рд╖реНрдп рджреВрд╕рд░реЗ рд╕рд░реНрд╡рд░ рдХреА рд╕реНрдореГрддрд┐ рдореЗрдВ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред
  2. рд╕рд░реНрд╡рд░ рдХреНрд░реИрд╢ рдХреЗ рдХрд╛рд░рдг рдлреНрдпреВрдЪрд░ рдХреЗ рдЦреЛ рдЬрд╛рдиреЗ рдХреЗ рдмрд╛рдж рдЯрд╛рд╕реНрдХ рдХреЛ рд░рджреНрдж рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

рд╢рд╛рдо рдХреЛ рд╕рдВрдХреНрд╖реЗрдкрдг рд░рджреНрдж рдХрд░рдиреЗ рдХрд╛ рд╕рдВрдХреНрд╖рд┐рдкреНрдд рд╡рд░реНрдгрди рдХрд░реЗрдВ:
рд╡рд╛рдЯрд░рдЪреЗрд░ рдиреЗ рд╕рднреА рд░рд┐рдХреЙрд░реНрдбреНрд╕ рдХреЛ рдХреИрдВрд╕рд▓_рдЯреИрдХреНрд╕ рдЯреЗрдмрд▓ рд╕реЗ рдирд┐рдХрд╛рд▓ рд▓рд┐рдпрд╛ (рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ рд▓реЙрдХ рд╕реЗрдЯ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ), рдкреНрд░рддреНрдпреЗрдХ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдЕрдкрдиреА рдореЗрдореЛрд░реА рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рднрд╡рд┐рд╖реНрдп рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддрд╛ рд╣реИред рдпрджрд┐ рднрд╡рд┐рд╖реНрдп рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХ рдкреНрд░рд╛рдкреНрдд рд╣реЛрддрд╛ рд╣реИ, рддреЛ рд╕рдВрдмрдВрдзрд┐рдд рдереНрд░реЗрдб рдмрд╛рдзрд┐рдд рд╣реЛрддрд╛ рд╣реИ, рдХрд╛рд░реНрдп рд╡рд╛рдкрд╕ рд╣реЛрддрд╛ рд╣реИ рдФрд░ рдЕрдиреБрд░реЛрдз рддрд╛рд▓рд┐рдХрд╛ рд╕реЗ рд╣рдЯрд╛ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрджрд┐ рдХрд╛рд░реНрдп рдХреЛ рд░рджреНрдж рдХрд░рдиреЗ рдХрд╛ рдЯрд╛рдЗрдордЖрдЙрдЯ рдЕрдиреБрд░реЛрдз рдкрд╛рд░ рд╣реЛ рдЧрдпрд╛ рд╣реИ (рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рд╕рд░реНрд╡рд░ рджреБрд░реНрдШрдЯрдирд╛рдЧреНрд░рд╕реНрдд рд╣реЛ рдЧрдпрд╛ рдФрд░ рднрд╡рд┐рд╖реНрдп рдЦреЛ рдЧрдпрд╛) - рдЕрдиреБрд░реЛрдз рдХреЗрд╡рд▓ рддрд╛рд▓рд┐рдХрд╛ рд╕реЗ рд╣рдЯрд╛ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдпрджрд┐ рдХрдИ рд╕рд░реНрд╡рд░ рдПрдХ рдЯрд╛рдЗрдордЖрдЙрдЯ рдиреЛрдЯрд┐рд╕ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рддрд╛рд▓рд┐рдХрд╛ рд╕реЗ рд░рд┐рдХреЙрд░реНрдб рд╣рдЯрд╛рддреЗ рд╣реИрдВ, рддреЛ рдХреБрдЫ рднреА рдмреБрд░рд╛ рдирд╣реАрдВ рд╣реЛрдЧрд╛, рдХреНрдпреЛрдВрдХрд┐ рдкреЛрд╕реНрдЯрдЧреНрд░реЗрдХреНрдпреВрдПрд▓ рдореЗрдВ рдбрд┐рд▓реАрдЯ рдХрд░рдирд╛ рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рд╣реИред


рд░рджреНрдж рдХрд░реЗрдВ


рдЫрд┐рдкрд╛ рд╣реБрдЖ рдкрд╛рда
 /** * This class scans for tasks to cancel and tries to cancel them. */ @Component class CancelTasksWatcher { private static final Logger logger = LoggerFactory.getLogger(CancelTasksWatcher.class); private static final Duration cancelTimeout = Duration.ofMinutes(10); private CancelTasksManager cancelTasksManager; private TasksStarterService tasksStarterService; private TasksManager tasksManager; // spring setters... /** * This watcher wakes up every time 10 seconds passed from the last completion, checks if there are any tasks to cancel and tries to * cancel each task. * <p> * Since there are can be working more that one instance of the program, {@literal Future} instance of task can belong to different * servers. We can't get access to {@literal Future} if it's not in memory of the server where task cancellation request was accepted. * So the purpose of this watcher is to be able cancel tasks that works in the other instance of program. Each server has this watcher * checking for available cancellation requests and if any, the watcher tries to cancel corresponding {@literal Future}. * If cancellation is successful task will be also reverted. * <p> * If task cancellation request timeout exceeded, then it means a server that had requested {@literal Future} instances has been * shutdown, so all {@literal Future} instances lost and task can't be canceled. In such case task cancellation request will be ignored. * * @see TasksStarterService#getFuture(Integer) * @see TasksManager#revertTask(Task) */ @Scheduled(fixedDelay = 10 * 1000) @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW) public void watchTasksToCancel() { Iterable<CancelTask> cancelTasks = cancelTasksManager.findAll(); Iterable<Task> tasks = tasksManager.findAllById(StreamSupport.stream(cancelTasks.spliterator(), false) .map(CancelTask::getTaskId).collect(Collectors.toList())); Map<Integer, Task> tasksAsMap = StreamSupport.stream(tasks.spliterator(), false) .collect(Collectors.toMap(Task::getId, Function.identity())); List<Integer> taskIdsForDeleting = new ArrayList<>(); for (CancelTask cancelTask : cancelTasks) { Integer taskId = cancelTask.getTaskId(); Task task = tasksAsMap.get(taskId); if (task == null) { logger.error("Can't cancel task: no such entity with ID {}", taskId); taskIdsForDeleting.add(taskId); continue; } // timeout exceeded, that is server shutdown and lost all Future instances, so task can't be canceled if (LocalDateTime.now(ZoneOffset.UTC).isAfter(cancelTask.getPutTime().plus(cancelTimeout))) { logger.error("Can't cancel task: timeout exceed. Task ID: {}", taskId); taskIdsForDeleting.add(taskId); continue; } tasksStarterService.getFuture(taskId).ifPresent(future -> { logger.info("Canceling task with ID {}", taskId); boolean canceled = future.cancel(true); if (canceled) { try { // give time to properly handle interrupt Thread.sleep(10000); } catch (InterruptedException e) { // should not happen } tasksManager.revertTask(task); } taskIdsForDeleting.add(taskId); logger.info("Task canceled: {}. Task ID: {}", canceled, taskId); }); } cancelTasksManager.deleteByTaskIdIn(taskIdsForDeleting); } } 



рд╣реИрдВрдбрд▓рд┐рдВрдЧ рдореЗрдВ рддреНрд░реБрдЯрд┐


, , Future, try-catch :


 try { ... } catch (RuntimeException e) { ... errorTasksManager.addErrorTask(taskId); } 

RuntimeException , Future , .


addErrorTask(taskId) , ID , .
? , , , .


:
, , . тАФ PostgreSQL select for update , select skip locked . , , revertTask() , .


ErrorTasksWatcher :


 /** * This class scans for erroneous tasks and handles them depending on their state. */ @Component class ErrorTasksWatcher { private static final Logger logger = LoggerFactory.getLogger(ErrorTasksWatcher.class); private static final Integer nRows = 10; private TasksManager tasksManager; private ErrorTasksManager errorTasksManager; // spring setters... /** * This watcher wakes up every time 1 minute passed from the last completion, checks backup states periodically and handles erroneous * tasks if any. * <p> * The watcher handles at most N tasks as described by {@link #nRows} constant and skips already locked tasks. * When retrieving error tasks from database pessimistic lock is set. It allows safely run more than one copy of program, as no other * watcher can pick up already being handled error tasks. * <p> * If the server shutdowns while rows was locked, transaction will be rolled back and lock released, so these entities can be picked * up by the other running server. */ @Scheduled(fixedDelay = 60 * 1000) @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW) public void watchErrorTasks() { for (ErrorTask errorTask : errorTasksManager.findFirstNAndLock(nRows)) { if (!errorTask.isErrorHandled()) { Integer backupTaskId = errorTask.getTaskId(); Optional<Task> optionalTask = tasksManager.findById(backupTaskId); if (!optionalTask.isPresent()) { logger.info("Can't handle erroneous task: no corresponding backup task entity. Backup task ID: {}", backupTaskId); continue; } tasksManager.revertTask(optionalTask.get()); errorTask.setErrorHandled(true); } } } } 

revertTask(Task) :


  /** * This function reverts erroneous task by its entity. * <p> * Use this function only after canceling related {@literal Future}. * <p> * If the task was of the type {@link Task.Type#CREATE_BACKUP} then related {@link BackupProperties} will be deleted. * * @param task the entity */ public void revertTask(@NotNull Task task) { Objects.requireNonNull(task); Task.State state = task.getState(); switch (state) { case DOWNLOADING: case APPLYING_DEPROCESSORS: case RESTORING: case DELETING: { logger.info("Handling broken operation. Operation: {}. No extra actions required", state.toString()); break; } case CREATING: case APPLYING_PROCESSORS: { logger.info("Handling broken operation. Operation: {}. Delete backup properties...", state.toString()); Integer backupPropertiesID = task.getBackupPropertiesId(); if (!backupPropertiesManager.existsById(backupPropertiesID)) { logger.error("Can't revert task: no related backup properties. Task info: {}", task); return; } backupPropertiesManager.deleteById(backupPropertiesID); break; } case UPLOADING: { logger.info("Handling broken operation. Operation: {}. Deleting backup from storage...", state); Integer backupPropertiesId = task.getBackupPropertiesId(); Optional<BackupProperties> optionalBackupProperties = backupPropertiesManager.findById(backupPropertiesId); if (!optionalBackupProperties.isPresent()) { logger.error("Can't revert task: no related backup properties. Task info: {}", task); return; } tasksStarterService.startDeleteTask(Task.RunType.INTERNAL, optionalBackupProperties.get()); backupPropertiesManager.deleteById(backupPropertiesId); break; } default: { logger.error("Can't revert task: unknown state. Task info: {}", task); } } } 

рдЖрдЗрдП рд╕рдВрднрд╛рд╡рд┐рдд рд╕реНрдерд┐рддрд┐рдпреЛрдВ рдХрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░реЗрдВ:


  1. DOWNLOADING , APPLYING_DEPROCESSORS , RESTORING , DELETING тАФ . , .
  2. CREATING , APPLYING_PROCESSORS тАФ , . BackupProperties , ( BackupProperties Web UI ).
  3. UPLOADING тАФ . BackupProperties , . .

, . , ? , , Future ( 1), , InputStream ( 2). , 2, 1 2 ?


, , , . Future ( 1) :


  public void onError(@NotNull Throwable t, @NotNull Integer taskId) { logger.error("Exception caught. Task ID: {}", taskId, t); Optional<Future> optionalFuture = tasksStarterService.getFuture(taskId); if (!optionalFuture.isPresent()) { logger.error("Can't cancel the Future of task with ID {}: no such Future instance", taskId); } else { boolean canceled = optionalFuture.get().cancel(true); if (!canceled) { logger.error("Error canceling the Future of task with ID {}", taskId); } else { logger.info("Task canceled. Task ID: {}", taskId); errorTasksManager.setError(taskId); } } } 

, , ID , , Future - , ID .


, , , , , .


, :


, , , . тАФ Future.


, , , I/O , тАФ / . , . :


  1. , . , тАФ .
  2. тАФ Future , . , / , , ( , тАФ IOException , , ).

, тАФ ( ID , , ), .




, , . , , .



  1. Web UI: , . ,

рдирд┐рд╖реНрдХрд░реНрд╖


:



, ! , GitHub!

Source: https://habr.com/ru/post/hi459478/


All Articles