Are basecamp resources ID unique? - basecamp

I found a couple references but quite very old and I know the API has changed since.
Are all resources IDs globally unique (across all accounts)?
For instance are all to-do item IDs unique accross all accounts in the system ?
I want to know as i would like associate data with a to-do ID and i want to make sure to avoid collisions (as unlikely as they could be)
EDIT:
Here is a sample ID: 8549954
One of the post i referred to: https://groups.google.com/forum/#!searchin/37signals-api/ID$20unique/37signals-api/cNm-HKZ5fQY/xi497xpem1AJ
Thanks for clarifying.

They are unique across accounts, within the same product. So, for all requests to the Basecamp API (https://github.com/basecamp/bcx-api), you can treat the resource IDs as unique.

Related

Get purchased product from PaymentIntent

in my app i want to list past purchases for a stripe customer. So I was looking at the relevant API objects like PaymentIntents, Sessions or Charges. But they all do not seem to contain any reference to Product or Price, which I would need to list the purchased products.
Subscriptions contain a list of items that are contained in that subscription, so I was expecting PaymentIntents to have something like that too.
Does anyone has an idea how to archive my list of past purchases? Thanks!
I did some digging through the Stripe API docs[1] and, out of the three objects you referrenced (PaymentIntent, Session, Charges), the only one that I can see being able to trace back to a product is the Session.
Session objects have a line_items property[2] which can be followed all the way down to line_items.data.price.product[3]. To access this you’ll need to inlcude the expand=["data.line_items"] parameter to your call to list Checkout Sessions. You can read more about expanding API responses here[4]
So for all the charges to your customers that were done using Checkout Sessions, you could list them all, use the customer property to associate earch session with a customer in your application, traverse the the returned data, and then query the API for the product details. If you have a lot of customers & products these API calls will add up fast so I would store this data in your back-end to avoid hitting rate limits[5].
Alternatively, you could just save the product ID (either Stripe or your local version) as metadata[6] for any of the above Stripe payment objects listed. That would allow you to link any payment object you wish to a product.
https://stripe.com/docs/api
https://stripe.com/docs/api/checkout/sessions/object#checkout_session_object-line_items
https://stripe.com/docs/api/checkout/sessions/object#checkout_session_object-line_items-data-price-product
https://stripe.com/docs/expand
https://stripe.com/docs/rate-limits
https://stripe.com/docs/api/metadata
I had the same question I found a way to retrieve the products related to a specific PaymentIntent.
You need to get the sessions that was linked to PaymentIntent when the Checkout process was made.
I will give you the code (in PHP) that I use to to this.
\Stripe\Stripe::setApiKey(STRIPE_API_SECRET);
// Find the Session for that PaymentIntent
$sessions = \Stripe\Checkout\Session::all([
'payment_intent' => "pi_xxxxxxxxxx",
'expand' => ['data.line_items'],
]);
You will then have an key line_items that contain the products linked.
Enjoy

Track multiple context for the same Bot

We have a bot that will be used by different customers and depending on their database, sector of activity we're gonna have different answers from the bot and inputs from users. Intents etc will be the same for now we don't plan to make a custom bot for each customer.
What would be the best way to separate data per customer within Chatbase?
I'm not sure if we should use
A new API key for each customer (Do we have a limitation then?)
Differentiate them by the platform filter (seems to not be appropriated)
Differentiate them by the version filter (same it would feel a bit weird to me)
Using Custom Event, not sure how though
Example, in Dialogflow we pass the customer name/id as a context parameter.
Thank you for your question. You listed the two workarounds I would suggest, I will detail the pros/cons:
New API Key for each customer: Could become unwieldy to have to change bots everytime you want to look at a different users' metrics. You should also create a general api (bot) where you send all messages in order to get the aggregate metrics. This would mean making two api calls per message.
Differentiate by version filter: This would be the preferred method, however it could lengthen load times for your reports as your number of users grows. The advantage would be that all of your metrics are in one place, and they will be aggregated while only having to send one api call per message.

What's the right way to gather data from different microservices?

I'm having a problem understanding how basic communication between microservices should be made and I haven't been able to find a good solution or standard way to do this in the other questions. Let's use this basic example.
I have an invoice service that return invoices, every invoice will contain information(ids) about the user and the products. If I have a view in which I need to render the invoices for a specific user, I just make a simple request.
let url = "http://my-domain.com/api/v2/invoices"
let params = {userId:1}
request(url,params,(e,r)=>{
const results = r // An array of 1000 invoices for the user 1
});
Now, for this specific view I will need to make another request to get all the details for each product on each invoice.
results.map((invoice)=>{
invoice.items.map((itemId)=>{
const url=`http://my-domain.com/api/v2/products/${itemId}`
request(url,(e,r)=>{
const product = r
//Do something else.....
});
});
});
I know the code example is not perfect but you can see that this will generate a huge number of requests(at least 1000) to the product service and just for 1 user, now imagine if I have 1000 users making this kind of requests.
What is the right way to get the information off all the products without having to make this number of requests in order to avoid performance issues?.
I found some workarounds for this kind of scenarios such as:
Create an API endpoint that accepts a list of IDs in order to make a single request.
Duplicate the information from the Product service within the invoice service and find a way to keep them in sync.
In a microservices architecture are these the right ways to deal with this kind of issues? For me, they look like simple workarounds.
Edit #1: Based on Remus Rusanu response.
As per Remus recommendation, I decided to isolate my services and describe them a little bit better.
As shown in the image above the microservices are now isolated(in specific the Billing-service) and they now are the owners of the data. By using this structure I ensure that Billing-service is able to work even if there are async jobs or even if the other two services are down.
If I need to create a new invoice, I can call the other two microservices(Users, Inventory) synchronously and then update the data on the "cache" tables(Users, Inventory) in my billing service.
Is it also good to assume these "cache" tables are read-only? I assume they are since only the user/inventory services should be able to modify this information to preserve isolation and authority over the information.
You need to isolate the services as so they do not share state/data. The design in your question is a single macroservice split into 3 correlated storage silos. Case in point, you cannot interpret a result form the 'Invoicing' service w/o correlating the data with the 'Products' response(s).
Isolated microservices mean they own their data and they can operate independently. An invoice is complete as returned from the 'Invoices' service. It contains the product names, the customer name, every information on the invoice. All the data came from its own storage. A separate microservice could be 'Inventory', that operates all the product inventories, current stock etc. It would also have its own data, in its own storage. A 'product' can exist in both storage mediums, and there once was logical link between them (when the invoice was created), but the link is severed now. The 'Inventory' microservice can change its products (eg. remove one, add new SKUs etc) w/o affecting the existing Invoices (this is not only a microservice isolation requirement, is also a basic accounting requirement). I'm not going to enter here into details of what is a product 'identity' in real life.
If you find yourself asking questions like you're asking it likely means you do not have microservices. You should think at your microservice boundaries while considering what happens if you replace all communication with async queued based requests (a response can come 6 days later): If the semantics break, the boundary is probably wrong. If the semantics hold, is the right track.
It all depends on the resilience requirements that you have. Do you want your microservice to function when the other microservices are down or not?
The first solution that you presented is the less resilient: if any of the Users or Products microservices goes down, the Invoice microservice would also go down. Is this what you want? On the other hand, this architecture is the simplest. A variation of this architecture is to let the client make the join requests; this leads to a chatty conversation but it has the advantage that the client could replace the missing information with default information when the other microservices are down.
The second solution offers the biggest possible resilience but it's more complex. Having an event-driven architecture helps a lot in this case. In this architecture the microservices act as swimming lanes. A failure in one of the microservices does not propagate to other microservices.

REST API - How to design rest api?

I'm little bit confused about when to create a new entity in rest. I have this rest api implemented in node:
GET api/v1/services - get all services
GET api/v1/services/{serviceId}/suppliers - get all suppliers for service id
Now, I want to add another api for getting all suppliers, no matter which service.
Does the following approach is good practice?
GET api/v1/services/suppliers - get all suppliers
PUT api/v1/services/suppliers/{supplierId} - edit by supplier id
Or should we need to create a new suppliers entity?
I hope that #wizard already found an answer for his question.
But here are my thoughts.
As per my understanding, the resource "api/v1/services/suppliers" is not a right way to get back all the suppliers. We can use the REST Subresources to represent the relationships so that it will be more readable one. But here Supplier resource can't be used outside of parent resource(Services).
But in this case, we want to get all supplier details and also update the specific supplier information. Hence we require a flexible API. So we have to create another endpoint(/api/v1/suppliers) for working with supplier details.
(/api/v1/suppliers - fetch all the supplier details(GET)
and
/api/v1/suppliers/{supplierId} [PUT] for updating a specific supplier.

DDD, external datas and Repository

I'm thinking to use DDD for our next application. I have already found a lot of interesting papers and answers but cannot find a solution to my problem :
We have an SOA. architecture where some services are known as master of their datas. That's nice but I can't figure how to use them nicely with DDD.
Given a service "employees" who is the master of the Employee datas, it is a crud over a couple of simple values (first and lastname, birthdate, address).
My new app, should track the trainings offered to those employees. So I have the concept of Participant, a Participant has the same values as an Employee plus a list of trainings and a skill.
We can suppose that the "trainings" applications has a database with a table of participants that contains a participant_id, skill and one employee_id used to retrieve the first and lastname.
Am I correct ?
But now, which component may I use to call the "employees" service ? Is it the ParticipantRepository so that when I get a participant I have is names. Or is it the application service who complete the Participant datas before using them. Or may I explicitly call the employees service when needed ?
Thanks a lot.
In your training application (I mean in the domain of your application) the concept of an employee might not exist as other than an external reference. As you correctly said, that will be a Participant.
I understand that you need to get some data from the employee service to populate the participant. I can think of few options.
1) ParticipantRepository builds a Participant, which is an aggregate root, some of that data might be in a PersonalDetails value object. This value object is constructed by calling the employee app. This approach is easy, but might not be the best. This is the approach you mentioned, where the ParticipantRepository calls an interface PersonalDetailsService and the implementation of that interface does the actual call to the Employee service. In this way, your domain has no idea that is dealing with employees, as it only sees PersonalDetails.
2) Eventual consistency by replicating data from the employee service: If the employee service can send a notification when an employee is updated (e.g. via messaging) you can listen to those events and have a read only copy of the data. The benefit of this is that your app will work even if the employee service goes down. The problem is that you might need to build something to re-send data that might have got lost.
Both of these approaches are explained quite well in the book Implementing Domain-Driven Design

Resources