@@ -598,7 +598,7 @@ ul.references li p a.back-anchor { This book is distributed under the Creative Commons Attribution-NonCommercial 4.0 International licence. Source code available at github.com/twirl/The-API-Book - Share: facebook · twitter · linkedin · redditTable of ContentsIntroductionChapter 1. On the Structure of This BookChapter 2. The API DefinitionChapter 3. Overview of Existing API Development SolutionsChapter 4. API Quality CriteriaChapter 5. The API-first approachChapter 6. On Backward CompatibilityChapter 7. On VersioningChapter 8. Terms and Notation KeysSection I. The API DesignChapter 9. The API Contexts PyramidChapter 10. Defining an Application FieldChapter 11. Separating Abstraction LevelsChapter 12. Isolating Responsibility AreasChapter 13. Describing Final InterfacesChapter 14. Annex to Section I. Generic API Example[Work in Progress] Section II. The API PatternsChapter 15. On Design Patterns in the API ContextChapter 16. Authenticating Partners and Authorizing API CallsChapter 17. Synchronization StrategiesChapter 18. Eventual ConsistencyChapter 19. Asynchronicity and Time ManagementChapter 20. Lists and Accessing ThemChapter 21. Bidirectional Data Flows. Push and Poll ModelsChapter 22. Organization of Notification SystemsChapter 23. AtomicityChapter 24. Partial UpdatesChapter 25. Degradation and PredictabilitySection III. The Backward CompatibilityChapter 26. The Backward Compatibility Problem StatementChapter 27. On the Waterline of the IcebergChapter 28. Extending through AbstractingChapter 29. Strong Coupling and Related ProblemsChapter 30. Weak CouplingChapter 31. Interfaces as a Universal PatternChapter 32. The Serenity Notepad[Work in Progress] Section IV. The HTTP API & RESTChapter 33. On HTTP API Concept and TerminologyChapter 34. The REST MythChapter 35. The Semantics of the HTTP Request ComponentsChapter 36. The HTTP API Advantages and DisadvantagesChapter 37. HTTP API Organization PrinciplesChapter 38. Working with HTTP API ErrorsChapter 39. Organizing the HTTP API Resources and OperationsChapter 40. Final Provisions and General Recommendations[Work in Progress] Section V. The SDK & UI LibrariesChapter 41. On the Content of This SectionChapter 42. The SDK: Problems and SolutionsChapter 43. The Code Generation PatternChapter 44. The UI ComponentsChapter 45. Decomposing UI ComponentsChapter 46. The MV* FrameworksChapter 47. The Backend-Driven UIChapter 48. Shared Resources and Asynchronous LocksChapter 49. Computed PropertiesChapter 50. ConclusionSection VI. The API ProductChapter 51. API as a ProductChapter 52. The API Business ModelsChapter 53. Developing a Product VisionChapter 54. Communicating with DevelopersChapter 55. Communicating with Business OwnersChapter 56. The API Services RangeChapter 57. The API Key Performance IndicatorsChapter 58. Identifying Users and Preventing FraudChapter 59. The Technical Means of Preventing ToS ViolationsChapter 60. Supporting customersChapter 61. The DocumentationChapter 62. The Testing EnvironmentChapter 63. Managing Expectations + Share: facebook · twitter · linkedin · redditTable of ContentsIntroductionChapter 1. On the Structure of This BookChapter 2. The API DefinitionChapter 3. Overview of Existing API Development SolutionsChapter 4. API Quality CriteriaChapter 5. The API-First ApproachChapter 6. On Backward CompatibilityChapter 7. On VersioningChapter 8. Terms and Notation KeysSection I. The API DesignChapter 9. The API Contexts PyramidChapter 10. Defining an Application FieldChapter 11. Separating Abstraction LevelsChapter 12. Isolating Responsibility AreasChapter 13. Describing Final InterfacesChapter 14. Annex to Section I. Generic API Example[Work in Progress] Section II. The API PatternsChapter 15. On Design Patterns in the API ContextChapter 16. Authenticating Partners and Authorizing API CallsChapter 17. Synchronization StrategiesChapter 18. Eventual ConsistencyChapter 19. Asynchronicity and Time ManagementChapter 20. Lists and Accessing ThemChapter 21. Bidirectional Data Flows. Push and Poll ModelsChapter 22. Chapter 23. AtomicityChapter 24. Partial UpdatesChapter 25. Degradation and PredictabilitySection III. The Backward CompatibilityChapter 26. The Backward Compatibility Problem StatementChapter 27. On the Waterline of the IcebergChapter 28. Extending through AbstractingChapter 29. Strong Coupling and Related ProblemsChapter 30. Weak CouplingChapter 31. Interfaces as a Universal PatternChapter 32. The Serenity Notepad[Work in Progress] Section IV. The HTTP API & RESTChapter 33. On HTTP API Concept and TerminologyChapter 34. The REST MythChapter 35. The Semantics of the HTTP Request ComponentsChapter 36. The HTTP API Advantages and DisadvantagesChapter 37. HTTP API Organization PrinciplesChapter 38. Working with HTTP API ErrorsChapter 39. Organizing the HTTP API Resources and OperationsChapter 40. Final Provisions and General Recommendations[Work in Progress] Section V. The SDK & UI LibrariesChapter 41. On the Content of This SectionChapter 42. The SDK: Problems and SolutionsChapter 43. The Code Generation PatternChapter 44. The UI ComponentsChapter 45. Decomposing UI ComponentsChapter 46. The MV* FrameworksChapter 47. The Backend-Driven UIChapter 48. Shared Resources and Asynchronous LocksChapter 49. Computed PropertiesChapter 50. ConclusionSection VI. The API ProductChapter 51. API as a ProductChapter 52. The API Business ModelsChapter 53. Developing a Product VisionChapter 54. Communicating with DevelopersChapter 55. Communicating with Business OwnersChapter 56. The API Services RangeChapter 57. The API Key Performance IndicatorsChapter 58. Identifying Users and Preventing FraudChapter 59. The Technical Means of Preventing ToS ViolationsChapter 60. Supporting customersChapter 61. The DocumentationChapter 62. The Testing EnvironmentChapter 63. Managing Expectations § @@ -673,7 +673,7 @@ ul.references li p a.back-anchor { However, the static convenience and clarity of APIs are simple parts. After all, nobody seeks to make an API deliberately irrational and unreadable. When we develop an API, we always start with clear basic concepts. Providing you have some experience in APIs, it's quite hard to make an API core that fails to meet obviousness, readability, and consistency criteria. Problems begin when we start to expand our API. Adding new functionality sooner or later results in transforming once plain and simple API into a mess of conflicting concepts, and our efforts to maintain backward compatibility will lead to illogical, unobvious, and simply bad design solutions. It is partly related to an inability to predict the future in detail: your understanding of “fine” APIs will change over time, both in objective terms (what problems the API is to solve, and what is best practice) and in subjective terms too (what obviousness, readability, and consistency really mean to your API design). -The principles we are explaining below are specifically oriented towards making APIs evolve smoothly over time, without being turned into a pile of mixed inconsistent interfaces. It is crucial to understand that this approach isn't free: the necessity to bear in mind all possible extension variants and to preserve essential growth points means interface redundancy and possibly excessive abstractions being embedded in the API design. Besides, both make the developers' jobs harder. Providing excess design complexities being reserved for future use makes sense only if this future actually exists for your API. Otherwise, it's simply overengineering.Chapter 5. The API-first approach +The principles we are explaining below are specifically oriented towards making APIs evolve smoothly over time, without being turned into a pile of mixed inconsistent interfaces. It is crucial to understand that this approach isn't free: the necessity to bear in mind all possible extension variants and to preserve essential growth points means interface redundancy and possibly excessive abstractions being embedded in the API design. Besides, both make the developers' jobs harder. Providing excess design complexities being reserved for future use makes sense only if this future actually exists for your API. Otherwise, it's simply overengineering.Chapter 5. The API-First Approach Today, more and more IT companies are recognizing the importance of the “API-first” approach, which is the paradigm of developing software with a heavy focus on APIs. However, we must differentiate between the product concept of the API-first approach and the technical one. The former means that the first (and sometimes the only) step in developing a service is creating an API for it, and we will discuss it in “The API Product” section of this book. @@ -3194,7 +3194,130 @@ GET /v1/orders/created-history⮠ queues might accumulate unprocessed events, introducing increasing delays, and solving this issue on the subscriber's side might be quite non-trivial. Also, in public APIs both technologies are frequently used in conjunction: the API backend sends a task to call the webhook in the form of publishing an event which the specially designed internal service will try to process by making the call. -Theoretically, we can imagine an integration that exposes directly accessible message queues in one of the standard formats for partners to subscribe. However, we are unaware of any examples of such APIs.Chapter 22. Organization of Notification SystemsChapter 23. AtomicityChapter 24. Partial UpdatesChapter 25. Degradation and PredictabilitySection III. The Backward CompatibilityChapter 26. The Backward Compatibility Problem Statement +Theoretically, we can imagine an integration that exposes directly accessible message queues in one of the standard formats for partners to subscribe. However, we are unaware of any examples of such APIs.Chapter 22. [Multiplexing Notifications. Asynchronous Event Processing][api-patterns-async-event-processing] +One of the vexing restrictions of almost every technology mentioned in the previous chapter is the limited size of messages. With client push notifications the situation is the most problematic: Google Firebase Messaging at the moment this chapter is being written allowed no more than 4000 bytes of payload. In backend development, the restrictions are also notable; let's say, Amazon SQS limits the size of messages to 256 KiB. While developing webhook-based integrations, you risk hitting the maximum body size allowed by the partner's webserver (for example, in nginx the default value is 1MB). This leads us to the necessity of making two technical decisions regarding the notification formats: + +Whether a message contains all data needed to process it or just notifies some state change has happened +If we choose the latter, whether a single notification contains data on a single change, or it might bear several such events. + +On the example of our coffee API: +// Option #1: the message +// contains all the order data +POST /partner/webhook +Host: partners.host +{ + "event_id", + "occurred_at", + "order": { + "id", + "status", + "recipe_id", + "volume", + // Other data fields + … + } +} + +// Option #2: the message body +// contains only the notification +// of the status change +POST /partner/webhook +Host: partners.host +{ + "event_id", + // Message type: a notification + // about a new order + "event_type": "new_order", + "occurred_at", + // Data sufficient to + // retrieve the full state, + // in our case, the order identifier + "order_id" +} +// To process the event, the partner +// must request some endpoint +// on the API vendor's side, +// possibly asynchronously +GET /v1/orders/{id} +→ +{ /* full data regarding + the order */ } + +// Option #3: the API vendor +// notifies partners that +// several orders await their +// reaction +POST /partner/webhook +Host: partners.host +{ + // The system state revision + // and/or a cursor to retrieve + // the orders might be provided + "occurred_at", + "pending_order_count": + <the number of pending orders> +} +// In response to such a call, +// partners should retrieve the list +// of ongoing orders +GET /v1/orders/pending +→ +{ + "orders", + "cursor" +} + +Which option to select depends on the subject area (and on the allowed message sizes in particular) and on the procedure of handling messages by partners. In our case, every order must be processed independently and the number of messages during the order life cycle is low, so our natural choice would be either option #1 (if order data cannot contain unpredictably large fields) or #2. Option #3 is viable if: + +The API generates a lot of notifications for a single logical entity +Partners are interested in fresh state changes only +Or events must be processed sequentially, and no parallelism is allowed. + +NB: the approach #3 (and partly #2) naturally leads us to the scheme that is typical for client-server integration: the push message itself contains almost no data and is only a trigger for ahead-of-time polling. +The technique of sending only essential data in the notification has one important disadvantage, apart from more complicated data flows and increased request rate. With option #1 implemented (i.e., the message contains all the data), we might assume that returning a success response by the subscriber is equivalent to successfully processing the state change by the partner (although it's not guaranteed if the partner uses asynchronous techniques). With options #2 and #3, this is certainly not the case: the partner must carry out additional actions (starting from retrieving the actual order state) to fully process the message. This implies that two separate statuses might be needed: “message received” and “message processed.” Ideally, the latter should follow the logic of the API work cycle, i.e., the partner should carry out some action upon processing the event, and this action might be treated as the “message processed” signal. In our coffee example, we can expect that the partner will either accept or reject an order after receiving the “new order” message. Then the full message processing flow will look like this: +// The API vendor +// notifies the partner that +// several orders await their +// reaction +POST /partner/webhook +Host: partners.host +{ + "occurred_at", + "pending_order_count": + <the number of pending orders> +} + +// In response, the partner +// retrieves the list of +// pending orders +GET /v1/orders/pending +→ +{ + "orders", + "cursor" +} + +// After the orders are processed, +// the partners notify about this +// by calling the specific API +// endpoint +POST /v1/orders/bulk-status-change +{ + "status_changes": [{ + "order_id", + "new_status": "accepted", + // Other relevant information + // e.g. the preparation time + // estimates + … + }, { + "order_id", + "new_status": "rejected", + "reason" + }, …] +} + +If there is no genuine follow-up call expected during our API work cycle, we can introduce an endpoint to explicitly mark notifications as processed. This step is not mandatory as we can always stipulate that it is the partner's responsibility to process notifications and we do not expect any confirmations. However, we will lose an important monitoring tool if we do so, as we can no longer track what's happening on the partner's side, i.e., whether the partner is able to process notifications on time. This, in turn, will make it harder to develop the degradation and emergency shutdown mechanisms we talked about in the previous chapter.Chapter 23. AtomicityChapter 24. Partial UpdatesChapter 25. Degradation and PredictabilitySection III. The Backward CompatibilityChapter 26. The Backward Compatibility Problem Statement As usual, let's conceptually define “backward compatibility” before we start. Backward compatibility is a feature of the entire API system to be stable in time. It means the following: the code that developers have written using your API continues working functionally correctly for a long period of time. There are two important questions to this definition and two explanations: diff --git a/docs/API.en.pdf b/docs/API.en.pdf index 2395623..aa0bacc 100644 Binary files a/docs/API.en.pdf and b/docs/API.en.pdf differ diff --git a/docs/API.ru.epub b/docs/API.ru.epub index 345df98..3279af9 100644 Binary files a/docs/API.ru.epub and b/docs/API.ru.epub differ diff --git a/docs/API.ru.html b/docs/API.ru.html index 7c9cc39..afee114 100644 --- a/docs/API.ru.html +++ b/docs/API.ru.html @@ -577,7 +577,7 @@ ul.references li p a.back-anchor { Ссылка: - СодержаниеВведениеГлава 1. О структуре этой книгиГлава 2. Определение APIГлава 3. Обзор существующих решений в области разработки APIГлава 4. Критерии качества APIГлава 5. API-first подходГлава 6. Обратная совместимостьГлава 7. О версионированииГлава 8. Условные обозначения и терминологияРаздел I. Проектирование APIГлава 9. Пирамида контекстов APIГлава 10. Определение области примененияГлава 11. Разделение уровней абстракцииГлава 12. Разграничение областей ответственностиГлава 13. Описание конечных интерфейсовГлава 14. Приложение к разделу I. Модельный API[В разработке] Раздел II. Паттерны дизайна APIГлава 15. О паттернах проектирования в контексте APIГлава 16. Аутентификация партнёров и авторизация вызовов APIГлава 17. Стратегии синхронизацииГлава 18. Слабая консистентностьГлава 19. Асинхронность и управление временемГлава 20. Списки и организация доступа к нимГлава 21. Двунаправленные потоки данных. Push и poll-моделиГлава 22. Варианты организации системы нотификацийГлава 23. АтомарностьГлава 24. Частичные обновленияГлава 25. Деградация и предсказуемостьРаздел III. Обратная совместимостьГлава 26. Постановка проблемы обратной совместимостиГлава 27. О ватерлинии айсбергаГлава 28. Расширение через абстрагированиеГлава 29. Сильная связность и сопутствующие проблемыГлава 30. Слабая связностьГлава 31. Интерфейсы как универсальный паттернГлава 32. Блокнот душевного покоя[В разработке] Раздел IV. HTTP API и RESTГлава 33. О концепции HTTP API и терминологииГлава 34. Мифология RESTГлава 35. Составляющие HTTP запросов и их семантикаГлава 36. Преимущества и недостатки HTTP APIГлава 37. Принципы организации HTTP APIГлава 38. Работа с ошибками в HTTP APIГлава 39. Организация URL ресурсов и операций над ними в HTTP APIГлава 40. Заключительные положения и общие рекомендации[В разработке] Раздел V. SDK и UIГлава 41. О содержании разделаГлава 42. SDK: проблемы и решенияГлава 43. КодогенерацияГлава 44. UI-компонентыГлава 45. Декомпозиция UI-компонентов. MV*-подходыГлава 46. MV*-фреймворкиГлава 47. Backend-Driven UIГлава 48. Разделяемые ресурсы и асинхронные блокировкиГлава 49. Вычисляемые свойстваГлава 50. В заключениеРаздел VI. API как продуктГлава 51. Продукт APIГлава 52. Бизнес-модели APIГлава 53. Формирование продуктового виденияГлава 54. Взаимодействие с разработчикамиГлава 55. Взаимодействие с бизнес-аудиториейГлава 56. Линейка сервисов APIГлава 57. Ключевые показатели эффективности APIГлава 58. Идентификация пользователей и борьба с фродомГлава 59. Технические способы борьбы с несанкционированным доступом к APIГлава 60. Поддержка пользователей APIГлава 61. ДокументацияГлава 62. Тестовая средаГлава 63. Управление ожиданиями + СодержаниеВведениеГлава 1. О структуре этой книгиГлава 2. Определение APIГлава 3. Обзор существующих решений в области разработки APIГлава 4. Критерии качества APIГлава 5. API-first подходГлава 6. Обратная совместимостьГлава 7. О версионированииГлава 8. Условные обозначения и терминологияРаздел I. Проектирование APIГлава 9. Пирамида контекстов APIГлава 10. Определение области примененияГлава 11. Разделение уровней абстракцииГлава 12. Разграничение областей ответственностиГлава 13. Описание конечных интерфейсовГлава 14. Приложение к разделу I. Модельный API[В разработке] Раздел II. Паттерны дизайна APIГлава 15. О паттернах проектирования в контексте APIГлава 16. Аутентификация партнёров и авторизация вызовов APIГлава 17. Стратегии синхронизацииГлава 18. Слабая консистентностьГлава 19. Асинхронность и управление временемГлава 20. Списки и организация доступа к нимГлава 21. Двунаправленные потоки данных. Push и poll-моделиГлава 22. Мультиплексирование сообщений. Асинхронная обработка событийГлава 23. АтомарностьГлава 24. Частичные обновленияГлава 25. Деградация и предсказуемостьРаздел III. Обратная совместимостьГлава 26. Постановка проблемы обратной совместимостиГлава 27. О ватерлинии айсбергаГлава 28. Расширение через абстрагированиеГлава 29. Сильная связность и сопутствующие проблемыГлава 30. Слабая связностьГлава 31. Интерфейсы как универсальный паттернГлава 32. Блокнот душевного покоя[В разработке] Раздел IV. HTTP API и RESTГлава 33. О концепции HTTP API и терминологииГлава 34. Мифология RESTГлава 35. Составляющие HTTP запросов и их семантикаГлава 36. Преимущества и недостатки HTTP APIГлава 37. Принципы организации HTTP APIГлава 38. Работа с ошибками в HTTP APIГлава 39. Организация URL ресурсов и операций над ними в HTTP APIГлава 40. Заключительные положения и общие рекомендации[В разработке] Раздел V. SDK и UIГлава 41. О содержании разделаГлава 42. SDK: проблемы и решенияГлава 43. КодогенерацияГлава 44. UI-компонентыГлава 45. Декомпозиция UI-компонентов. MV*-подходыГлава 46. MV*-фреймворкиГлава 47. Backend-Driven UIГлава 48. Разделяемые ресурсы и асинхронные блокировкиГлава 49. Вычисляемые свойстваГлава 50. В заключениеРаздел VI. API как продуктГлава 51. Продукт APIГлава 52. Бизнес-модели APIГлава 53. Формирование продуктового виденияГлава 54. Взаимодействие с разработчикамиГлава 55. Взаимодействие с бизнес-аудиториейГлава 56. Линейка сервисов APIГлава 57. Ключевые показатели эффективности APIГлава 58. Идентификация пользователей и борьба с фродомГлава 59. Технические способы борьбы с несанкционированным доступом к APIГлава 60. Поддержка пользователей APIГлава 61. ДокументацияГлава 62. Тестовая средаГлава 63. Управление ожиданиями @@ -598,7 +598,7 @@ ul.references li p a.back-anchor { Это произведение доступно по лицензии Creative Commons «Attribution-NonCommercial» («Атрибуция — Некоммерческое использование») 4.0 Всемирная. Исходный код доступен на github.com/twirl/The-API-Book - Поделиться: facebook · twitter · linkedin · redditСодержаниеВведениеГлава 1. О структуре этой книгиГлава 2. Определение APIГлава 3. Обзор существующих решений в области разработки APIГлава 4. Критерии качества APIГлава 5. API-first подходГлава 6. Обратная совместимостьГлава 7. О версионированииГлава 8. Условные обозначения и терминологияРаздел I. Проектирование APIГлава 9. Пирамида контекстов APIГлава 10. Определение области примененияГлава 11. Разделение уровней абстракцииГлава 12. Разграничение областей ответственностиГлава 13. Описание конечных интерфейсовГлава 14. Приложение к разделу I. Модельный API[В разработке] Раздел II. Паттерны дизайна APIГлава 15. О паттернах проектирования в контексте APIГлава 16. Аутентификация партнёров и авторизация вызовов APIГлава 17. Стратегии синхронизацииГлава 18. Слабая консистентностьГлава 19. Асинхронность и управление временемГлава 20. Списки и организация доступа к нимГлава 21. Двунаправленные потоки данных. Push и poll-моделиГлава 22. Варианты организации системы нотификацийГлава 23. АтомарностьГлава 24. Частичные обновленияГлава 25. Деградация и предсказуемостьРаздел III. Обратная совместимостьГлава 26. Постановка проблемы обратной совместимостиГлава 27. О ватерлинии айсбергаГлава 28. Расширение через абстрагированиеГлава 29. Сильная связность и сопутствующие проблемыГлава 30. Слабая связностьГлава 31. Интерфейсы как универсальный паттернГлава 32. Блокнот душевного покоя[В разработке] Раздел IV. HTTP API и RESTГлава 33. О концепции HTTP API и терминологииГлава 34. Мифология RESTГлава 35. Составляющие HTTP запросов и их семантикаГлава 36. Преимущества и недостатки HTTP APIГлава 37. Принципы организации HTTP APIГлава 38. Работа с ошибками в HTTP APIГлава 39. Организация URL ресурсов и операций над ними в HTTP APIГлава 40. Заключительные положения и общие рекомендации[В разработке] Раздел V. SDK и UIГлава 41. О содержании разделаГлава 42. SDK: проблемы и решенияГлава 43. КодогенерацияГлава 44. UI-компонентыГлава 45. Декомпозиция UI-компонентов. MV*-подходыГлава 46. MV*-фреймворкиГлава 47. Backend-Driven UIГлава 48. Разделяемые ресурсы и асинхронные блокировкиГлава 49. Вычисляемые свойстваГлава 50. В заключениеРаздел VI. API как продуктГлава 51. Продукт APIГлава 52. Бизнес-модели APIГлава 53. Формирование продуктового виденияГлава 54. Взаимодействие с разработчикамиГлава 55. Взаимодействие с бизнес-аудиториейГлава 56. Линейка сервисов APIГлава 57. Ключевые показатели эффективности APIГлава 58. Идентификация пользователей и борьба с фродомГлава 59. Технические способы борьбы с несанкционированным доступом к APIГлава 60. Поддержка пользователей APIГлава 61. ДокументацияГлава 62. Тестовая средаГлава 63. Управление ожиданиями + Поделиться: facebook · twitter · linkedin · redditСодержаниеВведениеГлава 1. О структуре этой книгиГлава 2. Определение APIГлава 3. Обзор существующих решений в области разработки APIГлава 4. Критерии качества APIГлава 5. API-first подходГлава 6. Обратная совместимостьГлава 7. О версионированииГлава 8. Условные обозначения и терминологияРаздел I. Проектирование APIГлава 9. Пирамида контекстов APIГлава 10. Определение области примененияГлава 11. Разделение уровней абстракцииГлава 12. Разграничение областей ответственностиГлава 13. Описание конечных интерфейсовГлава 14. Приложение к разделу I. Модельный API[В разработке] Раздел II. Паттерны дизайна APIГлава 15. О паттернах проектирования в контексте APIГлава 16. Аутентификация партнёров и авторизация вызовов APIГлава 17. Стратегии синхронизацииГлава 18. Слабая консистентностьГлава 19. Асинхронность и управление временемГлава 20. Списки и организация доступа к нимГлава 21. Двунаправленные потоки данных. Push и poll-моделиГлава 22. Мультиплексирование сообщений. Асинхронная обработка событийГлава 23. АтомарностьГлава 24. Частичные обновленияГлава 25. Деградация и предсказуемостьРаздел III. Обратная совместимостьГлава 26. Постановка проблемы обратной совместимостиГлава 27. О ватерлинии айсбергаГлава 28. Расширение через абстрагированиеГлава 29. Сильная связность и сопутствующие проблемыГлава 30. Слабая связностьГлава 31. Интерфейсы как универсальный паттернГлава 32. Блокнот душевного покоя[В разработке] Раздел IV. HTTP API и RESTГлава 33. О концепции HTTP API и терминологииГлава 34. Мифология RESTГлава 35. Составляющие HTTP запросов и их семантикаГлава 36. Преимущества и недостатки HTTP APIГлава 37. Принципы организации HTTP APIГлава 38. Работа с ошибками в HTTP APIГлава 39. Организация URL ресурсов и операций над ними в HTTP APIГлава 40. Заключительные положения и общие рекомендации[В разработке] Раздел V. SDK и UIГлава 41. О содержании разделаГлава 42. SDK: проблемы и решенияГлава 43. КодогенерацияГлава 44. UI-компонентыГлава 45. Декомпозиция UI-компонентов. MV*-подходыГлава 46. MV*-фреймворкиГлава 47. Backend-Driven UIГлава 48. Разделяемые ресурсы и асинхронные блокировкиГлава 49. Вычисляемые свойстваГлава 50. В заключениеРаздел VI. API как продуктГлава 51. Продукт APIГлава 52. Бизнес-модели APIГлава 53. Формирование продуктового виденияГлава 54. Взаимодействие с разработчикамиГлава 55. Взаимодействие с бизнес-аудиториейГлава 56. Линейка сервисов APIГлава 57. Ключевые показатели эффективности APIГлава 58. Идентификация пользователей и борьба с фродомГлава 59. Технические способы борьбы с несанкционированным доступом к APIГлава 60. Поддержка пользователей APIГлава 61. ДокументацияГлава 62. Тестовая средаГлава 63. Управление ожиданиями § @@ -3183,7 +3183,123 @@ GET /v1/orders/created-history⮠ в очереди могут скапливаться необработанные сообщения, внося нарастающие задержки, и решение этой проблемы на стороне подписчика может оказаться отнюдь не тривиальным. Отметим также, что в публичных API зачастую используются обе технологии в связке — бэкенд API отправляет задание на вызов webhook-а в виде публикации события, которое специально предназначенный для этого внутренний сервис будет пытаться обработать путём вызова webhook-а. -Теоретически можно представить себе и такую интеграцию, в которой разработчик API даёт партнёрам непосредственно прямой доступ к внутренней очереди сообщений, однако примеры таких API нам неизвестны.Глава 22. Варианты организации системы нотификацийГлава 23. АтомарностьГлава 24. Частичные обновленияГлава 25. Деградация и предсказуемостьРаздел III. Обратная совместимостьГлава 26. Постановка проблемы обратной совместимости +Теоретически можно представить себе и такую интеграцию, в которой разработчик API даёт партнёрам непосредственно прямой доступ к внутренней очереди сообщений, однако примеры таких API нам неизвестны.Глава 22. Мультиплексирование сообщений. Асинхронная обработка событий +Одно из неприятных ограничений почти всех перечисленных в предыдущей главе технологий — это относительно невысокий размер сообщения. Наиболее проблематичная ситуация с push-уведомлениями: Google Firebase Messaging на момент написания настоящей главы разрешал сообщения не более 4000 байт. Но и в серверной разработке ограничения заметны: например, Amazon SQS лимитирует размер сообщения 256 килобайтами. При разработке webhook-ов вы рискуете быстро упереться в размеры тел сообщений, выставленных на веб-серверах партнёров (например, в nginx по умолчанию разрешены тела запросов не более одного мегабайта). Это приводит нас к необходимости сделать два технических выбора: + +содержит ли тело сообщения все данные необходимые для его обработки, или только уведомляет о факте изменения состояния; +если второе, то содержит ли один вызов извещение об одном изменении, или может уведомлять сразу о нескольких таких событиях. + +Рассмотрим на примере нашего кофейного API: +// Вариант 1: тело сообщения +// содержит все данные о заказе +POST /partner/webhook +Host: partners.host +{ + "event_id", + "occurred_at", + "order": { + "id", + "status", + "recipe_id", + "volume", + // Все прочие детали заказа + … + } +} + +// Вариант 2: тело сообщения +// содержит только информацию +// о самом событии +POST /partner/webhook +Host: partners.host +{ + "event_id", + // Тип сообщения: нотификация + // о появлении нового заказа + "event_type": "new_order", + "occurred_at", + // Все поля данных, необходимые + // для обращения за полным + // состоянием. В нашем случае — + // идентификатор заказа + "order_id" +} +// При обработке сообщения, +// возможно, отложенной, +// партнёр должен обратиться +// к нашему API +GET /v1/orders/{id} +→ +{ /* все детали заказа */ } + +// Вариант 3: мы уведомляем +// партнёра, что его реакции +// ожидают три новых заказа +POST /partner/webhook +Host: partners.host +{ + // Здесь может быть версия + // состояния системы или курсор + "occurred_at", + "pending_order_count": + <число новых заказов> +} +// В ответ партнёр должен вызвать +// эндпойнт получения списка заказов +GET /v1/orders/pending +→ +{ + "orders", + "cursor" +} + +Выбор подходящей модели зависит от предметной области (в частности, допустимых размерах тел сообщений) и того, каким образом партнёр будет обрабатывать сообщение. В нашем конкретном случае, когда партнёр должен каждый новый заказ обработать отдельно, при этом на один заказ не может приходить больше одного-двух уведомлений, естественным выбором является вариант 1 (если тело запроса не содержит никаких непредсказуемо больших данных) или 2. Третий подход будет естественным выбором, если: + +API генерирует большое число сообщений об изменениях состояния на одну логическую сущность; +партнёров интересуют только наиболее свежие изменения; +или обработка событий требует последовательного исполнения и не подразумевает параллельности. + +NB: третий (и отчасти второй) варианты естественным образом приводят нас к схеме, характерной для клиентских устройств: push-уведомление само по себе не почти содержит полезной информации и только является сигналом для внеочередного поллинга. +Применение техник с отправкой только ограниченного набора данных помимо усложнения схемы взаимодействия и увеличения количества запросов имеет ещё один важный недостаток. Если в варианте 1 (сообщение содержит в себе все релевантные данные) мы можем рассчитывать на то, что возврат кода успеха подписчиком эквивалентен успешной обработке сообщения партнёром (что, вообще говоря, тоже не гарантировано, т.к. партнёр может использовать асинхронные схемы), то для вариантов 2 и 3 это заведомо не так: для обработки сообщений партнёр должен выполнить дополнительные действия, начиная с получения нужных данных о заказе. В этом случае нам необходимо иметь раздельные статусы — сообщение доставлено и сообщение обработано; в идеале, второе должно вытекать из логики работы API, т.е. сигналом о том, что сообщение обработано, является какое-то действие, совершаемое партнёром. В нашем кофейном примере это может быть перевод заказа партнёром из статуса "new" (заказ создан пользователем) в статус "accepted" или "rejected" (кофейня партнёра приняла или отклонила заказ). Тогда полный цикл обработки уведосления будет выглядеть так: +// Уведомляем партнёра о том, +// что его реакции +// ожидают три новых заказа +POST /partner/webhook +Host: partners.host +{ + "occurred_at", + "pending_order_count": + <число новых заказов> +} + +// В ответ партнёр вызывает +// эндпойнт получения списка заказов +GET /v1/orders/pending +→ +{ + "orders", + "cursor" +} + +// После того, как заказы обработаны, +// партнёр уведомляет нас об +// изменениях статуса +POST /v1/orders/bulk-status-change +{ + "status_changes": [{ + "order_id", + "new_status": "accepted", + // Иная релевантная информация, + // например, время готовности + … + }, { + "order_id", + "new_status": "rejected", + "reason" + }, …] +} + +Если такого нативного способа оповестить об успешной обработке события схема работы нашего API не предполагает, мы можем ввести эндпойнт который явно помечает сообщения прочитанными. Этот шаг, вообще говоря, необязательный (мы можем просто договориться о том, что это ответственность партнёра обрабатывать события и мы не ждём от него никаких подтверждений), но это лишает нас полезного инструмента мониторинга — что происходит на стороне партнёра, успевает ли он обрабатывать события — что в свою очередь затрудняет разработку упомянутых в предыдущей главе механизмов деградации и аварийного отключения интеграции.Глава 23. АтомарностьГлава 24. Частичные обновленияГлава 25. Деградация и предсказуемостьРаздел III. Обратная совместимостьГлава 26. Постановка проблемы обратной совместимости Как обычно, дадим смысловое определение «обратной совместимости», прежде чем начинать изложение. Обратная совместимость — это свойство всей системы API быть стабильной во времени. Это значит следующее: код, написанный разработчиками с использованием вашего API, продолжает работать функционально корректно в течение длительного времени. К этому определению есть два больших вопроса, и два уточнения к ним. diff --git a/docs/API.ru.pdf b/docs/API.ru.pdf index a384383..bdc7d8a 100644 Binary files a/docs/API.ru.pdf and b/docs/API.ru.pdf differ diff --git a/docs/index.html b/docs/index.html index 633fe03..daf41b3 100644 --- a/docs/index.html +++ b/docs/index.html @@ -61,7 +61,7 @@ Chapter 2. The API Definition Chapter 3. Overview of Existing API Development Solutions Chapter 4. API Quality Criteria -Chapter 5. The API-first approach +Chapter 5. The API-First Approach Chapter 6. On Backward Compatibility Chapter 7. On Versioning Chapter 8. Terms and Notation Keys @@ -88,7 +88,7 @@ Chapter 19. Asynchronicity and Time Management Chapter 20. Lists and Accessing Them Chapter 21. Bidirectional Data Flows. Push and Poll Models -Chapter 22. Organization of Notification Systems +Chapter 22. Chapter 23. Atomicity Chapter 24. Partial Updates Chapter 25. Degradation and Predictability diff --git a/docs/index.ru.html b/docs/index.ru.html index 48b68aa..d8ea75f 100644 --- a/docs/index.ru.html +++ b/docs/index.ru.html @@ -88,7 +88,7 @@ Глава 19. Асинхронность и управление временем Глава 20. Списки и организация доступа к ним Глава 21. Двунаправленные потоки данных. Push и poll-модели -Глава 22. Варианты организации системы нотификаций +Глава 22. Мультиплексирование сообщений. Асинхронная обработка событий Глава 23. Атомарность Глава 24. Частичные обновления Глава 25. Деградация и предсказуемость
@@ -598,7 +598,7 @@ ul.references li p a.back-anchor { Это произведение доступно по лицензии Creative Commons «Attribution-NonCommercial» («Атрибуция — Некоммерческое использование») 4.0 Всемирная. Исходный код доступен на github.com/twirl/The-API-Book - Поделиться: facebook · twitter · linkedin · redditСодержаниеВведениеГлава 1. О структуре этой книгиГлава 2. Определение APIГлава 3. Обзор существующих решений в области разработки APIГлава 4. Критерии качества APIГлава 5. API-first подходГлава 6. Обратная совместимостьГлава 7. О версионированииГлава 8. Условные обозначения и терминологияРаздел I. Проектирование APIГлава 9. Пирамида контекстов APIГлава 10. Определение области примененияГлава 11. Разделение уровней абстракцииГлава 12. Разграничение областей ответственностиГлава 13. Описание конечных интерфейсовГлава 14. Приложение к разделу I. Модельный API[В разработке] Раздел II. Паттерны дизайна APIГлава 15. О паттернах проектирования в контексте APIГлава 16. Аутентификация партнёров и авторизация вызовов APIГлава 17. Стратегии синхронизацииГлава 18. Слабая консистентностьГлава 19. Асинхронность и управление временемГлава 20. Списки и организация доступа к нимГлава 21. Двунаправленные потоки данных. Push и poll-моделиГлава 22. Варианты организации системы нотификацийГлава 23. АтомарностьГлава 24. Частичные обновленияГлава 25. Деградация и предсказуемостьРаздел III. Обратная совместимостьГлава 26. Постановка проблемы обратной совместимостиГлава 27. О ватерлинии айсбергаГлава 28. Расширение через абстрагированиеГлава 29. Сильная связность и сопутствующие проблемыГлава 30. Слабая связностьГлава 31. Интерфейсы как универсальный паттернГлава 32. Блокнот душевного покоя[В разработке] Раздел IV. HTTP API и RESTГлава 33. О концепции HTTP API и терминологииГлава 34. Мифология RESTГлава 35. Составляющие HTTP запросов и их семантикаГлава 36. Преимущества и недостатки HTTP APIГлава 37. Принципы организации HTTP APIГлава 38. Работа с ошибками в HTTP APIГлава 39. Организация URL ресурсов и операций над ними в HTTP APIГлава 40. Заключительные положения и общие рекомендации[В разработке] Раздел V. SDK и UIГлава 41. О содержании разделаГлава 42. SDK: проблемы и решенияГлава 43. КодогенерацияГлава 44. UI-компонентыГлава 45. Декомпозиция UI-компонентов. MV*-подходыГлава 46. MV*-фреймворкиГлава 47. Backend-Driven UIГлава 48. Разделяемые ресурсы и асинхронные блокировкиГлава 49. Вычисляемые свойстваГлава 50. В заключениеРаздел VI. API как продуктГлава 51. Продукт APIГлава 52. Бизнес-модели APIГлава 53. Формирование продуктового виденияГлава 54. Взаимодействие с разработчикамиГлава 55. Взаимодействие с бизнес-аудиториейГлава 56. Линейка сервисов APIГлава 57. Ключевые показатели эффективности APIГлава 58. Идентификация пользователей и борьба с фродомГлава 59. Технические способы борьбы с несанкционированным доступом к APIГлава 60. Поддержка пользователей APIГлава 61. ДокументацияГлава 62. Тестовая средаГлава 63. Управление ожиданиями + Поделиться: facebook · twitter · linkedin · redditСодержаниеВведениеГлава 1. О структуре этой книгиГлава 2. Определение APIГлава 3. Обзор существующих решений в области разработки APIГлава 4. Критерии качества APIГлава 5. API-first подходГлава 6. Обратная совместимостьГлава 7. О версионированииГлава 8. Условные обозначения и терминологияРаздел I. Проектирование APIГлава 9. Пирамида контекстов APIГлава 10. Определение области примененияГлава 11. Разделение уровней абстракцииГлава 12. Разграничение областей ответственностиГлава 13. Описание конечных интерфейсовГлава 14. Приложение к разделу I. Модельный API[В разработке] Раздел II. Паттерны дизайна APIГлава 15. О паттернах проектирования в контексте APIГлава 16. Аутентификация партнёров и авторизация вызовов APIГлава 17. Стратегии синхронизацииГлава 18. Слабая консистентностьГлава 19. Асинхронность и управление временемГлава 20. Списки и организация доступа к нимГлава 21. Двунаправленные потоки данных. Push и poll-моделиГлава 22. Мультиплексирование сообщений. Асинхронная обработка событийГлава 23. АтомарностьГлава 24. Частичные обновленияГлава 25. Деградация и предсказуемостьРаздел III. Обратная совместимостьГлава 26. Постановка проблемы обратной совместимостиГлава 27. О ватерлинии айсбергаГлава 28. Расширение через абстрагированиеГлава 29. Сильная связность и сопутствующие проблемыГлава 30. Слабая связностьГлава 31. Интерфейсы как универсальный паттернГлава 32. Блокнот душевного покоя[В разработке] Раздел IV. HTTP API и RESTГлава 33. О концепции HTTP API и терминологииГлава 34. Мифология RESTГлава 35. Составляющие HTTP запросов и их семантикаГлава 36. Преимущества и недостатки HTTP APIГлава 37. Принципы организации HTTP APIГлава 38. Работа с ошибками в HTTP APIГлава 39. Организация URL ресурсов и операций над ними в HTTP APIГлава 40. Заключительные положения и общие рекомендации[В разработке] Раздел V. SDK и UIГлава 41. О содержании разделаГлава 42. SDK: проблемы и решенияГлава 43. КодогенерацияГлава 44. UI-компонентыГлава 45. Декомпозиция UI-компонентов. MV*-подходыГлава 46. MV*-фреймворкиГлава 47. Backend-Driven UIГлава 48. Разделяемые ресурсы и асинхронные блокировкиГлава 49. Вычисляемые свойстваГлава 50. В заключениеРаздел VI. API как продуктГлава 51. Продукт APIГлава 52. Бизнес-модели APIГлава 53. Формирование продуктового виденияГлава 54. Взаимодействие с разработчикамиГлава 55. Взаимодействие с бизнес-аудиториейГлава 56. Линейка сервисов APIГлава 57. Ключевые показатели эффективности APIГлава 58. Идентификация пользователей и борьба с фродомГлава 59. Технические способы борьбы с несанкционированным доступом к APIГлава 60. Поддержка пользователей APIГлава 61. ДокументацияГлава 62. Тестовая средаГлава 63. Управление ожиданиями § @@ -3183,7 +3183,123 @@ GET /v1/orders/created-history⮠ в очереди могут скапливаться необработанные сообщения, внося нарастающие задержки, и решение этой проблемы на стороне подписчика может оказаться отнюдь не тривиальным. Отметим также, что в публичных API зачастую используются обе технологии в связке — бэкенд API отправляет задание на вызов webhook-а в виде публикации события, которое специально предназначенный для этого внутренний сервис будет пытаться обработать путём вызова webhook-а. -Теоретически можно представить себе и такую интеграцию, в которой разработчик API даёт партнёрам непосредственно прямой доступ к внутренней очереди сообщений, однако примеры таких API нам неизвестны.Глава 22. Варианты организации системы нотификацийГлава 23. АтомарностьГлава 24. Частичные обновленияГлава 25. Деградация и предсказуемостьРаздел III. Обратная совместимостьГлава 26. Постановка проблемы обратной совместимости +Теоретически можно представить себе и такую интеграцию, в которой разработчик API даёт партнёрам непосредственно прямой доступ к внутренней очереди сообщений, однако примеры таких API нам неизвестны.Глава 22. Мультиплексирование сообщений. Асинхронная обработка событий +Одно из неприятных ограничений почти всех перечисленных в предыдущей главе технологий — это относительно невысокий размер сообщения. Наиболее проблематичная ситуация с push-уведомлениями: Google Firebase Messaging на момент написания настоящей главы разрешал сообщения не более 4000 байт. Но и в серверной разработке ограничения заметны: например, Amazon SQS лимитирует размер сообщения 256 килобайтами. При разработке webhook-ов вы рискуете быстро упереться в размеры тел сообщений, выставленных на веб-серверах партнёров (например, в nginx по умолчанию разрешены тела запросов не более одного мегабайта). Это приводит нас к необходимости сделать два технических выбора: + +содержит ли тело сообщения все данные необходимые для его обработки, или только уведомляет о факте изменения состояния; +если второе, то содержит ли один вызов извещение об одном изменении, или может уведомлять сразу о нескольких таких событиях. + +Рассмотрим на примере нашего кофейного API: +// Вариант 1: тело сообщения +// содержит все данные о заказе +POST /partner/webhook +Host: partners.host +{ + "event_id", + "occurred_at", + "order": { + "id", + "status", + "recipe_id", + "volume", + // Все прочие детали заказа + … + } +} + +// Вариант 2: тело сообщения +// содержит только информацию +// о самом событии +POST /partner/webhook +Host: partners.host +{ + "event_id", + // Тип сообщения: нотификация + // о появлении нового заказа + "event_type": "new_order", + "occurred_at", + // Все поля данных, необходимые + // для обращения за полным + // состоянием. В нашем случае — + // идентификатор заказа + "order_id" +} +// При обработке сообщения, +// возможно, отложенной, +// партнёр должен обратиться +// к нашему API +GET /v1/orders/{id} +→ +{ /* все детали заказа */ } + +// Вариант 3: мы уведомляем +// партнёра, что его реакции +// ожидают три новых заказа +POST /partner/webhook +Host: partners.host +{ + // Здесь может быть версия + // состояния системы или курсор + "occurred_at", + "pending_order_count": + <число новых заказов> +} +// В ответ партнёр должен вызвать +// эндпойнт получения списка заказов +GET /v1/orders/pending +→ +{ + "orders", + "cursor" +} + +Выбор подходящей модели зависит от предметной области (в частности, допустимых размерах тел сообщений) и того, каким образом партнёр будет обрабатывать сообщение. В нашем конкретном случае, когда партнёр должен каждый новый заказ обработать отдельно, при этом на один заказ не может приходить больше одного-двух уведомлений, естественным выбором является вариант 1 (если тело запроса не содержит никаких непредсказуемо больших данных) или 2. Третий подход будет естественным выбором, если: + +API генерирует большое число сообщений об изменениях состояния на одну логическую сущность; +партнёров интересуют только наиболее свежие изменения; +или обработка событий требует последовательного исполнения и не подразумевает параллельности. + +NB: третий (и отчасти второй) варианты естественным образом приводят нас к схеме, характерной для клиентских устройств: push-уведомление само по себе не почти содержит полезной информации и только является сигналом для внеочередного поллинга. +Применение техник с отправкой только ограниченного набора данных помимо усложнения схемы взаимодействия и увеличения количества запросов имеет ещё один важный недостаток. Если в варианте 1 (сообщение содержит в себе все релевантные данные) мы можем рассчитывать на то, что возврат кода успеха подписчиком эквивалентен успешной обработке сообщения партнёром (что, вообще говоря, тоже не гарантировано, т.к. партнёр может использовать асинхронные схемы), то для вариантов 2 и 3 это заведомо не так: для обработки сообщений партнёр должен выполнить дополнительные действия, начиная с получения нужных данных о заказе. В этом случае нам необходимо иметь раздельные статусы — сообщение доставлено и сообщение обработано; в идеале, второе должно вытекать из логики работы API, т.е. сигналом о том, что сообщение обработано, является какое-то действие, совершаемое партнёром. В нашем кофейном примере это может быть перевод заказа партнёром из статуса "new" (заказ создан пользователем) в статус "accepted" или "rejected" (кофейня партнёра приняла или отклонила заказ). Тогда полный цикл обработки уведосления будет выглядеть так: +// Уведомляем партнёра о том, +// что его реакции +// ожидают три новых заказа +POST /partner/webhook +Host: partners.host +{ + "occurred_at", + "pending_order_count": + <число новых заказов> +} + +// В ответ партнёр вызывает +// эндпойнт получения списка заказов +GET /v1/orders/pending +→ +{ + "orders", + "cursor" +} + +// После того, как заказы обработаны, +// партнёр уведомляет нас об +// изменениях статуса +POST /v1/orders/bulk-status-change +{ + "status_changes": [{ + "order_id", + "new_status": "accepted", + // Иная релевантная информация, + // например, время готовности + … + }, { + "order_id", + "new_status": "rejected", + "reason" + }, …] +} + +Если такого нативного способа оповестить об успешной обработке события схема работы нашего API не предполагает, мы можем ввести эндпойнт который явно помечает сообщения прочитанными. Этот шаг, вообще говоря, необязательный (мы можем просто договориться о том, что это ответственность партнёра обрабатывать события и мы не ждём от него никаких подтверждений), но это лишает нас полезного инструмента мониторинга — что происходит на стороне партнёра, успевает ли он обрабатывать события — что в свою очередь затрудняет разработку упомянутых в предыдущей главе механизмов деградации и аварийного отключения интеграции.Глава 23. АтомарностьГлава 24. Частичные обновленияГлава 25. Деградация и предсказуемостьРаздел III. Обратная совместимостьГлава 26. Постановка проблемы обратной совместимости Как обычно, дадим смысловое определение «обратной совместимости», прежде чем начинать изложение. Обратная совместимость — это свойство всей системы API быть стабильной во времени. Это значит следующее: код, написанный разработчиками с использованием вашего API, продолжает работать функционально корректно в течение длительного времени. К этому определению есть два больших вопроса, и два уточнения к ним. diff --git a/docs/API.ru.pdf b/docs/API.ru.pdf index a384383..bdc7d8a 100644 Binary files a/docs/API.ru.pdf and b/docs/API.ru.pdf differ diff --git a/docs/index.html b/docs/index.html index 633fe03..daf41b3 100644 --- a/docs/index.html +++ b/docs/index.html @@ -61,7 +61,7 @@ Chapter 2. The API Definition Chapter 3. Overview of Existing API Development Solutions Chapter 4. API Quality Criteria -Chapter 5. The API-first approach +Chapter 5. The API-First Approach Chapter 6. On Backward Compatibility Chapter 7. On Versioning Chapter 8. Terms and Notation Keys @@ -88,7 +88,7 @@ Chapter 19. Asynchronicity and Time Management Chapter 20. Lists and Accessing Them Chapter 21. Bidirectional Data Flows. Push and Poll Models -Chapter 22. Organization of Notification Systems +Chapter 22. Chapter 23. Atomicity Chapter 24. Partial Updates Chapter 25. Degradation and Predictability diff --git a/docs/index.ru.html b/docs/index.ru.html index 48b68aa..d8ea75f 100644 --- a/docs/index.ru.html +++ b/docs/index.ru.html @@ -88,7 +88,7 @@ Глава 19. Асинхронность и управление временем Глава 20. Списки и организация доступа к ним Глава 21. Двунаправленные потоки данных. Push и poll-модели -Глава 22. Варианты организации системы нотификаций +Глава 22. Мультиплексирование сообщений. Асинхронная обработка событий Глава 23. Атомарность Глава 24. Частичные обновления Глава 25. Деградация и предсказуемость