txt: ## dist_cpan-JNTHN-Cro-HTTP-Session-Pg.md
  # Cro::HTTP::Session::Pg
  
  An implementation of Cro persistent sessions using Postgres.
  
  ## Assumptions
  
  There are dozens of ways we might do session storage; this module handles
  the case where:
  
  * The database is being accessed using `DB::Pg`.
  * You're fine with the session state being serialized and stored as a
    string/blob in the database.
  
  If these don't meet your needs, it's best to steal the code from this
  module into your own application and edit it as needed.
  
  ## Database setup
  
  Create a table like this in the database:
  
  ```
  CREATE TABLE sessions (
      id TEXT PRIMARY KEY,
      state TEXT,
      expiration TIMESTAMP
  );
  
  ```
  
  You can change the table and column names, but will then have to specify
  them when constructing the session state object.
  
  ## Minimal Cro application setup
  
  First, create a session object if you do not already have one. This is
  a class that holds the session state. We'll be saving/loading its content.
  For example:
  
  ```
  class MySession {
      has $.user-id;
  
      method set-logged-in-user($!user-id --> Nil) { }
  
      method is-logged-in(--> Bool) { $!user-id.defined }
  }
  
  ```
  
  In the case that:
  
  * You are using the default table/column names
  * Your session object can be serialized by serializing its public attributes
    to JSON, and deserialized by passing those back to new
  * You are fine with the default 60 minute session expiration time
  
  Then the only thing needed is to construct the session storage middleware with
  a database handle and a session cookie name.
  
  ```
  my $session-middleware = Cro::HTTP::Session::Pg[MySession].new:
      :$db,
      :cookie-name('my_app_name_session');
  
  ```
  
  It can then be applied as application or `route`-block level middleware.
  
  ## Tweaking the session duration
  
  Pass a `Duration` object as the `duration` named argument:
  
  ```
  my $session-middleware = Cro::HTTP::Session::Pg[MySession].new:
      :$db,
      :cookie-name('my_app_name_session'),
      :duration(Duration.new(15 #`(minutes) * 60)); 
  
  ```
  
  ## Tweaking the table and column names
  
  Pass these named arguments as needed during construction:
  
  * `sessions-table`
  * `id-column`
  * `state-column`
  * `expiration-column`
  
  ## Controlling serialization
  
  Instead of using the `Cro::HTTP::Session::Pg` role directly, create a
  class that composes it.
  
  ```
  class MySessionStore does Cro::HTTP::Session::Pg[MySession] {
      method serialize(MySession $s) {
          # Replace this with your serialization logic.
          to-json $s.Capture.hash
      }
      
      method deserialize($d --> MySession) {
          # Replace this with your deserialization logic.
          Session.new(|from-json($d))
      }
  }
  
  ```
  