SlideShare a Scribd company logo
MAX

Realtime messaging and

activity stream engine
Carles Bruguera (@sunbit)

Víctor Fernández de Alba (@sneridagh)
Víctor
● Senior Python Developer and IT architect

● Plone Foundation member

● Plone core developer since 2010

● Author of Plone 3 intranets book (2010, PacktPub)
@sneridagh
Carles
● Python and JavaScript lover
● Working with python for the last 8 years
● Occasional Erlang coder (when on drugs)
● Regex freak
@sunbit
Python @UPCnet and @BarcelonaTech
DEMO!
History
● First commit on August, 2011
● Initially designed as the key feature for the Universitat
Politècnica de Catalunya (BarcelonaTech) university
concept of social intranet
● Today, MAX is used by more than 30.000 students and
8.000 university staff integrated in the online campus
and the institutional collaboration tools
What is MAX?
● RESTful API

● 88 (and growing) endpoints

● Multi-source user and application activity stream 

● Asynchronous messaging and conversations
● GPL Licensed
Old styled forums
Forum Topic Post Post Post
What is a context?
Context (unique URI)
Forum Topic Post
Posts
Subscriptions
Post Post
Contexts
● Identified by unique URIs

● Permissions per context

o read

o write

o subscribe

o unsubscribe

● Multiple context types based on permissions variations

● Granular permissions per user

o Overriding the default ones defined by the context

o Grant / Revoke
o invite

o kick

o delete

o flag
Real life examples
Communities site
Alumni
Sell your stuff
Institutional events
Institutional news
Online campus
Compilers
Faculty news
Applied maths III
Signal theory
Real life examples (II)
Community types
Open Closed Institutional
Everyone can
join and leave
at will
The owner
should invite me
to join and I can
leave at will
The site admin
subscribes
people, no one
can leave
Features
Activity Stream
● Stores activity from users and applications
● Usual social actions

○ Comments

○ Likes

○ Favorites

● Images and files support
Features
Conversations
● Realtime conversations and private messaging
● One to one

● Groups
● Images and files support
Features
JS
Javascript
UI widget
Notifications
● Platform specific push notifications





● Internal notifications

○ Double check

○ others
Features
Features
External sources aggregation
Features
Fully deployable on premises
● Addresses any security concerns

● Absolute customer data privacy
and ownership
● “Corporate whatsapp”
Features Summary
JS
Components overview
iOs App
Plone
Moodle
android App
REST Api
“MAX”
OAuth Server
“Osiris”
Messaging
“Maxbunny”
NGINX
max.ui.js
RabbitMQ MongoDB
LDAP
Sync services
“Hub”
Twitter listener
“MaxTweety”
Osiris
● Minimal OAuth2 server implementation
● Build on top of pyramid
● Resource Owner Credentials Flow
● Tokens stored on MongoDB
● /token endpoint to generate token for a user
● /checktoken endpoint to verify a token
● Base LDAP user storage implementation
● Pluggable repoze.who based alternative user
storage implementations
NGINX
Pyramid + gevent
MongoDB
WSGI (Chausette)
MAX
● REST(ful) api
● Also build on top of pyramid
● Hybrid URL-dispatch + traversal routing
● ACL policy with fine-grained permissions per
endpoint
● Customized venusian decorator to configure
endpoints
● Tweens used for several tasks
● Per-exception catching to provide detailed JSON
error messages
● Per-request caching of variables
NGINX
Pyramid + Gevent
MongoDB
WSGI (Chausette)
RabbitMQ
MAX (Routing)
● Route definition
RESOURCES['avatar'] = dict(route='/people/{username}/
avatar', filesystem=True, category='User', name='User
avatar', traverse='/people/{username}')
● Endpoint definition
@endpoint(route_name='avatar', request_method='POST',
permission=modify_avatar)
def postUserAvatar(user, request):
"""
Upload user avatar
"""
MAX (Tweens)
● exception catcher
● post tunneling
● compatibility check
def compatibility_checker_factory(handler, registry):
def compatibility_checker_tween(request):
requested_compat_id = request.headers.get('X-Max-Compat-ID', None)
if requested_compat_id is None:
response = handler(request)
return response
expected_compat_id = str(request.registry.settings.get('max.compat_id'))
if expected_compat_id == requested_compat_id:
response = handler(request)
return response
else:
return JSONHTTPPreconditionFailed(
error=dict(
objectType='error',
error="CompatibilityIDMismatch",
error_description='X-Max-Compat-ID header value mismatch, {} was
expected'.format(expected_compat_id)))
return compatibility_checker_tween
MAX (Exception handling)
● Known error use cases are raised as custom
exceptions:
raise ObjectNotFound("User {} doesn't have role {}".format(user, role))
● And rendered as a JSON message
@view_config(context=ObjectNotFound)
def object_not_found(exc, request):
return JSONHTTPNotFound(error=dict(objectType='error',
error=ObjectNotFound.__name__, error_description=exc.message))
● Non-handled exceptions are logged with request
information
Max euro python 2015
RabbitMQ & messaging
● Exchange-to-exchange routing
● STOMP over WS using rabbitmq plugins
● “Public” end-user stomp endpoints
● Message delivery and security through
routing key bindings
● Oauth authentication via erlang plugin
● Easy plug-in of temp queues for debugging
NGINX
Queues & exchanges
RabbitMQ
Websockets
STOMP AMQP
Oauth Authentication
Oauth2
activity
type=topic
conversations
type=topic
userid.subscribe
type=fanout
userid.publish
type=direct
...
Mobile
Apps
Other
clients
pushmessages
dynamic
queue
dynamic
queue
MAX
Messaging Design
internal
id.*
id.*
*.messages
*.notifi
cations
id
MaxCarrot
{"uuid": "005fab55bee84",
"user": {
"username": "johndoe",
"displayname" : "John Doe"
},
"action": "add",
"object": "message",
"data": {
"text": "Hello world!"
},
"source": "ios",
"domain": "demo",
"version": "4.0.1",
"published": "2015-07-21"}
MaxCarrot
● JSON based message format
● Used on messages routed through RabbitMQ
● Packed and unpacked versions
● Metadata/debugging fields
● Purpose related fields
● Encapsulates messaging logic
MaxCarrot
(Rules)
● Map field combinations to actions
● Pack messages following spec
● Ignore any message not matching any mapping
"source": {
"id": "s",
"type": "char",
"values": {
"ios": { "id”: "c" },
(...)
"max": { "id”: "m" }
}
"version": {
"id": "v",
"type": "string",
}
MaxCarrot
(human-readable)
{"uuid": "005fab55bee84",
"user": {
"username": "johndoe",
"displayname" : "John Doe"
},
"action": "add",
"object": "message",
"data": {
"text": "Hello world!"
},
"source": "ios",
"domain": "demo",
"version": "4.0.1",
"published": "2015-07-21"}
MaxCarrot
(nerd-readable)
{‘a’:'a','d':
{'text':'Helloworld
!'},'g':'005fab55be
e84','i':'demo','o'
:'m','p':'2015-07-2
1','s':'i','u':
{'u':'johndoe','d':
'JohnDoe'},'v':'4.0
.1'}
MaxBunny
● Pluggable multiprocess domain-aware
queue consumer
● A multiprocess runner runs N process for
each consumer defined.
● Each consumer binds to a queue and
consumes messages
● Runner provides a shared pool of WSGI
MaxClient instances, one for each
domain.MongoDB
RabbitMQ
MAX
MaxBunny Runner
& Consumers
WSGI MaxClient
MaxClient
● Opinionated Wrapper for REST api’s
● Wraps endpoint resources based on endpoint list definition.
RESOURCES[‘activity’] = dict(route=’/people/{username}/activities’)
● Accesses endpoints in a pythonic way
>>> client.people[‘username’].activities.get(qs={‘limit’:2})
● Creates json bodies from “nested” kwargs (with optional
sensible defaults)
>>> client.activities.post(object_content=’Hello’)
{
“object”: {
“objectType”: “note”,
“content”: “Hello”
}}
MaxClient
● Raises a custom RequestError exception on 5xx and
4xx responses
● Returns None on 404 responses
● Returns parsed JSON body on success responses
WSGI MaxClient
● WSGI version
● Subclassed MaxClient that makes calls to a “fake” wsgi
server
● Actual MAX Codebase is run by the client
● Requests don’t stress main api servers, only database
● Limitations:
o User must have privileges on “real” max server
o Computer from where client is run must have access to
storage backed
Twitter external aggregation
● Backend process listens twitter streaming service
● Selected tweets are queued and processed
● Valid tweets are injected into max activity stream
● Max users linked with twitter usernames
● Aggregation of content as a context
Current integrations
UPCnet uLearn Communities
UPCnet uLearn Campus
iOS & Android apps
Max euro python 2015
Max euro python 2015
Max euro python 2015
Max euro python 2015
Potential integrations
<place your web|app|whatever thingy name here>
<place the screenshots here>
Whishlist
● Social interactions (Follow/share)

● Finish & polish documentation

● Microservices / Dockerization

● Redis backed cache

● RabbitMQ SSL without NGINX

● Python3 / asyncio

● Explore JSON-LD (HATEOAS)

● Encryption
Community building?
Absolutely!

Let’s do it!
Contact us, PR are welcome!
Resources
https://upcnet.github.io/max

https://github.com/UPCnet/max

https://github.com/UPCnet/maxserver
Thanks / Gràcies
@sunbit

@sneridagh

More Related Content

PPTX
MongoDB + Java + Spring Data
PPTX
Morphia, Spring Data & Co.
PDF
Ajax chap 5
PDF
Java Persistence Frameworks for MongoDB
PDF
Ajax chap 4
KEY
Practical Use of MongoDB for Node.js
PPTX
User Data Management with MongoDB
PPT
Synapse india dotnet development web approch part 2
MongoDB + Java + Spring Data
Morphia, Spring Data & Co.
Ajax chap 5
Java Persistence Frameworks for MongoDB
Ajax chap 4
Practical Use of MongoDB for Node.js
User Data Management with MongoDB
Synapse india dotnet development web approch part 2

What's hot (19)

PDF
MongoDB SoCal 2020: Best Practices for Working with IoT and Time-series Data
KEY
Introduction to Restkit
PPTX
[MongoDB.local Bengaluru 2018] Just in Time Validation with JSON Schema
PDF
Mongoose: MongoDB object modelling for Node.js
PPTX
Conceptos básicos. Seminario web 4: Indexación avanzada, índices de texto y g...
PPT
Mongo db tutorials
PPTX
Data Management 3: Bulletproof Data Management
PPTX
Data Management 2: Conquering Data Proliferation
PDF
Learn Learn how to build your mobile back-end with MongoDB
ODP
Consume Spring Data Rest with Angularjs
PPTX
Mongoose and MongoDB 101
PDF
Nk API - examples
PPTX
Introduction to JSON & AJAX
KEY
RESTfull with RestKit
PDF
Webinar: Developing with the modern App Stack: MEAN and MERN (with Angular2 a...
PPTX
MongoDB + Java - Everything you need to know
PDF
Joker'15 Java straitjackets for MongoDB
PPTX
Webinar: Back to Basics: Thinking in Documents
PPTX
Conceptos básicos. Seminario web 5: Introducción a Aggregation Framework
MongoDB SoCal 2020: Best Practices for Working with IoT and Time-series Data
Introduction to Restkit
[MongoDB.local Bengaluru 2018] Just in Time Validation with JSON Schema
Mongoose: MongoDB object modelling for Node.js
Conceptos básicos. Seminario web 4: Indexación avanzada, índices de texto y g...
Mongo db tutorials
Data Management 3: Bulletproof Data Management
Data Management 2: Conquering Data Proliferation
Learn Learn how to build your mobile back-end with MongoDB
Consume Spring Data Rest with Angularjs
Mongoose and MongoDB 101
Nk API - examples
Introduction to JSON & AJAX
RESTfull with RestKit
Webinar: Developing with the modern App Stack: MEAN and MERN (with Angular2 a...
MongoDB + Java - Everything you need to know
Joker'15 Java straitjackets for MongoDB
Webinar: Back to Basics: Thinking in Documents
Conceptos básicos. Seminario web 5: Introducción a Aggregation Framework
Ad

Viewers also liked (7)

PDF
June 2014 - Building Rabbit MQ based chat on Android
PPTX
분석과 설계
PDF
RabbitMQ Data Ingestion
PDF
Dissecting the rabbit: RabbitMQ Internal Architecture
PDF
2015 스타트업 투자동향보고서_platum
PDF
Unit of Value: A Framework for Scaling
June 2014 - Building Rabbit MQ based chat on Android
분석과 설계
RabbitMQ Data Ingestion
Dissecting the rabbit: RabbitMQ Internal Architecture
2015 스타트업 투자동향보고서_platum
Unit of Value: A Framework for Scaling
Ad

Similar to Max euro python 2015 (20)

PDF
XFLTReaT: A New Dimension in Tunnelling (HITB GSEC 2017)
PDF
XFLTReaT: A New Dimension in Tunneling (Shakacon 2017)
PDF
WebCamp Ukraine 2016: Instant messenger with Python. Back-end development
PDF
XFLTReaT: a new dimension in tunnelling (BruCON 0x09 2017)
PDF
WebCamp 2016: Python. Вячеслав Каковский: Real-time мессенджер на Python. Осо...
PDF
Website Monitoring with Distributed Messages/Tasks Processing (AMQP & RabbitM...
PDF
XFLTReaT: A New Dimension In Tunnelling (DeepSec 2017)
PDF
Trick or XFLTReaT a.k.a. Tunnel All The Things
PDF
Python RESTful webservices with Python: Flask and Django solutions
PDF
Balázs Bucsay - XFLTReaT: Building a Tunnel
PDF
XFLTReat: a new dimension in tunnelling
PDF
MAX: Realtime messaging and activity stream engine
PPTX
Spark Kernel Talk - Apache Spark Meetup San Francisco (July 2015)
PDF
Asynchronous Architectures for Implementing Scalable Cloud Services - Evan Co...
PDF
Django at Scale
ODP
Introduction to Python Celery
PDF
Queue Everything and Please Everyone
PDF
Project Proposal: Internet of Things uxing XMPP
PDF
Celery: The Distributed Task Queue
PDF
Life in a Queue - Using Message Queue with django
XFLTReaT: A New Dimension in Tunnelling (HITB GSEC 2017)
XFLTReaT: A New Dimension in Tunneling (Shakacon 2017)
WebCamp Ukraine 2016: Instant messenger with Python. Back-end development
XFLTReaT: a new dimension in tunnelling (BruCON 0x09 2017)
WebCamp 2016: Python. Вячеслав Каковский: Real-time мессенджер на Python. Осо...
Website Monitoring with Distributed Messages/Tasks Processing (AMQP & RabbitM...
XFLTReaT: A New Dimension In Tunnelling (DeepSec 2017)
Trick or XFLTReaT a.k.a. Tunnel All The Things
Python RESTful webservices with Python: Flask and Django solutions
Balázs Bucsay - XFLTReaT: Building a Tunnel
XFLTReat: a new dimension in tunnelling
MAX: Realtime messaging and activity stream engine
Spark Kernel Talk - Apache Spark Meetup San Francisco (July 2015)
Asynchronous Architectures for Implementing Scalable Cloud Services - Evan Co...
Django at Scale
Introduction to Python Celery
Queue Everything and Please Everyone
Project Proposal: Internet of Things uxing XMPP
Celery: The Distributed Task Queue
Life in a Queue - Using Message Queue with django

Recently uploaded (20)

PDF
Wondershare Filmora 15 Crack With Activation Key [2025
PDF
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
PPTX
L1 - Introduction to python Backend.pptx
PDF
Upgrade and Innovation Strategies for SAP ERP Customers
PPTX
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
PDF
Nekopoi APK 2025 free lastest update
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 41
PPTX
Transform Your Business with a Software ERP System
PPTX
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
PDF
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
PDF
medical staffing services at VALiNTRY
PPTX
assetexplorer- product-overview - presentation
PPTX
history of c programming in notes for students .pptx
PDF
Design an Analysis of Algorithms II-SECS-1021-03
PDF
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
PDF
Digital Strategies for Manufacturing Companies
PPTX
ai tools demonstartion for schools and inter college
PDF
Digital Systems & Binary Numbers (comprehensive )
PPTX
Operating system designcfffgfgggggggvggggggggg
PDF
How to Migrate SBCGlobal Email to Yahoo Easily
Wondershare Filmora 15 Crack With Activation Key [2025
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
L1 - Introduction to python Backend.pptx
Upgrade and Innovation Strategies for SAP ERP Customers
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
Nekopoi APK 2025 free lastest update
Internet Downloader Manager (IDM) Crack 6.42 Build 41
Transform Your Business with a Software ERP System
Lecture 3: Operating Systems Introduction to Computer Hardware Systems
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
medical staffing services at VALiNTRY
assetexplorer- product-overview - presentation
history of c programming in notes for students .pptx
Design an Analysis of Algorithms II-SECS-1021-03
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
Digital Strategies for Manufacturing Companies
ai tools demonstartion for schools and inter college
Digital Systems & Binary Numbers (comprehensive )
Operating system designcfffgfgggggggvggggggggg
How to Migrate SBCGlobal Email to Yahoo Easily

Max euro python 2015

  • 1. MAX Realtime messaging and activity stream engine Carles Bruguera (@sunbit) Víctor Fernández de Alba (@sneridagh)
  • 2. Víctor ● Senior Python Developer and IT architect ● Plone Foundation member ● Plone core developer since 2010 ● Author of Plone 3 intranets book (2010, PacktPub) @sneridagh
  • 3. Carles ● Python and JavaScript lover ● Working with python for the last 8 years ● Occasional Erlang coder (when on drugs) ● Regex freak @sunbit
  • 4. Python @UPCnet and @BarcelonaTech
  • 6. History ● First commit on August, 2011 ● Initially designed as the key feature for the Universitat Politècnica de Catalunya (BarcelonaTech) university concept of social intranet ● Today, MAX is used by more than 30.000 students and 8.000 university staff integrated in the online campus and the institutional collaboration tools
  • 7. What is MAX? ● RESTful API ● 88 (and growing) endpoints ● Multi-source user and application activity stream ● Asynchronous messaging and conversations ● GPL Licensed
  • 8. Old styled forums Forum Topic Post Post Post
  • 9. What is a context? Context (unique URI) Forum Topic Post Posts Subscriptions Post Post
  • 10. Contexts ● Identified by unique URIs ● Permissions per context o read o write o subscribe o unsubscribe ● Multiple context types based on permissions variations ● Granular permissions per user o Overriding the default ones defined by the context o Grant / Revoke o invite o kick o delete o flag
  • 11. Real life examples Communities site Alumni Sell your stuff Institutional events Institutional news Online campus Compilers Faculty news Applied maths III Signal theory
  • 12. Real life examples (II) Community types Open Closed Institutional Everyone can join and leave at will The owner should invite me to join and I can leave at will The site admin subscribes people, no one can leave
  • 13. Features Activity Stream ● Stores activity from users and applications ● Usual social actions ○ Comments ○ Likes ○ Favorites ● Images and files support
  • 14. Features Conversations ● Realtime conversations and private messaging ● One to one ● Groups ● Images and files support
  • 16. Notifications ● Platform specific push notifications
 
 
 ● Internal notifications ○ Double check ○ others Features
  • 18. Features Fully deployable on premises ● Addresses any security concerns ● Absolute customer data privacy and ownership ● “Corporate whatsapp”
  • 20. Components overview iOs App Plone Moodle android App REST Api “MAX” OAuth Server “Osiris” Messaging “Maxbunny” NGINX max.ui.js RabbitMQ MongoDB LDAP Sync services “Hub” Twitter listener “MaxTweety”
  • 21. Osiris ● Minimal OAuth2 server implementation ● Build on top of pyramid ● Resource Owner Credentials Flow ● Tokens stored on MongoDB ● /token endpoint to generate token for a user ● /checktoken endpoint to verify a token ● Base LDAP user storage implementation ● Pluggable repoze.who based alternative user storage implementations NGINX Pyramid + gevent MongoDB WSGI (Chausette)
  • 22. MAX ● REST(ful) api ● Also build on top of pyramid ● Hybrid URL-dispatch + traversal routing ● ACL policy with fine-grained permissions per endpoint ● Customized venusian decorator to configure endpoints ● Tweens used for several tasks ● Per-exception catching to provide detailed JSON error messages ● Per-request caching of variables NGINX Pyramid + Gevent MongoDB WSGI (Chausette) RabbitMQ
  • 23. MAX (Routing) ● Route definition RESOURCES['avatar'] = dict(route='/people/{username}/ avatar', filesystem=True, category='User', name='User avatar', traverse='/people/{username}') ● Endpoint definition @endpoint(route_name='avatar', request_method='POST', permission=modify_avatar) def postUserAvatar(user, request): """ Upload user avatar """
  • 24. MAX (Tweens) ● exception catcher ● post tunneling ● compatibility check def compatibility_checker_factory(handler, registry): def compatibility_checker_tween(request): requested_compat_id = request.headers.get('X-Max-Compat-ID', None) if requested_compat_id is None: response = handler(request) return response expected_compat_id = str(request.registry.settings.get('max.compat_id')) if expected_compat_id == requested_compat_id: response = handler(request) return response else: return JSONHTTPPreconditionFailed( error=dict( objectType='error', error="CompatibilityIDMismatch", error_description='X-Max-Compat-ID header value mismatch, {} was expected'.format(expected_compat_id))) return compatibility_checker_tween
  • 25. MAX (Exception handling) ● Known error use cases are raised as custom exceptions: raise ObjectNotFound("User {} doesn't have role {}".format(user, role)) ● And rendered as a JSON message @view_config(context=ObjectNotFound) def object_not_found(exc, request): return JSONHTTPNotFound(error=dict(objectType='error', error=ObjectNotFound.__name__, error_description=exc.message)) ● Non-handled exceptions are logged with request information
  • 27. RabbitMQ & messaging ● Exchange-to-exchange routing ● STOMP over WS using rabbitmq plugins ● “Public” end-user stomp endpoints ● Message delivery and security through routing key bindings ● Oauth authentication via erlang plugin ● Easy plug-in of temp queues for debugging NGINX Queues & exchanges RabbitMQ Websockets STOMP AMQP Oauth Authentication Oauth2
  • 29. MaxCarrot {"uuid": "005fab55bee84", "user": { "username": "johndoe", "displayname" : "John Doe" }, "action": "add", "object": "message", "data": { "text": "Hello world!" }, "source": "ios", "domain": "demo", "version": "4.0.1", "published": "2015-07-21"}
  • 30. MaxCarrot ● JSON based message format ● Used on messages routed through RabbitMQ ● Packed and unpacked versions ● Metadata/debugging fields ● Purpose related fields ● Encapsulates messaging logic
  • 31. MaxCarrot (Rules) ● Map field combinations to actions ● Pack messages following spec ● Ignore any message not matching any mapping "source": { "id": "s", "type": "char", "values": { "ios": { "id”: "c" }, (...) "max": { "id”: "m" } } "version": { "id": "v", "type": "string", }
  • 32. MaxCarrot (human-readable) {"uuid": "005fab55bee84", "user": { "username": "johndoe", "displayname" : "John Doe" }, "action": "add", "object": "message", "data": { "text": "Hello world!" }, "source": "ios", "domain": "demo", "version": "4.0.1", "published": "2015-07-21"}
  • 34. MaxBunny ● Pluggable multiprocess domain-aware queue consumer ● A multiprocess runner runs N process for each consumer defined. ● Each consumer binds to a queue and consumes messages ● Runner provides a shared pool of WSGI MaxClient instances, one for each domain.MongoDB RabbitMQ MAX MaxBunny Runner & Consumers WSGI MaxClient
  • 35. MaxClient ● Opinionated Wrapper for REST api’s ● Wraps endpoint resources based on endpoint list definition. RESOURCES[‘activity’] = dict(route=’/people/{username}/activities’) ● Accesses endpoints in a pythonic way >>> client.people[‘username’].activities.get(qs={‘limit’:2}) ● Creates json bodies from “nested” kwargs (with optional sensible defaults) >>> client.activities.post(object_content=’Hello’) { “object”: { “objectType”: “note”, “content”: “Hello” }}
  • 36. MaxClient ● Raises a custom RequestError exception on 5xx and 4xx responses ● Returns None on 404 responses ● Returns parsed JSON body on success responses
  • 37. WSGI MaxClient ● WSGI version ● Subclassed MaxClient that makes calls to a “fake” wsgi server ● Actual MAX Codebase is run by the client ● Requests don’t stress main api servers, only database ● Limitations: o User must have privileges on “real” max server o Computer from where client is run must have access to storage backed
  • 38. Twitter external aggregation ● Backend process listens twitter streaming service ● Selected tweets are queued and processed ● Valid tweets are injected into max activity stream ● Max users linked with twitter usernames ● Aggregation of content as a context
  • 39. Current integrations UPCnet uLearn Communities UPCnet uLearn Campus iOS & Android apps
  • 44. Potential integrations <place your web|app|whatever thingy name here> <place the screenshots here>
  • 45. Whishlist ● Social interactions (Follow/share) ● Finish & polish documentation ● Microservices / Dockerization ● Redis backed cache ● RabbitMQ SSL without NGINX ● Python3 / asyncio ● Explore JSON-LD (HATEOAS) ● Encryption
  • 46. Community building? Absolutely! Let’s do it! Contact us, PR are welcome!