O slideshow foi denunciado.
Utilizamos seu perfil e dados de atividades no LinkedIn para personalizar e exibir anúncios mais relevantes. Altere suas preferências de anúncios quando desejar.
Beyond REST:

Coursera’s API Evolution
Bryan Kane
! @bryanskane
" bryan-coursera
Problems
• Number of courses grew rapidly
• Product needs changed:
• premium course certificates
• specializations
• multi...
Scale matters!

In many dimensions

• Queries per second
• Data set size
• Engineers
• Types in ontology
Transition to Microservices
Performance Requirements
• Minimize data transfer across the network
• Minimize round trips
Nice-to-have’s
• Caching
• ETa...
Experience-based
APIs
Queryable

APIs
Relational Algebra Meets

REST/JSON APIs
Projection: filter fields in response
Selection: filter items in a collection
Joi...
https://api.coursera.org/api/courses.v1?q=slug&slug=machine-learning

response:
{
"elements": [
{
"courseType": "v2.ondema...
https://api.coursera.org/api/courses.v1?q=slug&slug=machine-learning

&fields=primaryLanguages

response:
{
"elements": [
...
https://api.coursera.org/api/courses.v1?q=slug&slug=machine-learning

&fields=instructorIds&includes=instructorIds

respon...
https://api.coursera.org/api/courses.v1?q=slug&slug=machine-learning

&fields=instructorIds,instructors.v1(title)&includes...
0
200
400
600
800
Controllers vs Naptime Resources
Controllers
Resources
Naptime Key Learnings
• Leverage type safety, carefully
• Collections of Key-Value pairs
• Opinionated framework improves ...
context.executeAction(setCourseIdentifiers, {courseId, courseSlug});
context.executeAction(loadMembership);
context.execut...
Imperative Data Fetching Declarative Data Fetching
api.loadCourses().then(courses => {
const courseIds = courses.map(c => ...
NaptimeStore: {
"courses.v1": {
"69Bku0KoEeWZtA4u62x6lQ": {…},
"0HiU7Oe4EeWTAQ4yevf_oQ": {…},
"5zjIsJq-EeW_wArffOXkOw": {…...
Problems remained

• There are always going to be edge cases
• Feature prioritization requires careful balance
• Don’t und...
GraphQL Query:
query {
CoursesV1Resource {
slug(slug: "machine-learning") {
id
}
}
}
request endpoint:
/api/courses.v1
req...
request endpoint:
/api/courses.v1
request query parameters:
{
"q": "slug",
"slug": "machine-learning",
"fields": "primaryL...
request endpoint:
/api/courses.v1
request query parameters:
{
"q": "slug",
"slug": "machine-learning",
"fields": "instruct...
request endpoint:
/api/courses.v1
request query parameters:
{
"q": "slug",
"slug": "machine-learning",
"fields": "instruct...
Edge Tier
GraphQL
Assembler
Profile
Service
Enrollments
Service
Catalog
Service
Edge Tier
GraphQL
Assembler
Profile
Service
Enrollments
Service
Catalog
Service
Key Lessons Learned
Carefully understand your problem
Look to theory: stand on the shoulders of giants
Plug into the ecosy...
Naptime is developed in the open
https://github.com/coursera/naptime
Thank you!
Thank you!
Bryan Kane
! @bryanskane
" bryan-coursera
Beyond REST - Coursera's API evolution
Beyond REST - Coursera's API evolution
Beyond REST - Coursera's API evolution
Beyond REST - Coursera's API evolution
Beyond REST - Coursera's API evolution
Beyond REST - Coursera's API evolution
Beyond REST - Coursera's API evolution
Beyond REST - Coursera's API evolution
Próximos SlideShares
Carregando em…5
×

Beyond REST - Coursera's API evolution

Coursera’s educational platform has a broad API surface implemented in a standardized REST framework backed by a distributed microservice architecture. However, one of the biggest challenges engineers face is discovering and assembling the data required to render the UI on both web and mobile clients. To help improve our engineering velocity, we are migrating nearly 100% of our client data access to GraphQL, which provides better API discoverability, well-tested and community supported client libraries, and powerful type-checking and developer tooling. But we’re doing it WITHOUT throwing away our existing backend APIs, architecture, and tools. This talk will describe both how and why we're making every Coursera API available via GraphQL, the key principles that went into developing our API framework, Naptime, and what we've learned along the way.

https://www.meetup.com/graphql-by-the-bay/events/235184302/

  • Seja o primeiro a comentar

Beyond REST - Coursera's API evolution

  1. 1. Beyond REST:
 Coursera’s API Evolution Bryan Kane ! @bryanskane " bryan-coursera
  2. 2. Problems • Number of courses grew rapidly • Product needs changed: • premium course certificates • specializations • multi-university collaborations. • Growing size of engineering team
  3. 3. Scale matters!
 In many dimensions
 • Queries per second • Data set size • Engineers • Types in ontology
  4. 4. Transition to Microservices
  5. 5. Performance Requirements • Minimize data transfer across the network • Minimize round trips Nice-to-have’s • Caching • ETag & Conditional Request Support • Binary Serialization
  6. 6. Experience-based APIs Queryable
 APIs
  7. 7. Relational Algebra Meets
 REST/JSON APIs Projection: filter fields in response Selection: filter items in a collection Joins: related resources
  8. 8. https://api.coursera.org/api/courses.v1?q=slug&slug=machine-learning
 response: { "elements": [ { "courseType": "v2.ondemand", "id": "Gtv4Xb1-EeS-ViIACwYKVQ", "name": "Machine Learning", "slug": "machine-learning" } ], "linked": {}, "paging": { "total": 1 } } request endpoint: /api/courses.v1 request query parameters: { "q": "slug", "slug": "machine-learning" }
  9. 9. https://api.coursera.org/api/courses.v1?q=slug&slug=machine-learning
 &fields=primaryLanguages
 response: { "elements": [ { "courseType": "v2.ondemand", "id": "Gtv4Xb1-EeS-ViIACwYKVQ", "name": "Machine Learning", "slug": "machine-learning", "primaryLanguages": ["en"] } ], "linked": {}, "paging": { "total": 1 } } request endpoint: /api/courses.v1 request query parameters: { "q": "slug", "slug": "machine-learning", "fields": "primaryLanguages" }
  10. 10. https://api.coursera.org/api/courses.v1?q=slug&slug=machine-learning
 &fields=instructorIds&includes=instructorIds
 response: { "elements": [ { "courseType": "v2.ondemand", "id": "Gtv4Xb1-EeS-ViIACwYKVQ", "name": "Machine Learning", "slug": "machine-learning", ”instructorIds": [1244] } ], "linked": { "instructors.v1": [ { "id": 1244, "name": "Andrew Ng" } ] }, "paging": { "total": 1 } } request endpoint: /api/courses.v1 request query parameters: { "q": "slug", "slug": "machine-learning", "fields": "instructorIds", "includes": "instructorIds" }
  11. 11. https://api.coursera.org/api/courses.v1?q=slug&slug=machine-learning
 &fields=instructorIds,instructors.v1(title)&includes=instructorIds
 response: { "elements": [ { "courseType": "v2.ondemand", "id": "Gtv4Xb1-EeS-ViIACwYKVQ", "name": "Machine Learning", "slug": "machine-learning", "instructorIds": [1244] } ], "linked": { "instructors.v1": [ { "id": 1244, "name": "Andrew Ng", "title": "Associate Professor, Stanford University; Chief Scientist, Baidu;
 Chairman and Co-founder, Coursera" } ] }, "paging": { "total": 1 } } request endpoint: /api/courses.v1 request query parameters: { "q": "slug", "slug": "machine-learning", "fields": “instructorIds, instructors.v1(title)", "includes": "instructorIds" }
  12. 12. 0 200 400 600 800 Controllers vs Naptime Resources Controllers Resources
  13. 13. Naptime Key Learnings • Leverage type safety, carefully • Collections of Key-Value pairs • Opinionated framework improves communication Principle:
 Optimize for developer productivity.
  14. 14. context.executeAction(setCourseIdentifiers, {courseId, courseSlug}); context.executeAction(loadMembership); context.executeAction(getCurrentSession, {courseSlug}); context.executeAction(loadCourseSchedule, {courseId}); context.executeAction(initProfileStore, {authenticated, courseId, externalId, userId}); context.executeAction(loadCourseViewGrade, {userId, courseId}); context.executeAction(loadDomains); context.executeAction(loadUserGroupsForCourse, {courseId, userId}); context.executeAction(getReferencesList, {courseId}); context.executeAction(loadHonorsUserPreferences, {authenticated}); context.executeAction(loadCertificateData, {courseId, userId}); context.executeAction(loadVerificationDisplay, {authenticated, userId, course, s12n}); context.executeAction(getHomeProgress, {authenticated, courseId}); context.executeAction(getProgress, {authenticated, courseId, userId});
  15. 15. Imperative Data Fetching Declarative Data Fetching api.loadCourses().then(courses => { const courseIds = courses.map(c => c.id); api.loadCourseMemberships(courseIds) .then(courseMemberships => { this.setState({ courses, courseMemberships }); }); }); render() { if (this.state.courses && this.state.courseMemberships) { return <div>{courses}</div>; } } const Component = ({courses, memberships}) => { return <div>{courses}</div> } Naptime.withData(Component, ({courseId}) => { courses: CoursesV1.getAll(), memberships: MembershipV1.byCourse(courseId) });
  16. 16. NaptimeStore: { "courses.v1": { "69Bku0KoEeWZtA4u62x6lQ": {…}, "0HiU7Oe4EeWTAQ4yevf_oQ": {…}, "5zjIsJq-EeW_wArffOXkOw": {…} }, "instructors.v1": { "v9CQdBkhEeWjrA6seF25aw": {…}, "QgmoVdT2EeSlhSIACx2EBw": {…} } } Global ID:
 "courses.v1/69Bku0KoEeWZtA4u62x6lQ"
  17. 17. Problems remained
 • There are always going to be edge cases • Feature prioritization requires careful balance • Don’t underestimate the power of Googleability
  18. 18. GraphQL Query: query { CoursesV1Resource { slug(slug: "machine-learning") { id } } } request endpoint: /api/courses.v1 request query parameters: { "q": "slug", "slug": "machine-learning" }
  19. 19. request endpoint: /api/courses.v1 request query parameters: { "q": "slug", "slug": "machine-learning", "fields": "primaryLanguages" } GraphQL Query: query { CoursesV1Resource { slug(slug: "machine-learning") { id primaryLanguages } } }
  20. 20. request endpoint: /api/courses.v1 request query parameters: { "q": "slug", "slug": "machine-learning", "fields": "instructorIds", "includes": "instructorIds" } GraphQL Query: query { CoursesV1Resource { slug(slug: "machine-learning") { id instructors: instructorIds { id } } } }
  21. 21. request endpoint: /api/courses.v1 request query parameters: { "q": "slug", "slug": "machine-learning", "fields": "instructorIds,
 instructors.v1(title)", "includes": "instructorIds" } GraphQL Query: query { CoursesV1Resource { slug(slug: "machine-learning") { id instructors: instructorIds { id title } } } }
  22. 22. Edge Tier GraphQL Assembler Profile Service Enrollments Service Catalog Service
  23. 23. Edge Tier GraphQL Assembler Profile Service Enrollments Service Catalog Service
  24. 24. Key Lessons Learned Carefully understand your problem Look to theory: stand on the shoulders of giants Plug into the ecosystem
  25. 25. Naptime is developed in the open https://github.com/coursera/naptime
  26. 26. Thank you!
  27. 27. Thank you! Bryan Kane ! @bryanskane " bryan-coursera

×