I'm working on a D2L add-on right now and trying to retrieve all the courses the current user is enrolled in. The only way I found so far is using the
GET /d2l/api/lp/(version)/enrollments/myenrollments/ call. This works perfectly for a small amount of courses and is extremely slow for more than approximately 50 courses. Is there any better way to retrieve all the enrollments?
Thanks in advance
For end-users, this call is indeed the one intended to address this need. Since a portion of the performance drop may come from having to process a series of data pages (requiring several calls), you can try several techniques to add a bit of performance here:
You can pre-filter the call based on org unit type: this likely requires you as the app developer to know the org unit type IDs for the org units of interest to your end users. For example, if your main use case here is "student wants to see all the course offerings she's enrolled in", then you can provide the appropriate org unit type ID for course offering org units to your API call. This becomes more difficult if your app must address several different back-end services, or you don't know the org unit type ID used by the back-end service for the relevant org unit types.
You can try using an HTTP library that can pool connections, and batch together the calls that fetch all the data pages you need to get the complete list of enrollments needed. This will provide you with some benefit to overhead on each call, but the performance benefit will likely only be marginal.
Currently, this API route does not allow the caller to request a particular data page size, and allowing that would improve the overall latency involved in this use case: for example, requesting a page size of 500 records could conceivably fetch back all the enrollments in a single call. I would judge page-size requesting to be a completely reasonable feature enhancement to request, and I would encourage you to request it on D2L's Product Idea Exchange; in fact, I'd be rather surprised if someone hasn't already done so.
Related
I work in a large enterprise where multiple teams are developing Lex bots (on separate accounts). Each bot supports a different domain or application,. In some cases, it would be nice for a single user interface to ask a question without needing to know which bot to ask. Is there a way to federate bots, or to forward un-recognized intentions to 'backup' bots?
I feel like what I really want to do is treat each bot as a skill is treated in Alexa, except I'm in the position (through entitlements) to know which 'skills' would be appropriate for a given user.
The answer here is that you would need to develop a custom application that delivers a user's input to each of your company's array of bots.
You'd need to look at the NLU Confidence score from each Bot's response to decide which response is the most accurate to return to the user. Would also be worthwhile keeping some state in your app to remember which Bot the user is currently interacting with and defaulting to that Bot for successive user inputs. Should you reach a point where the confidence score is low, it might present a signal to you to test the user's input across the other Bots.
What you'll need to be aware of here is that your costs will increase with each additional Bot that you add. So, assuming you have 5 area-specific Bots, one inbound message from your user could result in 5 Lex calls. As you start moving into significant volumes of interactions, this could start proving to be an obstacle.
An alternative would be to use a custom fallback intent to invoke a Lambda function that calls your Bot orchestration function. Assuming that you're able to find the correct Bot to handle the user's query, you'd need to remember that so succesive messages now get routed to that Bot.
I've been using /d2l/api/lp/1.4/enrollments/myenrollments/ to get a list of enrollments for the current user. Now, I want to just get the enrollments where the user is in an instructor role. So, I'm trying to use:
/d2l/api/lp/1.4/enrollments/users/{userId}/orgUnits/?roleId=105
When I use that, I get an empty list of Items back, with or without the roleId specified.
My expectation is that just calling it without the roleId would return the same list as /d2l/api/lp/1.4/enrollments/myenrollments/. But, I always get an empty list, except when I log in as a system administrator. Only in that case do I get anything back.
Does anyone have any suggestions on what I might be doing wrong?
The various my* API calls specifically exist to provide end users to fetch back details about the system that they should know, but segregated from information they shouldn't (that's available through the more general routes for a particular area). Enrollments is a good example of this. And end-user should be able to see their own enrollments, but they should not have generalized access to enrollment records. In particular, the D2L system treats the D2L user role belonging to an enrollment as fairly privileged information, and a side effect of this is that it's not generally visible to end users.
One way that applications and services can cope with achieving goals that the end-user cannot themselves perform is to have set up a "service account" that the app can use to make calls of an administrative nature, to fetch back data that they can use in the business logic around presenting information to end users. In this particular case, you could, for example use the service account to make calls about a user's enrollments, and then present the user with logic that could filter the list of their enrollments by "these are the student ones, and these are the ones where you're a teacher, and a tutor, and so forth".
But you'd also need to carefully consider the implications of this type of activity in balance against the intentions of the client LMS's policies and administration. Even this level of information may be giving away too much to end users, in the eyes of a client LMS administrator.
Using a service account to let an app make administrative level calls must always be done with great care around the issue of information/functional leakage to end users.
Say you have a Recipe Manager application that you're building with a Web Api project. Do you send the list of recipes along with their ingredient names in JSON? Or do you send the recipes, ingredient names, and ingredient details? What's the process in determining how big the initial payload should be for a SPA?
These are the determining factors in how much to send to the client in an initial page:
Data that will be displayed for that first page
Lookup list data for any drop downs on that page
Data that is required for and presentation rules (might not be displayed but is used)
On a recipe page that would show a list of recipes, I would get the recipes and some key factors to display (like recipe name, the dish, and other key info) that can be displayed in a list. Enough for the user to make a determination on what to pick. Then when the user dives into a recipe, then go get that 1 recipe's details.
The general rule is get what you user will almost certainly need up front. Then get other data as they request it.
The process by which you determine how much data to send solely depends on the experience you want to provide your users - however it's as simple as this. If my experience demands that I readily display all of the recipes with a brief description and then allow them to drill into the recipe to get more information, then I'm only going to send enough information to produce the display and navigate further into the entity.
If then after navigating into the recipe it requires that you display the ingredient names and measures then send down that and enough information to navigate further into any single ingredient.
And as you can see it just goes on and on.
It depends if your application is just a simple HTTP API backing your web page, or your goal is something more akin to Platform As A Service. One driver for the adoption of SPA is that it makes the browser another client, just like an iOS or Android app,or a 3rd party.
If you want to support multiple clients, then it's likely that you want to design your APIs around the resources that you are trying to expose, such that you can use the uniform interface of GET/POST/PUT etc. against that resource. This will means it is much more likely that you are not coding in an client specific style and your API will be usable by a wide range of clients.
A resource is anything you would want to have its own URN.
I would suggest that is likely that in this case you would want a Recipe Book resource which has links to individual Recipe resources, which probably contain all the information necessary for that Recipe. Ingredients would only be a separate resource if you had more depth on what an Ingredient contained and they had their own resource.
At Huddle we use a Documentation Driven Design approach. That is we write the documentation for our API up front so that we can understand how usable our API would be. You can measure API quality in WTFs. http://code.google.com/p/huddle-apis/
Now this logical division might not be optimal in terms of performance. Your dealing with a classic tradeoff (ultimately architecture is all about balancing design tradeoffs) here between usability of your API and the performance of your API. Usually, don't favour performance until you know that it is an issue, because you will pay a penalty in usability or maintainability for early optimization.
Another possibility is to implement the OData query support for WebAPI. http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api
That way, your clients can perform their own queries to return only the data they need.
I have now played with the QBO and QBD APIs and feel I have a fair understanding of how it thinks and how to interact with it. So now it is time to design the actual integration solution.
Inside my application you can create new customers, quote services, perform services, and soon, pass invoices to QuickBooks, sounds easy.
But what if the customer is not in QB yet? No problem - for each invoice I will look up the customer (need the id anyway) and if it doesn’t exist, add it. But if I have to look up the customer for each invoice it seems like it might be slow. I will likely have 30,000 customers and have 500-3000 invoices per day.
So my question is this; what are others doing?
a) Are you storing the QB id for each customer in your data?
b) How do you detect address changes (changed in your app and changed in QB)?
c) Is the batch submission interface so much faster I should use that?
Thanks for your help!
We often times do store the QB id in our database for use. If we post an invoice into QB, we'll then store the QB id for future use if we need to modify it.
As far as detecting changes on the customer record and other info, there's a couple ways to handle the conflict resolution. One is to keep a timestamp on your side as to when changes are made. You can then compare this with the timestamp of the last change on the QB record and then make your decision as to which one gets updated.
FreddyMac,
To detect changes on the Intuit side you can construct a query with a CDCasOf Filter, which will return only the data that has changed since a date you provide. (ChangeDataCapture as of)
https://ipp.developer.intuit.com/0010_Intuit_Partner_Platform/0050_Data_Services/0500_QuickBooks_Windows/0100_Calling_Data_Services/0015_Retrieving_Objects
You need to keep track of data changes on your side.
The batch submission is not faster, its just easier for you to write the code.
The IPP SDK can queue the API calls for your and aggregate the responses.
regards,
Jarred
I'm creating a twilio service with three actors:
The customer, a person who calls a company
The company, a company who forwards calls to the service-provider
The service-provider (that's us), an entity that services the customer on behalf of the company
Herein lies the catch: The service provider needs to be able to identify the company associated with the customer but it may only use a single phone number. We cannot use multiple phone numbers for cost reasons (the margins are that low). We cannot use the caller id because a single customer may be associated with multiple companies.
I am familiar with Twilio's ForwardedFrom field but as mentioned here it isn't always reliable. In fact, forwarding from my cell-phone carrier results in a null ForwardedFrom field.
How can we (reliably) identify the company who redirected a customer to us without using multiple phone numbers?
You can use the number + extension. http://www.twilio.com/docs/howto/ivrs-extensions
Perhaps you could build a sort of phone tree system, asking the caller the nature of their problem, which would be an indicator of the company their call is related to.
My guess is that you wouldn't want an outright "which company are is your call related to?" question, because that would feel cheap to the customer. So, maybe you could formulate a question or series of questions that wouldn't be overtly asking which company their calling about, but the answer(s) would clearly indicate on the service-provider end which company the call is about.
This could be further whittled down on the service-provider end by doing a company lookup based on the customer's calling number - if it matches a certain company (or set of companies), then that automatically limits the potential company they could be calling about.
Another possibility (if it fits in your use case) is some sort of we'll-call-you setup. Perhaps the customer could text/email requesting a call, and the information they'd provide in the text/email/online-form-submission would indicate the company they wish to speak about (again, you could use questions that aren't overtly "which company do you want a call from?").
Then again, if it's such a low-margin operation, maybe the companies are ok with a phone-tree style call-in number, where the customer needs to select a company they're calling about which is then indicated to the service-provider.
This doesn't seem to be possible at this time (2013). I will keep an eye out for new answers and will accept them if this becomes possible at a later time.
In general, I'd recommend separate numbers per customer but since you say that's not an option, here's another approach:
When the call comes into the Company, that individual leg gets a CallSid which is a unique identifier. When the call is forwarded to the Service Provider, that separate leg also gets a CallSid. Let's call them CallSidOne and CallSidTwo respectively.
If you then query based on CallSidTwo, you'll get back its instance properties as listed here:
http://www.twilio.com/docs/api/rest/call#instance-properties
The key property here is "parent_call_sid" which should be CallSidOne. Therefore, you can connect the two segments together.. then you can query on CallSidOne which gives you the ability to track who called which customer called which customer when.
Does that solve your problem?
~Twilio employee