Websvc » History » Version 3
Sachin Divekar, 23/12/2016 05:16 PM
1 | 1 | Shuvam Misra | # Web services: general rules |
---|---|---|---|
2 | |||
3 | {{>toc}} |
||
4 | |||
5 | ## Some basic rules |
||
6 | |||
7 | * We will expect requests in `POST`, not `GET`. We will not design URLs to communicate request parameters. |
||
8 | * All JSON data structures will have member names in full lowercase. No mixed-case will be used. |
||
9 | |||
10 | ## Web service request format |
||
11 | |||
12 | * Example |
||
13 | 2 | Shuvam Misra | |
14 | 3 | Sachin Divekar | ``` |
15 | 1 | Shuvam Misra | { |
16 | 2 | Shuvam Misra | "ver": 1, |
17 | "uid": 1234, |
||
18 | "data": { |
||
19 | "goal_id": 23 |
||
20 | } |
||
21 | 1 | Shuvam Misra | } |
22 | 3 | Sachin Divekar | ``` |
23 | 1 | Shuvam Misra | |
24 | * @ver@ is the API version to be used |
||
25 | * @uid@ is user id. For some web service calls it will be optional. e.g. when user is just playing around and creating temporary portfolios, GBA engine won't need @uid@ field. |
||
26 | * @data@ is request data object. sample request objects for each API have been provided in [[Apicalls|API calls wiki]] |
||
27 | |||
28 | In some cases (e.g. [[Goallist]]) a web service only requires @uid@ as input. In those cases value of data will be an empty object. |
||
29 | |||
30 | e.g. |
||
31 | |||
32 | 3 | Sachin Divekar | |
33 | ``` |
||
34 | 1 | Shuvam Misra | { |
35 | "ver": 1, |
||
36 | "uid": 1234, |
||
37 | "data": {} |
||
38 | } |
||
39 | 3 | Sachin Divekar | ``` |
40 | 1 | Shuvam Misra | |
41 | ## Web service response format |
||
42 | |||
43 | A common JSON data structure will be returned by the API for success or errors. |
||
44 | For successes following JSON structure will be returned. |
||
45 | 3 | Sachin Divekar | |
46 | ``` |
||
47 | 1 | Shuvam Misra | { |
48 | "status": "success", |
||
49 | "data": { |
||
50 | /* Application-specific data payload goes here. */ |
||
51 | }, |
||
52 | "message": [] /* Or optional success message */ |
||
53 | } |
||
54 | 3 | Sachin Divekar | ``` |
55 | |||
56 | 1 | Shuvam Misra | The value of @data@ for each API call is provided in the [[Apicalls|API calls documentation]]. For errors, the following JSON structure will be returned. |
57 | 3 | Sachin Divekar | |
58 | ``` |
||
59 | 1 | Shuvam Misra | { |
60 | "status": "error", |
||
61 | "data": {}, |
||
62 | "message": [{ |
||
63 | "code": "code1", |
||
64 | "msg": "message1" |
||
65 | }, { |
||
66 | "code": "code2", |
||
67 | "msg": "message2" |
||
68 | }] |
||
69 | } |
||
70 | 3 | Sachin Divekar | ``` |
71 | |||
72 | 1 | Shuvam Misra | Example errors returned. |
73 | 3 | Sachin Divekar | |
74 | ``` |
||
75 | 1 | Shuvam Misra | { |
76 | "status": "error", |
||
77 | "data": {}, |
||
78 | "message": [{ |
||
79 | "code": "permission_denied", |
||
80 | "msg": "No permission for the requested operation." |
||
81 | }, { |
||
82 | "code": "account_restricted", |
||
83 | "msg": "The user account is disabled." |
||
84 | }] |
||
85 | } |
||
86 | 3 | Sachin Divekar | ``` |
87 | 1 | Shuvam Misra | |
88 | ## Reporting errors by web services |
||
89 | |||
90 | Each error reported has two parts |
||
91 | * the error code |
||
92 | * the human readable error message |
||
93 | |||
94 | The code is always going to be one word, always in lower case, with letters, digits, and/or underscore characters. |
||
95 | |||
96 | The code is the real indicator of the type of error, and must be used by the client code. It may handle the error, it may retry the operation, it may branch into a different path in the code, it may select a message to show the end-user, _etc_, as needed. The error message supplied by the GBA web service is meant for the programmer of the client software to understand and debug the web service call. |
||
97 | |||
98 | In multi-lingual user interfaces, the error message must be indexed to the combination of (language, errcode). The responsibility of designing and selecting meaningful error messages in the correct language lies with the client software, not with GBA. The client software dev team must build error message tables in each supported language, indexed with the GBA error-code. The error message supplied by GBA will always be in English, and may not have appropriate wording to display directly to the end-user. Its audience is the programmer of the client software. |
||
99 | |||
100 | ## ID formats |
||
101 | |||
102 | All IDs internally generated by GBA, e.g. goal-ID, scheme-investment-ID, temporary-portfolio-ID, ops-list-ID, _etc.,_ are all to be treated as opaque strings, _not_ as integers. |
||
103 | |||
104 | The GBA rules for ID syntax is: |
||
105 | * opaque, meaningless string |
||
106 | * between 1 and 50 octets long, variable length |
||
107 | * one word, _i.e._ no spaces or special characters in the word, only letters and digits |
||
108 | * case sensitive |
||
109 | * may start with a digit or a letter |
||
110 | * equality test possible, _i.e._ if two ID strings are identical as strings and refer to the objects of the same class, then they refer to the same instance |
||
111 | * guaranteed unique, _i.e._ if two object instances of the same class exist in GBA, they are guaranteed to have two separate ID strings |
||
112 | * ordering is meaningless, _i.e._ "greater than" or "less than" operation is meaningless |
||
113 | |||
114 | Note that this means that GBA may use integers as IDs, and all these rules will be fulfilled. But while representing them in JSON, the IDs will always be enclosed in double-quotes, even if they "look like" integers. |
||
115 | |||
116 | Examples of IDs: |
||
117 | * "a0ae48b16f90db8f3c542f44f8103701" |
||
118 | * "5" |
||
119 | * "750294852039" |
||
120 | |||
121 | Examples of strings which are not IDs: |
||
122 | * "a0ae48b16f90db8f3c542f4/f8103701" (there's a special character in it) |
||
123 | * 5 (a digit without quotes is not a string) |
||
124 | * "776,245,664" (commas are not permitted in IDs) |
||
125 | * "62.6" (the period is not permitted) |
||
126 | |||
127 | ## Authentication |
||
128 | |||
129 | GBA does no authentication of users who use the service. The front-end(s) which connect to GBA must have their own mechanism for authentication. GBA works with trusted client services, _i.e._ it trusts all requests it receives and believes all information given. If it receives a user-ID in a request, it makes no attempt to verify that this user-ID is valid or that it exists, or that it is allowed to use the GBA services. |
||
130 | |||
131 | ## API versions |
||
132 | |||
133 | Any web service (we will refer to it as "service" here) which is exposed to multiple clients (software systems which send web services requests to our service) will, over time, have to serve old clients and new ones. |
||
134 | |||
135 | Our service will grow in features and functionality, and the semantics of some web services may change. For instance, a particular web service may have been released initially with just three parameters in its input, but a fourth parameter was felt necessary after two years of service. Some older clients will still access the web service with three parameters and newer clients will pass four parameters to it. _C'est la vie_. One of the most obvious examples of this is when mobile apps access a web service. Some phones will have older releases of the mobile app and others will have newer releases. This makes it necessary for the web service to serve all generations of clients without breaking any. |
||
136 | |||
137 | One way to handle this is by adding an "API version number" parameter to each web service. This will be a mandatory parameter from Day 1. Initial clients will all be told to use @"ver": 1@ in their requests. When the service upgrades any web service and semantics change, then it will support the old semantics under @ver=1@ and newer semantics with @ver=2@. Newer clients which are aware of the updated semantics will use @ver=2@ in their requests. Older clients will not be aware of any changes. |
||
138 | |||
139 | The version number applies to each web service in isolation. The service as a whole may have versions 1 and 2 supported for some calls, 1, 2 and 3 for other calls, and just 1 for calls which have not changed at all. |
||
140 | |||
141 | This will go on, and new generations of web services will keep getting released. This will allow a single service to service multiple generations of clients at the same time. |
||
142 | |||
143 | This design approach is being used in GBA. The @ver@ parameter is mandatory and has an integer value. |
||
144 | |||
145 | ## History tables |
||
146 | |||
147 | Transaction tables which receive updates will also have history tables which "shadow" the main tables. This will ensure that, taken in an overall database context, all updates are non-destructive, because all before-images of records can be reconstructed by analysing the history tables. |
||
148 | |||
149 | History tables will contain |
||
150 | * previous images of updated records |
||
151 | * deleted records |
||
152 | |||
153 | The following policies will be applied for maintenance of history information: |
||
154 | * When a record is inserted in a main table, nothing is done to the history table. (This means that there is no history-related overhead of compute power or disk space for tables which are not modified much.) |
||
155 | * When a record is updated in a main table, its previous image is first inserted into the history table and then the data is updated in the main table |
||
156 | * When a record is physically deleted (_i.e._ using the SQL @DELETE@ operation) from a main table, the to-be-deleted record is first copied into the history table |
||
157 | * When @truncate@ operation is performed on the table, all the rows in the current table will be inserted to its history table |
||
158 | |||
159 | These are the implementation specifications for implementing the history feature: |
||
160 | * All main tables which are supposed to get the benefit of history tracking will now have corresponding history tables to "shadow" them. If the main table is called *@X@*, its shadow table will be called *@X_hist@*. |
||
161 | * The history maintenance feature will be implemented using Postgres triggers. |
||
162 | * The shadow table will have identical schema to the main table, with two additional fields: |
||
163 | ** *@hist_when@*: timestamp specifying when this record was inserted in the shadow table |
||
164 | ** *@hist_op@*: will contain either "@U@", "@D@" or "@T@", indicating that this history replica is because of an u(pdate), d(eletion) or t(runcated) |
||
165 | * The GBA application code will connect to the database using a specific database username and password meant for business operation. (Let's say that this username is @gba@.) This username will not have any rights on the shadow tables other than @INSERT@ rights. A separate, second database user (let's say, @gbahist@) will have @SELECT@ rights on the shadow table, and only the administrator will be able to modify the contents of shadow tables. |
||
166 | |||
167 | ## Timestamps |
||
168 | |||
169 | As per JSON Schema specification for "date-time":http://json-schema.org/latest/json-schema-validation.html#anchor108, for timestamps values, we will always use the format defined in "RFC 3339":https://tools.ietf.org/html/rfc3339#section-5.8 _e.g._ @1990-12-31T23:59:50Z@ for an Indian timezone timestamp or @201512-31T23:59:50+05:30@ for an Indian timezone timestamp. |