Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add standalone MPR postgres module #41

Merged
merged 18 commits into from
Dec 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
71eb74e
feat: Initial commit add standalone MPR postgress module
gabrielmatau79 Dec 18, 2024
c8d3cf8
refactor: Resolve the requested changes regarding module configuratio…
gabrielmatau79 Dec 18, 2024
e3a532d
refactor: Resolve the requested changes regarding the refactoring of …
gabrielmatau79 Dec 18, 2024
99f4fb2
feat: Resolve the requested changes regarding the introduction of a c…
gabrielmatau79 Dec 18, 2024
a20acf9
fix: fix export class into package/postgress/index.ts
gabrielmatau79 Dec 18, 2024
3d66932
fix: fix name packages postgres
gabrielmatau79 Dec 19, 2024
23852ae
refactor: Resolve the requested changes in variable names and type ex…
gabrielmatau79 Dec 19, 2024
a57ab7e
feat: add release configuration and encapsulated in an options object…
gabrielmatau79 Dec 19, 2024
2decf51
docs: Add documentation for using the PostgresMessagePickupRepository
gabrielmatau79 Dec 19, 2024
d07f5bc
fix: fix request changes about package.json and remove fcmServiceBaseUrl
gabrielmatau79 Dec 19, 2024
739e45f
fix: Fix description package.json
gabrielmatau79 Dec 19, 2024
1aceb9c
fix: fix querys sql into dbcollections.ts
gabrielmatau79 Dec 20, 2024
2061999
fix: remove conditionial 'this.instance' to publish message when live…
gabrielmatau79 Dec 20, 2024
fe221a6
refactor: The table names are changed to livesession and queuedmessage.
gabrielmatau79 Dec 20, 2024
4621818
fix: fix include indexMessageTable in buildPgDatabase
gabrielmatau79 Dec 20, 2024
8f86e72
chore: fix names, simplify example in README
genaris Dec 24, 2024
7493cbe
style: ignore CHANGELOG
genaris Dec 24, 2024
e2ae0ad
revert: changes in CHANGELOG
genaris Dec 24, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CHANGELOG.md
22 changes: 11 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@ Service designed for the management and storage of messaging for the Message Pic

## Environment Variables

| Variable | Description | Default Value |
| ---------------------- | ------------------------------------------------------------------------- | ----------------------------------------------------------------- |
| `APP_PORT` | The port number on which the application will run. | `3500` |
| `WS_PORT` | The port number on which the WebSocket server runs. | `3100` |
| `FCM_SERVICE_BASE_URL` | The base URL for the push notification service. | _Not set by default_ |
| `MONGODB_URI` | The MongoDB URI for connecting to the database. | `mongodb://user:password@localhost:27017/MessagePickupRepository` |
| `REDIS_TYPE` | Allows set redis type works `single` or `cluster` | `single` |
| `REDIS_NODES` | A comma-separated list of Redis nodes' `host:port` for cluster mode. Only required if `REDIS_TYPE` is set to `cluster`. Ignored in single mode. | `redis-node1:6379,redis-node2:6379,redis-node3:6379` |
| `REDIS_NATMAP` | The NAT mapping for Redis nodes in `externalAddress:host:port` format. Required for Redis cluster configurations where external IPs or ports are mapped to internal Redis node addresses. | `10.0.0.1:6379:redis-node1:6379,10.0.0.2:6379:redis-node2:6379` |
| `REDIS_URL` | The Redis database URL for connecting to the server.(only single mode) | `redis://localhost:6379` |
| `THRESHOLD_TIMESTAMP` | Allows set threshold time to execute message persist module on milisecond | `60000` |
| Variable | Description | Default Value |
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- |
| `APP_PORT` | The port number on which the application will run. | `3500` |
| `WS_PORT` | The port number on which the WebSocket server runs. | `3100` |
| `FCM_SERVICE_BASE_URL` | The base URL for the push notification service. | _Not set by default_ |
| `MONGODB_URI` | The MongoDB URI for connecting to the database. | `mongodb://user:password@localhost:27017/MessagePickupRepository` |
| `REDIS_TYPE` | Allows set redis type works `single` or `cluster` | `single` |
| `REDIS_NODES` | A comma-separated list of Redis nodes' `host:port` for cluster mode. Only required if `REDIS_TYPE` is set to `cluster`. Ignored in single mode. | `redis-node1:6379,redis-node2:6379,redis-node3:6379` |
| `REDIS_NATMAP` | The NAT mapping for Redis nodes in `externalAddress:host:port` format. Required for Redis cluster configurations where external IPs or ports are mapped to internal Redis node addresses. | `10.0.0.1:6379:redis-node1:6379,10.0.0.2:6379:redis-node2:6379` |
| `REDIS_URL` | The Redis database URL for connecting to the server.(only single mode) | `redis://localhost:6379` |
| `THRESHOLD_TIMESTAMP` | Allows set threshold time to execute message persist module on milisecond | `60000` |

## Installation

Expand Down
3 changes: 3 additions & 0 deletions packages/postgres/.release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"packages/postgres": "0.0.1"
}
105 changes: 105 additions & 0 deletions packages/postgres/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# credo-ts-message-pickup-repository-pg API Usage Documentation

## Overview

The `PostgresMessagePickupRepository` implements the MessagePickupRepository interface from @credo-ts to manage messaging in live mode. It uses PostgreSQL as the storage backend for all messaging operations and introduces a publish/subscribe system to support multiple instances sharing the same database that need .

This approach centralizes all database operations for a DIDComm Mediator, simplifying its implementation and ensuring seamless scalability across multiple instances.

## Features

- Message storage and retrieval: Save and fetch messages from a PostgreSQL database.

- Pub/Sub integration: Notify other services of new messages using Pub/Sub channels.

- Live session management: Handle live sessions for efficient message delivery.

- Database initialization: Automatically set up the database structure required for message operations.

## Installation

To use this module, install package in your Didcomm Mediator App:

```bash
npm i @2060.io/credo-ts-message-pickup-repository-pg
```

## Usage

Instance `PostgresMessagePickupRepository` with requires explicit configuration defined in `PostgresMessagePickupRepositoryConfig` type through its constructor to set up the PostgreSQL connection and Logger. Ensure to provide the necessary database credentials when creating an instance of the repository.

### Example Configuration

```javascript
const messageRepository = new PostgresMessagePickupRepository({
logger: yourLoggerInstance,
postgresUser: 'your_postgres_user',
postgresPassword: 'your_postgres_password',
postgresHost: 'your_postgres_host',
postgresDatabaseName: 'your_database_name',
})
```

### Initializing the Repository

To start using the `PostgresMessagePickupRepository`, initialize it with an agent and a callback function for retrieving connection information.

Note that in this example, notification token is stored as a tag in connection records, so it is used to determine whether to create a Push notification callback or not for a given DIDComm connection.

```javascript
const connectionInfoCallback = async (connectionId) => {
const connectionRecord = await this.agent.connections.findById(connectionId)
const token = connectionRecord?.getTag('device_token') as string | null
return {
sendPushNotification: token ? (messageId) => { this.notificationSender.send(token, messageId }: undefined,
}
}
await messagePickupRepository.initialize({ agent, connectionInfoCallback })
```

### Using with a Credo-based DIDComm Mediator

This full example shows how `PostgresMessagePickupRepository` is created an initialized alongside an `Agent` instance:

```javascript
import { Agent, MediatorModule, MessagePickupModule } from '@credo-ts/core'
import { agentDependencies } from '@credo-ts/node'
import { MessageForwardingStrategy } from '@credo-ts/core/build/modules/routing/MessageForwardingStrategy'
import { PostgresMessagePickupRepository } from './PostgresMessagePickupRepository'

const messagePickupRepository = new PostgresMessagePickupRepository({
postgresHost: 'postgres',
postgresUser: 'user',
postgresPassword: 'pass',
})
const agent = new Agent({
dependencies: agentDependencies,
config: { label: 'Test' },
modules: {
mediator: new MediatorModule({ messageForwardingStrategy: MessageForwardingStrategy.QueueOnly }),
messagePickup: new MessagePickupModule({
messagePickupRepository,
}),
},
})

const notificationSender = // { your implementation of a Push notification service }
const connectionInfoCallback = async (connectionId: string) => {
const connectionRecord = await agent.connections.findById(connectionId)

const token = connectionRecord?.getTag('device_token') as string | null

return {
sendPushNotification: token
? (messageId: string) => {
notificationSender.send(token, messageId)
}
: undefined,
}
}

await messagePickupRepository.initialize({ agent, connectionInfoCallback })
await agent.initialize()
```

With these steps, you can now use the `PostgresMessagePickupRepository` with your Credo-based DIDComm mediator. Have fun!
28 changes: 28 additions & 0 deletions packages/postgres/config/dbCollections.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
export const messagesTableName = 'queuedmessage'

export const createTableMessage = `
CREATE TABLE IF NOT EXISTS ${messagesTableName} (
id VARCHAR(20) DEFAULT substr(md5(random()::text), 1, 20) PRIMARY KEY,
connectionId VARCHAR(255),
recipientKeys TEXT[],
encryptedMessage JSONB,
state VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
`

export const liveSessionTableName = 'livesession'

export const createTableLive = `
CREATE TABLE IF NOT EXISTS ${liveSessionTableName} (
sessionid VARCHAR(255) PRIMARY KEY,
connectionid VARCHAR(50),
protocolVersion VARCHAR(50),
role VARCHAR(50),
instance VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);`

export const messageTableIndex = `CREATE INDEX IF NOT EXISTS "${messagesTableName}_connectionId_index" ON "${messagesTableName}" (connectionId);`

export const liveSessionTableIndex = `CREATE INDEX IF NOT EXISTS "${liveSessionTableName}_connectionid" ON "${liveSessionTableName}" USING btree ("connectionid");`
21 changes: 21 additions & 0 deletions packages/postgres/jest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import type { Config } from '@jest/types'

const config: Config.InitialOptions = {
preset: 'ts-jest',
testEnvironment: 'node',
coveragePathIgnorePatterns: ['/build/', '/node_modules/', '/__tests__/', 'tests'],
coverageDirectory: '<rootDir>/coverage/',
testMatch: ['**/?(*.)+(spec|test).[tj]s?(x)'],
transform: {
'^.+\\.tsx?$': [
'ts-jest',
{
isolatedModules: true,
},
],
'^.+\\.jsx?$': require.resolve('babel-jest'),
},
moduleNameMapper: { '^uuid$': 'uuid' },
}

export default config
46 changes: 46 additions & 0 deletions packages/postgres/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"name": "@2060.io/credo-ts-message-pickup-repository-pg",
"main": "build/src/index.js",
"types": "build/src/index.d.ts",
"version": "0.0.1",
"files": [
"build"
],
"publishConfig": {
"access": "public"
},
"description": "Message Pickup Repository Postgres module",
"license": "Apache-2.0",
"homepage": "https://github.com/2060-io/message-pickup-repository/tree/main/packages/postgres",
"repository": {
"type": "git",
"url": "https://github.com/2060-io/message-pickup-repository",
"directory": "packages/postgres"
},
"scripts": {
"build": "yarn run clean && yarn run compile",
"clean": "rimraf -rf ./build",
"compile": "tsc -p tsconfig.build.json",
"prepublishOnly": "yarn run build",
"test": "jest"
},
"dependencies": {
"@credo-ts/core": "^0.5.11",
"loglevel": "^1.8.0",
"pg": "^8.11.3",
"pg-pubsub": "^0.8.1",
"typescript": "^4.0.0"
},
"devDependencies": {
"@types/node": "^16.0.0",
"@types/pg": "^8.11.10",
"jest": "^27.0.0",
"ts-jest": "^27.0.0",
"ts-loader": "^9.0.0",
"webpack": "^5.0.0",
"webpack-cli": "^4.0.0"
},
"peerDependencies": {
"@credo-ts/core": "^0.5.11"
}
}
5 changes: 5 additions & 0 deletions packages/postgres/release-please-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"packages/postgres": {
"release-type": "node"
}
}
Loading
Loading