-
Notifications
You must be signed in to change notification settings - Fork 25
Postgres Bucket Storage #178
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
Merged
Merged
Changes from all commits
Commits
Show all changes
51 commits
Select commit
Hold shift + click to select a range
a82e02e
postgres bucket storage initial
stevensJourney a745f33
wip test factory
stevensJourney 997ed4e
Add postgres storage to MySQL and Postgres replicator tests
stevensJourney 3846a99
Fixes for MySQL tests: Store relation_id as text. Update BIGINT max …
stevensJourney ee891a8
Add Postgres storage to MongoDB replicator tests. Fix bug: last_check…
stevensJourney 501df22
git move
stevensJourney a86472a
share logic in lib postgres
stevensJourney 556b8d1
Add postgres storage to CI
stevensJourney 63d8e3f
fix core test
stevensJourney a255cb7
dispose clients
stevensJourney 7121d06
fix postgres slow tests
stevensJourney 98f46a1
bump timeout
stevensJourney 73de76e
fix truncation
stevensJourney 0c682bb
attempt to fix racey mysql test
stevensJourney 653626a
fix sync rules termination bug
stevensJourney 9fd0481
cleanup
stevensJourney af47872
added changeset
stevensJourney 198b6aa
improve sync performance
stevensJourney 705b472
fix bug
stevensJourney dc76df1
cleanup
stevensJourney e64bde5
Merge remote-tracking branch 'origin/main' into pg-bucket-storage
stevensJourney 7524d3b
cleanup
stevensJourney b670441
add env note
stevensJourney b9009d8
add primary keys to tables
stevensJourney 07bbf19
update max row size to match mongo
stevensJourney 6fbd9f8
set keepalive_op to bigint
stevensJourney 40d434f
Cleanup sync_rules id sequence usage. Use integer/number type for gro…
stevensJourney 405521e
fix lock conflict.
stevensJourney 07ca4b7
move comment.
stevensJourney a06c715
update readme configuration. Remove batch settings from documentation.
stevensJourney c03e56e
better size estimation
stevensJourney fc39638
update to pg_relation_size to not include index size.
stevensJourney 8c4a7e9
test pg_total_relation_size with vitest snapshot
stevensJourney efed534
add beta readme note
stevensJourney d17d896
update postgres replication storage snapshot
stevensJourney af9a6a1
cleanup slot poking
stevensJourney 7cb338d
add note about ts-codec. Make buffer codex a bit clearer.
stevensJourney c517976
move pgwire_number to codecs file
stevensJourney 79da9db
cleanup
stevensJourney d006e90
update bucket_parameters types
stevensJourney 198fe30
store relation_id as json in order to store number or string type
stevensJourney 91da74d
remove duplicated lines
stevensJourney 7f3ea55
Updated BucketStorageFactory to use AsyncDisposable
stevensJourney c39ea45
added changeset
stevensJourney 2318c6d
fix mongo tests
stevensJourney 2d0f8fd
remove mystery todo update comment
stevensJourney 444bc95
reset metrics between tests
stevensJourney 483b94e
Improve migration logic.
stevensJourney 5a723fd
fix typo
stevensJourney 9556a47
cleanup
stevensJourney 780770b
add public config in order for publish task to succeed
stevensJourney File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| --- | ||
| '@powersync/service-module-mongodb-storage': minor | ||
| '@powersync/service-core-tests': minor | ||
| '@powersync/service-core': minor | ||
| --- | ||
|
|
||
| Updated BucketStorageFactory to use AsyncDisposable |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| --- | ||
| '@powersync/service-module-postgres-storage': minor | ||
| '@powersync/service-module-postgres': minor | ||
| '@powersync/lib-service-postgres': minor | ||
| '@powersync/service-core': minor | ||
| --- | ||
|
|
||
| Initial release of Postgres bucket storage. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| --- | ||
| '@powersync/service-core-tests': minor | ||
| '@powersync/lib-services-framework': minor | ||
| --- | ||
|
|
||
| Improved migrations logic. Up migrations can be executed correctly after down migrations. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,5 @@ | ||
| # Connections for tests | ||
| MONGO_TEST_URL="mongodb://localhost:27017/powersync_test" | ||
| PG_TEST_URL="postgres://postgres:postgres@localhost:5432/powersync_test" | ||
| PG_TEST_URL="postgres://postgres:postgres@localhost:5432/powersync_test" | ||
| # Note that this uses a separate server on a different port | ||
| PG_STORAGE_TEST_URL="postgres://postgres:postgres@localhost:5431/powersync_storage_test" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -104,6 +104,18 @@ jobs: | |
| -d postgres:${{ matrix.postgres-version }} \ | ||
| -c wal_level=logical | ||
|
|
||
| - name: Start PostgreSQL (Storage) | ||
| run: | | ||
| docker run \ | ||
| --health-cmd pg_isready \ | ||
| --health-interval 10s \ | ||
| --health-timeout 5s \ | ||
| --health-retries 5 \ | ||
| -e POSTGRES_PASSWORD=postgres \ | ||
| -e POSTGRES_DB=powersync_storage_test \ | ||
| -p 5431:5432 \ | ||
| -d postgres:${{ matrix.postgres-version }} | ||
|
|
||
| - name: Start MongoDB | ||
| uses: supercharge/[email protected] | ||
| with: | ||
|
|
@@ -176,6 +188,18 @@ jobs: | |
| mongodb-version: '6.0' | ||
| mongodb-replica-set: test-rs | ||
|
|
||
| - name: Start PostgreSQL (Storage) | ||
| run: | | ||
| docker run \ | ||
| --health-cmd pg_isready \ | ||
| --health-interval 10s \ | ||
| --health-timeout 5s \ | ||
| --health-retries 5 \ | ||
| -e POSTGRES_PASSWORD=postgres \ | ||
| -e POSTGRES_DB=powersync_storage_test \ | ||
| -p 5431:5432 \ | ||
| -d postgres:16 | ||
|
|
||
| - name: Setup NodeJS | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
|
|
@@ -229,6 +253,18 @@ jobs: | |
| mongodb-version: ${{ matrix.mongodb-version }} | ||
| mongodb-replica-set: test-rs | ||
|
|
||
| - name: Start PostgreSQL (Storage) | ||
| run: | | ||
| docker run \ | ||
| --health-cmd pg_isready \ | ||
| --health-interval 10s \ | ||
| --health-timeout 5s \ | ||
| --health-retries 5 \ | ||
| -e POSTGRES_PASSWORD=postgres \ | ||
| -e POSTGRES_DB=powersync_storage_test \ | ||
| -p 5431:5432 \ | ||
| -d postgres:16 | ||
|
|
||
| - name: Setup Node.js | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| # @powersync/lib-service-postgres |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| # Functional Source License, Version 1.1, Apache 2.0 Future License | ||
|
|
||
| ## Abbreviation | ||
|
|
||
| FSL-1.1-Apache-2.0 | ||
|
|
||
| ## Notice | ||
|
|
||
| Copyright 2023-2024 Journey Mobile, Inc. | ||
|
|
||
| ## Terms and Conditions | ||
|
|
||
| ### Licensor ("We") | ||
|
|
||
| The party offering the Software under these Terms and Conditions. | ||
|
|
||
| ### The Software | ||
|
|
||
| The "Software" is each version of the software that we make available under these Terms and Conditions, as indicated by our inclusion of these Terms and Conditions with the Software. | ||
|
|
||
| ### License Grant | ||
|
|
||
| Subject to your compliance with this License Grant and the Patents, Redistribution and Trademark clauses below, we hereby grant you the right to use, copy, modify, create derivative works, publicly perform, publicly display and redistribute the Software for any Permitted Purpose identified below. | ||
|
|
||
| ### Permitted Purpose | ||
|
|
||
| A Permitted Purpose is any purpose other than a Competing Use. A Competing Use means making the Software available to others in a commercial product or service that: | ||
|
|
||
| 1. substitutes for the Software; | ||
| 2. substitutes for any other product or service we offer using the Software that exists as of the date we make the Software available; or | ||
| 3. offers the same or substantially similar functionality as the Software. | ||
|
|
||
| Permitted Purposes specifically include using the Software: | ||
|
|
||
| 1. for your internal use and access; | ||
| 2. for non-commercial education; | ||
| 3. for non-commercial research; and | ||
| 4. in connection with professional services that you provide to a licensee using the Software in accordance with these Terms and Conditions. | ||
|
|
||
| ### Patents | ||
|
|
||
| To the extent your use for a Permitted Purpose would necessarily infringe our patents, the license grant above includes a license under our patents. If you make a claim against any party that the Software infringes or contributes to the infringement of any patent, then your patent license to the Software ends immediately. | ||
|
|
||
| ### Redistribution | ||
|
|
||
| The Terms and Conditions apply to all copies, modifications and derivatives of the Software. | ||
| If you redistribute any copies, modifications or derivatives of the Software, you must include a copy of or a link to these Terms and Conditions and not remove any copyright notices provided in or with the Software. | ||
|
|
||
| ### Disclaimer | ||
|
|
||
| THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, TITLE OR NON-INFRINGEMENT. | ||
| IN NO EVENT WILL WE HAVE ANY LIABILITY TO YOU ARISING OUT OF OR RELATED TO THE SOFTWARE, INCLUDING INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, EVEN IF WE HAVE BEEN INFORMED OF THEIR POSSIBILITY IN ADVANCE. | ||
|
|
||
| ### Trademarks | ||
|
|
||
| Except for displaying the License Details and identifying us as the origin of the Software, you have no right under these Terms and Conditions to use our trademarks, trade names, service marks or product names. | ||
|
|
||
| ## Grant of Future License | ||
|
|
||
| We hereby irrevocably grant you an additional license to use the Software under the Apache License, Version 2.0 that is effective on the second anniversary of the date we make the Software available. On or after that date, you may use the Software under the Apache License, Version 2.0, in which case the following will apply: | ||
|
|
||
| Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. | ||
| You may obtain a copy of the License at | ||
|
|
||
| http://www.apache.org/licenses/LICENSE-2.0 | ||
|
|
||
| Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| # PowerSync Service Postgres | ||
|
|
||
| Library for common Postgres logic used in the PowerSync service. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| { | ||
| "name": "@powersync/lib-service-postgres", | ||
| "repository": "https://github.com/powersync-ja/powersync-service", | ||
| "types": "dist/index.d.ts", | ||
| "version": "0.0.0", | ||
| "main": "dist/index.js", | ||
| "license": "FSL-1.1-Apache-2.0", | ||
| "type": "module", | ||
| "publishConfig": { | ||
| "access": "public" | ||
| }, | ||
| "scripts": { | ||
| "build": "tsc -b", | ||
| "build:tests": "tsc -b test/tsconfig.json", | ||
| "clean": "rm -rf ./dist && tsc -b --clean", | ||
| "test": "vitest" | ||
| }, | ||
| "exports": { | ||
| ".": { | ||
| "import": "./dist/index.js", | ||
| "require": "./dist/index.js", | ||
| "default": "./dist/index.js" | ||
| }, | ||
| "./types": { | ||
| "import": "./dist/types/types.js", | ||
| "require": "./dist/types/types.js", | ||
| "default": "./dist/types/types.js" | ||
| } | ||
| }, | ||
| "dependencies": { | ||
| "@powersync/lib-services-framework": "workspace:*", | ||
| "@powersync/service-jpgwire": "workspace:*", | ||
| "@powersync/service-sync-rules": "workspace:*", | ||
| "@powersync/service-types": "workspace:*", | ||
| "p-defer": "^4.0.1", | ||
| "ts-codec": "^1.3.0", | ||
| "uri-js": "^4.4.1", | ||
| "uuid": "^9.0.1" | ||
| }, | ||
| "devDependencies": { | ||
| "@types/uuid": "^9.0.4" | ||
| } | ||
| } |
109 changes: 109 additions & 0 deletions
109
libs/lib-postgres/src/db/connection/AbstractPostgresConnection.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,109 @@ | ||
| import * as framework from '@powersync/lib-services-framework'; | ||
| import * as pgwire from '@powersync/service-jpgwire'; | ||
| import * as t from 'ts-codec'; | ||
|
|
||
| export type DecodedSQLQueryExecutor<T extends t.Codec<any, any>> = { | ||
| first: () => Promise<t.Decoded<T> | null>; | ||
| rows: () => Promise<t.Decoded<T>[]>; | ||
| }; | ||
|
|
||
| export abstract class AbstractPostgresConnection< | ||
| Listener extends framework.DisposableListener = framework.DisposableListener | ||
| > extends framework.DisposableObserver<Listener> { | ||
| protected abstract baseConnection: pgwire.PgClient; | ||
|
|
||
| stream(...args: pgwire.Statement[]): AsyncIterableIterator<pgwire.PgChunk> { | ||
| return this.baseConnection.stream(...args); | ||
| } | ||
|
|
||
| query(script: string, options?: pgwire.PgSimpleQueryOptions): Promise<pgwire.PgResult>; | ||
| query(...args: pgwire.Statement[]): Promise<pgwire.PgResult>; | ||
| query(...args: any[]): Promise<pgwire.PgResult> { | ||
| return this.baseConnection.query(...args); | ||
| } | ||
|
|
||
| /** | ||
| * Template string helper which can be used to execute template SQL strings. | ||
| */ | ||
| sql(strings: TemplateStringsArray, ...params: pgwire.StatementParam[]) { | ||
| const { statement, params: queryParams } = sql(strings, ...params); | ||
|
|
||
| const rows = <T>(): Promise<T[]> => | ||
| this.queryRows({ | ||
| statement, | ||
| params: queryParams | ||
| }); | ||
|
|
||
| const first = async <T>(): Promise<T | null> => { | ||
| const [f] = await rows<T>(); | ||
| return f; | ||
| }; | ||
|
|
||
| return { | ||
| execute: () => | ||
| this.query({ | ||
| statement, | ||
| params | ||
| }), | ||
| rows, | ||
| first, | ||
| decoded: <T extends t.Codec<any, any>>(codec: T): DecodedSQLQueryExecutor<T> => { | ||
| return { | ||
| first: async () => { | ||
| const result = await first(); | ||
| return result && codec.decode(result); | ||
| }, | ||
| rows: async () => { | ||
| const results = await rows(); | ||
| return results.map((r) => { | ||
| return codec.decode(r); | ||
| }); | ||
| } | ||
| }; | ||
| } | ||
| }; | ||
| } | ||
|
|
||
| queryRows<T>(script: string, options?: pgwire.PgSimpleQueryOptions): Promise<T[]>; | ||
| queryRows<T>(...args: pgwire.Statement[] | [...pgwire.Statement[], pgwire.PgExtendedQueryOptions]): Promise<T[]>; | ||
| async queryRows(...args: any[]) { | ||
| return pgwire.pgwireRows(await this.query(...args)); | ||
| } | ||
|
|
||
| async *streamRows<T>(...args: pgwire.Statement[]): AsyncIterableIterator<T[]> { | ||
| let columns: Array<keyof T> = []; | ||
|
|
||
| for await (const chunk of this.stream(...args)) { | ||
| if (chunk.tag == 'RowDescription') { | ||
| columns = chunk.payload.map((c, index) => { | ||
| return c.name as keyof T; | ||
| }); | ||
| continue; | ||
| } | ||
|
|
||
| if (!chunk.rows.length) { | ||
| continue; | ||
| } | ||
|
|
||
| yield chunk.rows.map((row) => { | ||
| let q: Partial<T> = {}; | ||
| for (const [index, c] of columns.entries()) { | ||
| q[c] = row[index]; | ||
| } | ||
| return q as T; | ||
| }); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Template string helper function which generates PGWire statements. | ||
| */ | ||
| export const sql = (strings: TemplateStringsArray, ...params: pgwire.StatementParam[]): pgwire.Statement => { | ||
| const paramPlaceholders = new Array(params.length).fill('').map((value, index) => `$${index + 1}`); | ||
| const joinedQueryStatement = strings.map((query, index) => `${query} ${paramPlaceholders[index] ?? ''}`).join(' '); | ||
| return { | ||
| statement: joinedQueryStatement, | ||
| params | ||
| }; | ||
| }; |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.