Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Multi-tenancy with Rails

Multi-tenancy with Rails

Dimiter Petrov

September 14, 2016
Tweet

More Decks by Dimiter Petrov

Other Decks in Programming

Transcript

  1. Multi-tenancy with Rails
    Dimiter Petrov

    View Slide

  2. What is multi-tenancy?
    A software architecture where a single instance of a software application
    serves multiple customers.
    A customer is called a tenant in this architecture.

    View Slide

  3. Advantages/problems/compromises

    View Slide

  4. Advantages/problems/compromises
    Deploy once to update everyone's software,

    View Slide

  5. Advantages/problems/compromises
    Deploy once to update everyone's software, but
    there is single point of failure for all tenants.

    View Slide

  6. Advantages/problems/compromises
    Deploy once to update everyone's software, but
    there is single point of failure for all tenants.
    Shared development and maintenance costs,

    View Slide

  7. Advantages/problems/compromises
    Deploy once to update everyone's software, but
    there is single point of failure for all tenants.
    Shared development and maintenance costs, but
    customer-specific features are burdensome.

    View Slide

  8. Advantages/problems/compromises
    Deploy once to update everyone's software, but
    there is single point of failure for all tenants.
    Shared development and maintenance costs, but
    customer-specific features are burdensome.
    Single codebase,

    View Slide

  9. Advantages/problems/compromises
    Deploy once to update everyone's software, but
    there is single point of failure for all tenants.
    Shared development and maintenance costs, but
    customer-specific features are burdensome.
    Single codebase, but
    with configuration overhead.

    View Slide

  10. Advantages/problems/compromises
    Deploy once to update everyone's software, but
    there is single point of failure for all tenants.
    Shared development and maintenance costs, but
    customer-specific features are burdensome.
    Single codebase, but
    with configuration overhead.
    However, after configuration, development is the same as for a classic, single-
    tenant application.

    View Slide

  11. Requirements
    Data access control
    Custom features
    Custom branding

    View Slide

  12. Data separation

    View Slide

  13. Data separation strategies
    Application-level: in the controller and sometimes the model
    Database-level: different databases or different PostgreSQL schemas

    View Slide

  14. PostgreSQL schemas
    From the docs:
    A database contains one or more named schemas, which in turn
    contain tables. Schemas also contain other kinds of named objects,
    including data types, functions, and operators. The same object name
    can be used in different schemas without conflict
    http://www.postgresql.org/docs/9.5/static/ddl-schemas.html
    There is a default p
    u
    b
    l
    i
    c schema, but you can create your own.

    View Slide

  15. Schema example
    # c
    r
    e
    a
    t
    e s
    c
    h
    e
    m
    a m
    y
    s
    c
    h
    e
    m
    a
    ;
    # c
    r
    e
    a
    t
    e t
    a
    b
    l
    e m
    y
    s
    c
    h
    e
    m
    a
    .
    t
    h
    i
    n
    g
    s
    (
    i
    d s
    e
    r
    i
    a
    l
    )
    ;

    View Slide

  16. Schema search path
    Used to automatically infer which table is meant without specifying it
    explicitly.
    # s
    h
    o
    w s
    e
    a
    r
    c
    h
    _
    p
    a
    t
    h
    ;
    s
    e
    a
    r
    c
    h
    _
    p
    a
    t
    h
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    "
    $
    u
    s
    e
    r
    "
    , p
    u
    b
    l
    i
    c
    # s
    e
    t s
    e
    a
    r
    c
    h
    _
    p
    a
    t
    h t
    o m
    y
    s
    c
    h
    e
    m
    a
    ,
    p
    u
    b
    l
    i
    c
    ;
    # s
    h
    o
    w s
    e
    a
    r
    c
    h
    _
    p
    a
    t
    h
    ;
    s
    e
    a
    r
    c
    h
    _
    p
    a
    t
    h
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    m
    y
    s
    c
    h
    e
    m
    a
    , p
    u
    b
    l
    i
    c

    View Slide

  17. Schemas for data separation
    1. Create one schema per tenant
    2. Create all tables in all schemas
    3. Detect tenant on every request and change the schema search path

    View Slide

  18. Gems
    a
    p
    a
    r
    t
    m
    e
    n
    t
    Multitenancy for Rails and ActiveRecord
    a
    p
    a
    r
    t
    m
    e
    n
    t
    -
    s
    i
    d
    e
    k
    i
    q
    Support for Sidekiq with the a
    p
    a
    r
    t
    m
    e
    n
    t gem

    View Slide

  19. Migrations
    Handled by a
    p
    a
    r
    t
    m
    e
    n
    t which runs the migration for each tenant.

    View Slide

  20. Seeds
    # s
    e
    e
    d
    s
    .
    r
    b
    r
    e
    q
    u
    i
    r
    e '
    a
    c
    t
    i
    v
    e
    _
    r
    e
    c
    o
    r
    d
    /
    f
    i
    x
    t
    u
    r
    e
    s
    '
    r
    e
    q
    u
    i
    r
    e R
    a
    i
    l
    s
    .
    r
    o
    o
    t
    .
    j
    o
    i
    n
    (
    '
    l
    i
    b
    /
    f
    i
    x
    t
    u
    r
    e
    _
    l
    o
    a
    d
    e
    r
    '
    )
    f
    i
    x
    t
    u
    r
    e
    s
    _
    d
    i
    r
    e
    c
    t
    o
    r
    y =
    R
    a
    i
    l
    s
    .
    r
    o
    o
    t
    .
    j
    o
    i
    n
    (
    "
    d
    b
    /
    s
    e
    e
    d
    s
    /
    #
    {
    A
    p
    a
    r
    t
    m
    e
    n
    t
    :
    :
    T
    e
    n
    a
    n
    t
    .
    c
    u
    r
    r
    e
    n
    t
    }
    "
    )
    F
    i
    x
    t
    u
    r
    e
    L
    o
    a
    d
    e
    r
    :
    :
    l
    o
    a
    d
    _
    d
    i
    r
    e
    c
    t
    o
    r
    y
    (
    f
    i
    x
    t
    u
    r
    e
    s
    _
    d
    i
    r
    e
    c
    t
    o
    r
    y
    )
    # l
    i
    b
    /
    f
    i
    x
    t
    u
    r
    e
    _
    l
    o
    a
    d
    e
    r
    .
    r
    b
    c
    l
    a
    s
    s F
    i
    x
    t
    u
    r
    e
    L
    o
    a
    d
    e
    r
    d
    e
    f s
    e
    l
    f
    .
    l
    o
    a
    d
    _
    d
    i
    r
    e
    c
    t
    o
    r
    y
    (
    d
    i
    r
    e
    c
    t
    o
    r
    y
    )
    u
    n
    l
    e
    s
    s D
    i
    r
    .
    e
    x
    i
    s
    t
    ?
    (
    d
    i
    r
    e
    c
    t
    o
    r
    y
    )
    r
    a
    i
    s
    e A
    r
    g
    u
    m
    e
    n
    t
    E
    r
    r
    o
    r
    .
    n
    e
    w
    (
    "
    #
    {
    d
    i
    r
    e
    c
    t
    o
    r
    y
    } d
    o
    e
    s n
    o
    t e
    x
    i
    s
    t
    !
    "
    )
    e
    n
    d
    A
    c
    t
    i
    v
    e
    R
    e
    c
    o
    r
    d
    :
    :
    F
    i
    x
    t
    u
    r
    e
    S
    e
    t
    .
    r
    e
    s
    e
    t
    _
    c
    a
    c
    h
    e
    D
    i
    r
    .
    g
    l
    o
    b
    (
    d
    i
    r
    e
    c
    t
    o
    r
    y
    .
    j
    o
    i
    n
    (
    "
    *
    *
    /
    *
    "
    )
    )
    .
    e
    a
    c
    h d
    o |
    f
    i
    l
    e
    n
    a
    m
    e
    |
    f
    i
    x
    t
    u
    r
    e = P
    a
    t
    h
    n
    a
    m
    e
    .
    n
    e
    w
    (
    f
    i
    l
    e
    n
    a
    m
    e
    .
    c
    h
    o
    m
    p
    (
    '
    .
    y
    m
    l
    '
    )
    )
    .
    b
    a
    s
    e
    n
    a
    m
    e
    A
    c
    t
    i
    v
    e
    R
    e
    c
    o
    r
    d
    :
    :
    F
    i
    x
    t
    u
    r
    e
    S
    e
    t
    .
    c
    r
    e
    a
    t
    e
    _
    f
    i
    x
    t
    u
    r
    e
    s
    (
    d
    i
    r
    e
    c
    t
    o
    r
    y
    , f
    i
    x
    t
    u
    r
    e
    )
    e
    n
    d
    e
    n
    d
    e
    n
    d

    View Slide

  21. PostgreSQL shared extensions
    From the a
    p
    a
    r
    t
    m
    e
    n
    t gem documentation:
    When using extensions, keep in mind:
    Extensions can only be installed into one schema per database, so
    we will want to install it into a schema that is always available in
    the schema_search_path
    The schema and extension need to be created in the database
    before they are referenced in migrations, database.yml or
    apartment.
    There does not seem to be a way to create the schema and
    extension using standard rails migrations.
    Rails db:test:prepare deletes and recreates the database, so it
    needs to be easy for the extension schema to be recreated here.

    View Slide

  22. PostgreSQL shared extensions
    p
    s
    q
    l -
    U p
    o
    s
    t
    g
    r
    e
    s -
    c "
    C
    R
    E
    A
    T
    E D
    A
    T
    A
    B
    A
    S
    E t
    e
    m
    p
    l
    a
    t
    e
    _
    a
    p
    p
    ;
    p
    s
    q
    l -
    U p
    o
    s
    t
    g
    r
    e
    s -
    d t
    e
    m
    p
    l
    a
    t
    e
    _
    a
    p
    p -
    c \
    "
    C
    R
    E
    A
    T
    E S
    C
    H
    E
    M
    A I
    F N
    O
    T E
    X
    I
    S
    T
    S s
    h
    a
    r
    e
    d
    _
    e
    x
    t
    e
    n
    s
    i
    o
    n
    s
    ; \
    C
    R
    E
    A
    T
    E E
    X
    T
    E
    N
    S
    I
    O
    N I
    F N
    O
    T E
    X
    I
    S
    T
    S h
    s
    t
    o
    r
    e S
    C
    H
    E
    M
    A s
    h
    a
    r
    e
    d
    _
    e
    x
    t
    e
    n
    s
    i
    o
    n
    s
    ;
    "
    # d
    a
    t
    a
    b
    a
    s
    e
    .
    y
    m
    l
    d
    e
    f
    a
    u
    l
    t
    : &
    d
    e
    f
    a
    u
    l
    t
    a
    d
    a
    p
    t
    e
    r
    : p
    o
    s
    t
    g
    r
    e
    s
    q
    l
    e
    n
    c
    o
    d
    i
    n
    g
    : u
    n
    i
    c
    o
    d
    e
    t
    e
    m
    p
    l
    a
    t
    e
    : t
    e
    m
    p
    l
    a
    t
    e
    _
    a
    p
    p
    Also had to use s
    t
    r
    u
    c
    t
    u
    r
    e
    .
    s
    q
    l instead of s
    c
    h
    e
    m
    a
    .
    r
    b
    .

    View Slide

  23. Uploaded assets
    P
    a
    p
    e
    r
    c
    l
    i
    p
    :
    :
    A
    t
    t
    a
    c
    h
    m
    e
    n
    t
    .
    d
    e
    f
    a
    u
    l
    t
    _
    o
    p
    t
    i
    o
    n
    s
    [
    :
    u
    r
    l
    ] =
    "
    /
    :
    c
    l
    a
    s
    s
    /
    :
    t
    e
    n
    a
    n
    t
    /
    :
    a
    t
    t
    a
    c
    h
    m
    e
    n
    t
    /
    :
    i
    d
    /
    :
    s
    t
    y
    l
    e
    /
    :
    u
    p
    d
    a
    t
    e
    d
    _
    a
    t
    "
    P
    a
    p
    e
    r
    c
    l
    i
    p
    :
    :
    A
    t
    t
    a
    c
    h
    m
    e
    n
    t
    .
    d
    e
    f
    a
    u
    l
    t
    _
    o
    p
    t
    i
    o
    n
    s
    [
    :
    p
    a
    t
    h
    ] =
    R
    a
    i
    l
    s
    .
    r
    o
    o
    t
    .
    j
    o
    i
    n
    (
    '
    f
    i
    l
    e
    s
    '
    )
    .
    j
    o
    i
    n
    (
    "
    :
    c
    l
    a
    s
    s
    /
    :
    t
    e
    n
    a
    n
    t
    /
    :
    a
    t
    t
    a
    c
    h
    m
    e
    n
    t
    /
    :
    i
    d
    /
    :
    s
    t
    y
    l
    e
    /
    :
    u
    p
    d
    a
    t
    e
    d
    _
    a
    t
    "
    )
    .
    t
    o
    _
    s
    P
    a
    p
    e
    r
    c
    l
    i
    p
    .
    i
    n
    t
    e
    r
    p
    o
    l
    a
    t
    e
    s :
    t
    e
    n
    a
    n
    t d
    o |
    a
    t
    t
    a
    c
    h
    m
    e
    n
    t
    , s
    t
    y
    l
    e
    |
    A
    p
    a
    r
    t
    m
    e
    n
    t
    :
    :
    T
    e
    n
    a
    n
    t
    .
    c
    u
    r
    r
    e
    n
    t
    e
    n
    d
    # o
    t
    h
    e
    r i
    n
    t
    e
    r
    p
    o
    l
    a
    t
    i
    o
    n
    s
    .
    .
    .

    View Slide

  24. Business logic separation

    View Slide

  25. Feature gates
    A simple table with three columns: ID, feature name and a creation
    timestamp.
    c
    l
    a
    s
    s F
    e
    a
    t
    u
    r
    e < A
    c
    t
    i
    v
    e
    R
    e
    c
    o
    r
    d
    :
    :
    B
    a
    s
    e
    d
    e
    f s
    e
    l
    f
    .
    e
    n
    a
    b
    l
    e
    d
    ?
    (
    n
    a
    m
    e
    )
    w
    h
    e
    r
    e
    (
    n
    a
    m
    e
    : n
    a
    m
    e
    )
    .
    e
    x
    i
    s
    t
    s
    ?
    e
    n
    d
    e
    n
    d
    Remember: the contents of this table can be different for every tenant thanks
    to PosgreSQL schemas.

    View Slide

  26. Scheduled jobs
    d
    e
    f
    a
    u
    l
    t
    : &
    d
    e
    f
    a
    u
    l
    t
    c
    l
    a
    s
    s
    : '
    T
    a
    s
    k
    W
    o
    r
    k
    e
    r
    '
    q
    u
    e
    u
    e
    : '
    c
    r
    o
    n
    '
    r
    e
    t
    r
    i
    e
    s
    : 0
    s
    e
    n
    d
    _
    r
    e
    c
    a
    p
    _
    e
    m
    a
    i
    l
    s
    :
    <
    <
    : *
    d
    e
    f
    a
    u
    l
    t
    c
    r
    o
    n
    : "
    0 2 * * *
    " # 2
    :
    0
    0 e
    v
    e
    r
    y d
    a
    y
    a
    r
    g
    s
    : [
    '
    s
    e
    n
    d
    _
    r
    e
    c
    a
    p
    _
    e
    m
    a
    i
    l
    s
    '
    ]
    Results in something like
    w
    o
    r
    k
    e
    r = T
    a
    s
    k
    W
    o
    r
    k
    e
    r
    .
    n
    e
    w
    (
    o
    p
    t
    i
    o
    n
    s
    )
    w
    o
    r
    k
    e
    r
    .
    p
    e
    r
    f
    o
    r
    m
    (
    '
    s
    e
    n
    d
    _
    r
    e
    c
    a
    p
    _
    e
    m
    a
    i
    l
    s
    '
    )

    View Slide

  27. Scheduled jobs
    c
    l
    a
    s
    s T
    a
    s
    k
    W
    o
    r
    k
    e
    r
    i
    n
    c
    l
    u
    d
    e S
    i
    d
    e
    k
    i
    q
    :
    :
    W
    o
    r
    k
    e
    r
    s
    i
    d
    e
    k
    i
    q
    _
    o
    p
    t
    i
    o
    n
    s r
    e
    t
    r
    y
    : f
    a
    l
    s
    e
    d
    e
    f p
    e
    r
    f
    o
    r
    m
    (
    t
    a
    s
    k
    _
    n
    a
    m
    e
    )
    u
    n
    l
    e
    s
    s r
    e
    s
    p
    o
    n
    d
    _
    t
    o
    ?
    (
    t
    a
    s
    k
    _
    n
    a
    m
    e
    )
    r
    a
    i
    s
    e
    (
    A
    r
    g
    u
    m
    e
    n
    t
    E
    r
    r
    o
    r
    , "
    m
    i
    s
    s
    i
    n
    g t
    a
    s
    k #
    {
    t
    a
    s
    k
    _
    n
    a
    m
    e
    }
    "
    )
    e
    n
    d
    A
    p
    a
    r
    t
    m
    e
    n
    t
    .
    t
    e
    n
    a
    n
    t
    _
    n
    a
    m
    e
    s
    .
    e
    a
    c
    h d
    o |
    t
    e
    n
    a
    n
    t
    |
    A
    p
    a
    r
    t
    m
    e
    n
    t
    :
    :
    T
    e
    n
    a
    n
    t
    .
    s
    w
    i
    t
    c
    h
    (
    t
    e
    n
    a
    n
    t
    ) d
    o
    i
    f F
    e
    a
    t
    u
    r
    e
    .
    e
    n
    a
    b
    l
    e
    d
    ?
    (
    "
    t
    a
    s
    k
    :
    #
    {
    t
    a
    s
    k
    _
    n
    a
    m
    e
    }
    "
    )
    s
    e
    n
    d
    (
    t
    a
    s
    k
    _
    n
    a
    m
    e
    )
    e
    n
    d
    e
    n
    d
    e
    n
    d
    e
    n
    d
    d
    e
    f s
    e
    n
    d
    _
    r
    e
    c
    a
    p
    _
    e
    m
    a
    i
    l
    s
    ; e
    n
    d
    # .
    .
    .
    e
    n
    d

    View Slide

  28. Tenant con guration le
    A YAML file with configuration for all tenants (and optionally different
    environments for each tenant)
    t
    e
    n
    a
    n
    t
    1
    :
    <
    <
    : *
    d
    e
    f
    a
    u
    l
    t
    d
    o
    m
    a
    i
    n
    : e
    x
    a
    m
    p
    l
    e
    .
    c
    o
    m
    s
    m
    t
    p
    :
    d
    o
    m
    a
    i
    n
    : e
    x
    a
    m
    p
    l
    e
    .
    c
    o
    m
    Loaded in an initializer:
    r
    e
    q
    u
    i
    r
    e R
    a
    i
    l
    s
    .
    r
    o
    o
    t
    .
    j
    o
    i
    n
    (
    '
    l
    i
    b
    /
    c
    o
    n
    f
    i
    g
    '
    )
    R
    a
    i
    l
    s
    .
    a
    p
    p
    l
    i
    c
    a
    t
    i
    o
    n
    .
    c
    o
    n
    f
    i
    g
    .
    x
    .
    a
    p
    p = A
    p
    p
    :
    :
    C
    o
    n
    f
    i
    g
    .
    n
    e
    w

    View Slide

  29. Mailer con guration
    c
    l
    a
    s
    s A
    p
    p
    l
    i
    c
    a
    t
    i
    o
    n
    M
    a
    i
    l
    e
    r < A
    c
    t
    i
    o
    n
    M
    a
    i
    l
    e
    r
    :
    :
    B
    a
    s
    e
    d
    e
    f
    a
    u
    l
    t f
    r
    o
    m
    : -
    >
    (
    m
    a
    i
    l
    e
    r
    ) d
    o
    R
    a
    i
    l
    s
    .
    c
    o
    n
    f
    i
    g
    u
    r
    a
    t
    i
    o
    n
    .
    x
    .
    a
    p
    p
    .
    s
    e
    n
    d
    e
    r
    _
    e
    m
    a
    i
    l
    e
    n
    d
    l
    a
    y
    o
    u
    t '
    m
    a
    i
    l
    e
    r
    '
    d
    e
    f s
    e
    l
    f
    .
    s
    m
    t
    p
    _
    s
    e
    t
    t
    i
    n
    g
    s
    s
    u
    p
    e
    r
    .
    m
    e
    r
    g
    e
    (
    R
    a
    i
    l
    s
    .
    c
    o
    n
    f
    i
    g
    u
    r
    a
    t
    i
    o
    n
    .
    x
    .
    a
    p
    p
    .
    s
    m
    t
    p
    .
    s
    y
    m
    b
    o
    l
    i
    z
    e
    _
    k
    e
    y
    s
    )
    e
    n
    d
    d
    e
    f u
    r
    l
    _
    o
    p
    t
    i
    o
    n
    s
    s
    u
    p
    e
    r
    .
    m
    e
    r
    g
    e
    (
    h
    o
    s
    t
    : R
    a
    i
    l
    s
    .
    c
    o
    n
    f
    i
    g
    u
    r
    a
    t
    i
    o
    n
    .
    x
    .
    a
    p
    p
    .
    d
    o
    m
    a
    i
    n
    )
    e
    n
    d
    e
    n
    d

    View Slide

  30. c
    l
    a
    s
    s C
    o
    n
    f
    i
    g
    d
    e
    f m
    e
    t
    h
    o
    d
    _
    m
    i
    s
    s
    i
    n
    g
    (
    m
    e
    t
    h
    o
    d
    _
    n
    a
    m
    e
    , *
    a
    r
    g
    s
    , &
    b
    l
    o
    c
    k
    )
    g
    e
    t
    (
    m
    e
    t
    h
    o
    d
    _
    n
    a
    m
    e
    )
    e
    n
    d
    p
    r
    i
    v
    a
    t
    e
    d
    e
    f g
    e
    t
    (
    k
    e
    y
    , t
    e
    n
    a
    n
    t = n
    i
    l
    )
    c
    o
    n
    f
    i
    g =
    t
    e
    n
    a
    n
    t
    s
    _
    c
    o
    n
    f
    i
    g
    [
    t
    e
    n
    a
    n
    t |
    | A
    p
    a
    r
    t
    m
    e
    n
    t
    :
    :
    T
    e
    n
    a
    n
    t
    .
    c
    u
    r
    r
    e
    n
    t
    ] |
    | {
    }
    c
    o
    n
    f
    i
    g = c
    o
    n
    f
    i
    g
    .
    m
    e
    r
    g
    e
    (
    c
    o
    n
    f
    i
    g
    .
    f
    e
    t
    c
    h
    (
    R
    a
    i
    l
    s
    .
    e
    n
    v
    , {
    }
    )
    )
    c
    o
    n
    f
    i
    g
    .
    f
    e
    t
    c
    h
    (
    k
    e
    y
    .
    t
    o
    _
    s
    )
    r
    e
    s
    c
    u
    e K
    e
    y
    E
    r
    r
    o
    r
    r
    a
    i
    s
    e K
    e
    y
    E
    r
    r
    o
    r
    , e
    x
    c
    e
    p
    t
    i
    o
    n
    _
    m
    e
    s
    s
    a
    g
    e
    (
    k
    e
    y
    )
    e
    n
    d
    d
    e
    f t
    e
    n
    a
    n
    t
    s
    _
    c
    o
    n
    f
    i
    g
    @
    t
    e
    n
    a
    n
    t
    s
    _
    c
    o
    n
    f
    i
    g |
    |
    =
    Y
    A
    M
    L
    :
    :
    l
    o
    a
    d
    (
    E
    R
    B
    .
    n
    e
    w
    (
    R
    a
    i
    l
    s
    .
    r
    o
    o
    t
    .
    j
    o
    i
    n
    (
    "
    f
    o
    o
    .
    y
    m
    l
    "
    )
    .
    r
    e
    a
    d
    )
    .
    r
    e
    s
    u
    l
    t
    )
    e
    n
    d
    d
    e
    f e
    x
    c
    e
    p
    t
    i
    o
    n
    _
    m
    e
    s
    s
    a
    g
    e
    (
    k
    e
    y
    )
    # .
    .
    .
    e
    n
    d
    e
    n
    d

    View Slide

  31. Absolute URL helpers
    For use in the API
    m
    o
    d
    u
    l
    e U
    r
    l
    m
    o
    d
    u
    l
    e U
    s
    e
    r
    P
    i
    c
    t
    u
    r
    e
    d
    e
    f s
    e
    l
    f
    .
    p
    a
    t
    h
    (
    u
    s
    e
    r
    , s
    t
    y
    l
    e
    )
    # .
    .
    .
    e
    n
    d
    d
    e
    f s
    e
    l
    f
    .
    u
    r
    l
    (
    u
    s
    e
    r
    , s
    t
    y
    l
    e
    )
    h
    o
    s
    t = R
    a
    i
    l
    s
    .
    c
    o
    n
    f
    i
    g
    u
    r
    a
    t
    i
    o
    n
    .
    x
    .
    a
    p
    p
    .
    h
    o
    s
    t
    U
    R
    I
    .
    j
    o
    i
    n
    (
    h
    o
    s
    t
    , p
    a
    t
    h
    (
    u
    s
    e
    r
    , s
    t
    y
    l
    e
    )
    )
    .
    t
    o
    _
    s
    e
    n
    d
    e
    n
    d
    e
    n
    d

    View Slide

  32. Error reporting
    m
    o
    d
    u
    l
    e E
    x
    c
    e
    p
    t
    i
    o
    n
    N
    o
    t
    i
    f
    i
    e
    r
    c
    l
    a
    s
    s M
    u
    l
    t
    i
    t
    e
    n
    a
    n
    t
    E
    m
    a
    i
    l
    N
    o
    t
    i
    f
    i
    e
    r < E
    m
    a
    i
    l
    N
    o
    t
    i
    f
    i
    e
    r
    d
    e
    f o
    p
    t
    i
    o
    n
    s
    s
    u
    p
    e
    r
    .
    t
    a
    p d
    o |
    o
    p
    t
    s
    |
    e
    n
    v = R
    a
    i
    l
    s
    .
    e
    n
    v
    .
    s
    t
    a
    g
    i
    n
    g
    ? ? '
    S
    T
    A
    G
    I
    N
    G
    ' : n
    i
    l
    t
    e
    n
    a
    n
    t
    _
    w
    i
    t
    h
    _
    e
    n
    v
    i
    r
    o
    n
    m
    e
    n
    t =
    [
    c
    u
    r
    r
    e
    n
    t
    _
    t
    e
    n
    a
    n
    t
    , e
    n
    v
    ]
    .
    c
    o
    m
    p
    a
    c
    t
    .
    j
    o
    i
    n
    (
    ' '
    )
    o
    p
    t
    s
    [
    :
    e
    m
    a
    i
    l
    _
    p
    r
    e
    f
    i
    x
    ] = "
    [
    #
    {
    t
    e
    n
    a
    n
    t
    _
    w
    i
    t
    h
    _
    e
    n
    v
    i
    r
    o
    n
    m
    e
    n
    t
    }
    ]
    [
    E
    R
    R
    O
    R
    ]
    "
    e
    n
    d
    e
    n
    d
    p
    r
    i
    v
    a
    t
    e
    d
    e
    f c
    u
    r
    r
    e
    n
    t
    _
    t
    e
    n
    a
    n
    t
    :
    :
    A
    p
    a
    r
    t
    m
    e
    n
    t
    :
    :
    T
    e
    n
    a
    n
    t
    .
    c
    u
    r
    r
    e
    n
    t
    .
    u
    p
    c
    a
    s
    e
    e
    n
    d
    e
    n
    d
    e
    n
    d
    Examples:
    [
    T
    E
    N
    A
    N
    T O
    N
    E
    ]
    [
    E
    R
    R
    O
    R
    ] E
    r
    r
    o
    r m
    e
    s
    s
    a
    g
    e
    [
    T
    E
    N
    A
    N
    T O
    N
    E S
    T
    A
    G
    I
    N
    G
    ]
    [
    E
    R
    R
    O
    R
    ] E
    r
    r
    o
    r m
    e
    s
    s
    a
    g
    e
    [
    T
    E
    N
    A
    N
    T T
    W
    O
    ]
    [
    E
    R
    R
    O
    R
    ] O
    t
    h
    e
    r e
    r
    r
    o
    r

    View Slide

  33. Content specialization

    View Slide

  34. Internationalization — locale les
    e
    n
    :
    t
    e
    n
    a
    n
    t
    1
    :
    h
    e
    l
    l
    o
    : '
    H
    e
    l
    l
    o t
    e
    n
    a
    n
    t
    1
    '
    o
    t
    h
    e
    r
    :
    b
    y
    e
    : '
    G
    o
    o
    d
    b
    y
    e
    '
    h
    e
    l
    l
    o
    : '
    H
    e
    l
    l
    o
    '

    View Slide

  35. Internationalization — i18n backend
    m
    o
    d
    u
    l
    e I
    1
    8
    n
    m
    o
    d
    u
    l
    e B
    a
    c
    k
    e
    n
    d
    c
    l
    a
    s
    s M
    u
    l
    t
    i
    t
    e
    n
    a
    n
    t < S
    i
    m
    p
    l
    e
    d
    e
    f l
    o
    o
    k
    u
    p
    (
    l
    o
    c
    a
    l
    e
    , k
    e
    y
    , s
    c
    o
    p
    e
    , o
    p
    t
    i
    o
    n
    s
    )
    t
    e
    n
    a
    n
    t
    _
    s
    c
    o
    p
    e = [
    c
    u
    r
    r
    e
    n
    t
    _
    t
    e
    n
    a
    n
    t
    ] + [
    s
    c
    o
    p
    e
    ]
    .
    f
    l
    a
    t
    t
    e
    n
    s
    u
    p
    e
    r
    (
    l
    o
    c
    a
    l
    e
    , k
    e
    y
    , t
    e
    n
    a
    n
    t
    _
    s
    c
    o
    p
    e
    , o
    p
    t
    i
    o
    n
    s
    )
    e
    n
    d
    p
    r
    i
    v
    a
    t
    e
    d
    e
    f c
    u
    r
    r
    e
    n
    t
    _
    t
    e
    n
    a
    n
    t
    :
    :
    A
    p
    a
    r
    t
    m
    e
    n
    t
    :
    :
    T
    e
    n
    a
    n
    t
    .
    c
    u
    r
    r
    e
    n
    t
    e
    n
    d
    e
    n
    d
    e
    n
    d
    e
    n
    d

    View Slide

  36. Internationalization — i18n backend
    r
    e
    q
    u
    i
    r
    e '
    i
    1
    8
    n
    /
    b
    a
    c
    k
    e
    n
    d
    /
    m
    u
    l
    t
    i
    t
    e
    n
    a
    n
    t
    '
    I
    1
    8
    n
    .
    b
    a
    c
    k
    e
    n
    d =
    I
    1
    8
    n
    :
    :
    B
    a
    c
    k
    e
    n
    d
    :
    :
    C
    h
    a
    i
    n
    .
    n
    e
    w
    (
    I
    1
    8
    n
    :
    :
    B
    a
    c
    k
    e
    n
    d
    :
    :
    M
    u
    l
    t
    i
    t
    e
    n
    a
    n
    t
    .
    n
    e
    w
    ,
    I
    1
    8
    n
    .
    b
    a
    c
    k
    e
    n
    d
    )

    View Slide

  37. Custom views
    c
    l
    a
    s
    s A
    p
    p
    l
    i
    c
    a
    t
    i
    o
    n
    C
    o
    n
    t
    r
    o
    l
    l
    e
    r
    b
    e
    f
    o
    r
    e
    _
    a
    c
    t
    i
    o
    n :
    p
    r
    e
    p
    e
    n
    d
    _
    t
    e
    n
    a
    n
    t
    _
    v
    i
    e
    w
    _
    p
    a
    t
    h
    p
    r
    i
    v
    a
    t
    e
    d
    e
    f p
    r
    e
    p
    e
    n
    d
    _
    t
    e
    n
    a
    n
    t
    _
    v
    i
    e
    w
    _
    p
    a
    t
    h
    t
    e
    n
    a
    n
    t = A
    p
    a
    r
    t
    m
    e
    n
    t
    :
    :
    T
    e
    n
    a
    n
    t
    .
    c
    u
    r
    r
    e
    n
    t
    p
    r
    e
    p
    e
    n
    d
    _
    v
    i
    e
    w
    _
    p
    a
    t
    h R
    a
    i
    l
    s
    .
    r
    o
    o
    t
    .
    j
    o
    i
    n
    (
    '
    a
    p
    p
    '
    , '
    v
    i
    e
    w
    s
    '
    , t
    e
    n
    a
    n
    t
    )
    e
    n
    d
    e
    n
    d

    View Slide

  38. Custom view example
    r
    e
    n
    d
    e
    r '
    h
    o
    m
    e
    /
    l
    e
    g
    a
    l
    '
    $ l
    s a
    p
    p
    /
    v
    i
    e
    w
    s
    /
    *
    /
    h
    o
    m
    e
    a
    p
    p
    /
    v
    i
    e
    w
    s
    /
    t
    e
    n
    a
    n
    t
    1
    /
    h
    o
    m
    e
    :
    l
    e
    g
    a
    l
    .
    h
    t
    m
    l
    .
    e
    r
    b
    a
    p
    p
    /
    v
    i
    e
    w
    s
    /
    t
    e
    n
    a
    n
    t
    2
    /
    h
    o
    m
    e
    :
    l
    e
    g
    a
    l
    .
    h
    t
    m
    l
    .
    e
    r
    b

    View Slide

  39. Custom design

    View Slide

  40. Custom design
    Layout:
    <
    %
    = s
    t
    y
    l
    e
    s
    h
    e
    e
    t
    _
    l
    i
    n
    k
    _
    t
    a
    g A
    p
    a
    r
    t
    m
    e
    n
    t
    :
    :
    T
    e
    n
    a
    n
    t
    .
    c
    u
    r
    r
    e
    n
    t %
    >
    t
    e
    n
    a
    n
    t
    1
    .
    c
    s
    s
    :
    /
    *
    *
    = r
    e
    q
    u
    i
    r
    e .
    /
    t
    e
    n
    a
    n
    t
    1
    /
    m
    a
    i
    n
    *
    /
    t
    e
    n
    a
    n
    t
    1
    /
    m
    a
    i
    n
    .
    s
    c
    s
    s
    :
    @
    i
    m
    p
    o
    r
    t "
    .
    .
    /
    s
    h
    a
    r
    e
    d
    /
    f
    o
    n
    t
    -
    l
    a
    t
    o
    "
    ;
    @
    i
    m
    p
    o
    r
    t "
    v
    a
    r
    i
    a
    b
    l
    e
    s
    "
    ;
    @
    i
    m
    p
    o
    r
    t "
    .
    .
    /
    a
    p
    p
    l
    i
    c
    a
    t
    i
    o
    n
    /
    m
    a
    i
    n
    "
    ;
    @
    i
    m
    p
    o
    r
    t "
    i
    m
    a
    g
    e
    s
    "
    ;

    View Slide

  41. $ t
    r
    e
    e a
    p
    p
    /
    a
    s
    s
    e
    t
    s
    /
    s
    t
    y
    l
    e
    s
    h
    e
    e
    t
    s
    a
    p
    p
    /
    a
    s
    s
    e
    t
    s
    /
    s
    t
    y
    l
    e
    s
    h
    e
    e
    t
    s
    ├── a
    p
    p
    l
    i
    c
    a
    t
    i
    o
    n
    │ ├── a
    d
    m
    i
    n
    │ │ └── .
    .
    .
    │ ├── m
    a
    i
    n
    .
    s
    c
    s
    s
    │ └── .
    .
    .
    ├── e
    m
    b
    e
    d
    │ └── m
    a
    i
    n
    .
    s
    c
    s
    s
    ├── m
    o
    b
    i
    l
    e
    │ ├── m
    a
    i
    n
    .
    s
    c
    s
    s
    │ └── .
    .
    .
    ├── t
    e
    n
    a
    n
    t
    1
    │ ├── e
    m
    b
    e
    d
    .
    s
    c
    s
    s
    │ ├── f
    o
    n
    t
    -
    l
    a
    t
    o
    .
    s
    c
    s
    s
    │ ├── i
    m
    a
    g
    e
    s
    .
    s
    c
    s
    s
    │ ├── m
    a
    i
    n
    .
    s
    c
    s
    s
    │ ├── m
    o
    b
    i
    l
    e
    .
    s
    c
    s
    s
    │ └── _
    v
    a
    r
    i
    a
    b
    l
    e
    s
    .
    s
    c
    s
    s
    ├── t
    e
    n
    a
    n
    t
    1
    .
    c
    s
    s
    ├── t
    e
    n
    a
    n
    t
    1
    _
    e
    m
    b
    e
    d
    .
    c
    s
    s
    ├── t
    e
    n
    a
    n
    t
    1
    _
    m
    o
    b
    i
    l
    e
    .
    c
    s
    s
    ├── s
    h
    a
    r
    e
    d
    │ └── f
    o
    n
    t
    -
    l
    a
    t
    o
    .
    s
    c
    s
    s
    └── .
    .
    .

    View Slide

  42. Cache

    View Slide

  43. d
    e
    f a
    p
    p
    _
    c
    a
    c
    h
    e
    (
    n
    a
    m
    e = {
    }
    , o
    p
    t
    i
    o
    n
    s = n
    i
    l
    , &
    b
    l
    o
    c
    k
    )
    k
    e
    y = [
    A
    p
    a
    r
    t
    m
    e
    n
    t
    :
    :
    T
    e
    n
    a
    n
    t
    .
    c
    u
    r
    r
    e
    n
    t
    , I
    1
    8
    n
    .
    l
    o
    c
    a
    l
    e
    , n
    a
    m
    e
    ]
    c
    a
    c
    h
    e
    (
    k
    e
    y
    , o
    p
    t
    i
    o
    n
    s
    , &
    b
    l
    o
    c
    k
    )
    e
    n
    d

    View Slide

  44. Real-world example
    m
    o
    d
    u
    l
    e C
    a
    c
    h
    e
    H
    e
    l
    p
    e
    r
    d
    e
    f a
    p
    p
    _
    c
    a
    c
    h
    e
    (
    n
    a
    m
    e = {
    }
    , o
    p
    t
    i
    o
    n
    s = n
    i
    l
    , &
    b
    l
    o
    c
    k
    )
    c
    a
    c
    h
    e
    (
    [
    A
    p
    a
    r
    t
    m
    e
    n
    t
    :
    :
    T
    e
    n
    a
    n
    t
    .
    c
    u
    r
    r
    e
    n
    t
    ,
    I
    1
    8
    n
    .
    l
    o
    c
    a
    l
    e
    ,
    d
    e
    v
    i
    c
    e
    _
    c
    a
    c
    h
    e
    _
    k
    e
    y
    ,
    c
    u
    r
    r
    e
    n
    t
    _
    a
    c
    c
    o
    u
    n
    t
    .
    t
    r
    y
    (
    :
    r
    o
    l
    e
    s
    _
    c
    a
    c
    h
    e
    _
    k
    e
    y
    )
    ,
    n
    a
    m
    e
    ]
    .
    f
    l
    a
    t
    t
    e
    n
    (
    1
    )
    , o
    p
    t
    i
    o
    n
    s
    , &
    b
    l
    o
    c
    k
    )
    e
    n
    d
    d
    e
    f d
    e
    v
    i
    c
    e
    _
    c
    a
    c
    h
    e
    _
    k
    e
    y
    [
    d
    e
    v
    i
    c
    e
    _
    r
    e
    q
    u
    i
    r
    e
    s
    _
    u
    s
    e
    r
    _
    a
    c
    t
    i
    o
    n
    _
    t
    o
    _
    p
    l
    a
    y
    ?
    ]
    .
    i
    n
    d
    e
    x
    { |
    v
    e
    r
    s
    i
    o
    n
    | v
    e
    r
    s
    i
    o
    n }
    e
    n
    d
    d
    e
    f m
    o
    d
    e
    l
    _
    i
    s
    _
    o
    r
    _
    b
    e
    l
    o
    n
    g
    s
    _
    t
    o
    _
    c
    u
    r
    r
    e
    n
    t
    _
    u
    s
    e
    r
    ?
    (
    m
    o
    d
    e
    l
    )
    i
    f c
    u
    r
    r
    e
    n
    t
    _
    u
    s
    e
    r
    m
    o
    d
    e
    l =
    = c
    u
    r
    r
    e
    n
    t
    _
    u
    s
    e
    r |
    | m
    o
    d
    e
    l
    .
    t
    r
    y
    (
    :
    u
    s
    e
    r
    ) =
    = c
    u
    r
    r
    e
    n
    t
    _
    u
    s
    e
    r
    e
    n
    d
    e
    n
    d
    e
    n
    d

    View Slide

  45. Thank you

    View Slide