-
Notifications
You must be signed in to change notification settings - Fork 0
first draft #2
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
first draft #2
Changes from all commits
8471be6
e5afcc3
0b8e6d2
461135b
8c7c529
59c54b8
28512cc
ec2f272
78b3abb
d3a0a6e
f217b29
2f983a3
e8db95c
c8a2f89
c3df296
c9a8c41
e70d0af
ddc42d3
8d6ffc1
ada519c
15a2d0d
a67e0df
be6a12e
8dd7a9e
e36857a
0437e2c
ca2b874
e12aab3
dbc78df
5d899b6
5d9f90b
7df33c2
0560640
e69ef5d
787f7d2
666f77e
c5cd1a3
24a1f6c
f038b4b
a2b3b8c
a20e5fc
5d45607
6a43e02
9a64133
2da5d75
c8e68e9
d38c08f
e3c0314
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| name: test | ||
|
|
||
| on: | ||
| pull_request: | ||
| push: | ||
| branches: | ||
| - main | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| jobs: | ||
| unit: | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 5 | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: actions/setup-node@v4 | ||
| - run: npm run docker:start | ||
| - run: npm install | ||
| - run: npm test |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| output | ||
| node_modules | ||
| package-lock.json | ||
| output_test |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| ignore-scripts=true |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,22 @@ | ||
| # open-abap-lock | ||
| lock | ||
|
|
||
| Concurrent/cross session locking for Open ABAP. | ||
|
|
||
| Requires and works with PostgreSQL as the database backend, and only on the DEFAULT connection. | ||
|
|
||
| ## Notes | ||
|
|
||
| * [PostgreSQL - Advisory Locks](https://www.postgresql.org/docs/current/explicit-locking.html#ADVISORY-LOCKS) | ||
| * [PostgreSQL - Advisory Lock Functions](https://www.postgresql.org/docs/9.1/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS) | ||
|
|
||
| wildcards? | ||
| scope? | ||
| release on crash | ||
| table `pg_locks` | ||
|
|
||
| ## Todo | ||
|
|
||
| * `_scope` | ||
| * `wait` flag | ||
| * `mode` | ||
| * release at commit work if update task |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| { | ||
| "input_folder": ["src", "test/src"], | ||
| "input_filter": [], | ||
| "output_folder": "output", | ||
| "write_unit_tests": true, | ||
| "write_source_map": true, | ||
| "libs": [ | ||
| { | ||
| "url": "https://github.com/open-abap/open-abap-core" | ||
| } | ||
| ], | ||
| "options": { | ||
| "ignoreSyntaxCheck": false, | ||
| "addFilenames": true, | ||
| "addCommonJS": true, | ||
| "populateTables": { | ||
| "reposrc": false | ||
| }, | ||
| "setup": { | ||
| "filename": "../test/setup.mjs", | ||
| "postFunction": "postFunction", | ||
| "preFunction": "preFunction" | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| { | ||
| "name": "open-abap-lock", | ||
| "version": "1.0.0", | ||
| "private": true, | ||
| "description": "test", | ||
| "scripts": { | ||
| "lint": "abaplint", | ||
| "unit": "rm -rf output && abap_transpile abap_transpile.jsonc && echo RUNNING && node output/index.mjs", | ||
| "docker:start": "docker compose -p open-abap-lock -f test/stack.yml up -d", | ||
| "docker:stop": "docker compose -p open-abap-lock -f test/stack.yml down -v", | ||
| "test": "npm run lint && npm run unit" | ||
| }, | ||
| "license": "", | ||
| "dependencies": { | ||
| "@abaplint/cli": "^2.114.6", | ||
| "@abaplint/runtime": "^2.12.16", | ||
| "@abaplint/database-pg": "^2.11.78", | ||
| "@abaplint/transpiler-cli": "^2.12.16" | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,7 +1,131 @@ | ||||||||||||||||||||
| CLASS kernel_lock_concurrent DEFINITION PUBLIC. | ||||||||||||||||||||
| PUBLIC SECTION. | ||||||||||||||||||||
| CLASS-METHODS class_constructor. | ||||||||||||||||||||
|
|
||||||||||||||||||||
| CLASS-METHODS enqueue | ||||||||||||||||||||
| IMPORTING | ||||||||||||||||||||
| input TYPE any | ||||||||||||||||||||
| table_name TYPE string | ||||||||||||||||||||
| enqueue_name TYPE string | ||||||||||||||||||||
| EXCEPTIONS | ||||||||||||||||||||
| foreign_lock | ||||||||||||||||||||
| system_failure. | ||||||||||||||||||||
|
|
||||||||||||||||||||
| CLASS-METHODS dequeue | ||||||||||||||||||||
| IMPORTING | ||||||||||||||||||||
| table_name TYPE string | ||||||||||||||||||||
| enqueue_name TYPE string | ||||||||||||||||||||
| input TYPE any. | ||||||||||||||||||||
|
|
||||||||||||||||||||
| TYPES: BEGIN OF ty_cleanup, | ||||||||||||||||||||
| valid_locks TYPE i, | ||||||||||||||||||||
| cleaned_locks TYPE i, | ||||||||||||||||||||
| END OF ty_cleanup. | ||||||||||||||||||||
| CLASS-METHODS cleanup_locks | ||||||||||||||||||||
| RETURNING | ||||||||||||||||||||
| VALUE(rs_result) TYPE ty_cleanup. | ||||||||||||||||||||
| PRIVATE SECTION. | ||||||||||||||||||||
| CLASS-METHODS build_lock_key | ||||||||||||||||||||
| IMPORTING | ||||||||||||||||||||
| input TYPE any | ||||||||||||||||||||
| table_name TYPE string | ||||||||||||||||||||
| RETURNING | ||||||||||||||||||||
| VALUE(rv_lock_key) TYPE kernel_locks-lock_key. | ||||||||||||||||||||
| ENDCLASS. | ||||||||||||||||||||
|
|
||||||||||||||||||||
| CLASS kernel_lock_concurrent IMPLEMENTATION. | ||||||||||||||||||||
|
|
||||||||||||||||||||
| METHOD class_constructor. | ||||||||||||||||||||
| cleanup_locks( ). | ||||||||||||||||||||
| ENDMETHOD. | ||||||||||||||||||||
|
|
||||||||||||||||||||
| METHOD cleanup_locks. | ||||||||||||||||||||
| SELECT * FROM kernel_locks INTO TABLE @DATA(lt_locks) ORDER BY PRIMARY KEY ##SUBRC_OK. | ||||||||||||||||||||
| LOOP AT lt_locks INTO DATA(ls_lock). | ||||||||||||||||||||
| DATA(lv_exists) = lcl_advisory=>exists( lcl_key=>encode( ls_lock-lock_key ) ). | ||||||||||||||||||||
| IF lv_exists = abap_true. | ||||||||||||||||||||
| rs_result-valid_locks = rs_result-valid_locks + 1. | ||||||||||||||||||||
| ELSE. | ||||||||||||||||||||
| DELETE FROM kernel_locks WHERE table_name = @ls_lock-table_name AND lock_key = @ls_lock-lock_key. | ||||||||||||||||||||
| rs_result-cleaned_locks = rs_result-cleaned_locks + 1. | ||||||||||||||||||||
| ENDIF. | ||||||||||||||||||||
| ENDLOOP. | ||||||||||||||||||||
| ENDMETHOD. | ||||||||||||||||||||
|
|
||||||||||||||||||||
| METHOD build_lock_key. | ||||||||||||||||||||
|
|
||||||||||||||||||||
| DATA lr_dref TYPE REF TO data. | ||||||||||||||||||||
| DATA lo_structdescr TYPE REF TO cl_abap_structdescr. | ||||||||||||||||||||
| DATA lv_string TYPE string. | ||||||||||||||||||||
|
|
||||||||||||||||||||
| FIELD-SYMBOLS <lg_row> TYPE any. | ||||||||||||||||||||
|
|
||||||||||||||||||||
| CREATE DATA lr_dref TYPE (table_name). | ||||||||||||||||||||
| ASSIGN lr_dref->* TO <lg_row>. | ||||||||||||||||||||
|
|
||||||||||||||||||||
| lo_structdescr ?= cl_abap_typedescr=>describe_by_data( <lg_row> ). | ||||||||||||||||||||
| ASSERT lo_structdescr IS NOT INITIAL. | ||||||||||||||||||||
|
|
||||||||||||||||||||
| LOOP AT lo_structdescr->components INTO DATA(ls_component). | ||||||||||||||||||||
| WRITE '@KERNEL lv_string.set(input[ls_component.get().name.get().toLowerCase().trimEnd()] || "");'. | ||||||||||||||||||||
|
||||||||||||||||||||
| WRITE '@KERNEL lv_string.set(input[ls_component.get().name.get().toLowerCase().trimEnd()] || "");'. | |
| " Dynamically get the value from input structure for the current component | |
| FIELD-SYMBOLS <lv_input_field> TYPE any. | |
| ASSIGN COMPONENT ls_component-name OF STRUCTURE input TO <lv_input_field>. | |
| IF sy-subrc = 0 AND <lv_input_field> IS NOT INITIAL. | |
| lv_string = |{ <lv_input_field> }|. | |
| ELSE. | |
| lv_string = ''. | |
| ENDIF. |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment on line 120 says "it doesnt have the lock" but the logic is attempting to acquire the lock in the dequeue method. This is confusing - the dequeue method should release a lock, not attempt to acquire one. The comment should clarify why acquiring a lock is necessary during dequeue, or this may indicate a logic issue.
| " it doesnt have the lock, or another session has the lock | |
| " Unable to acquire the lock: either this session does not hold the lock, or another session currently holds it. |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Grammar/spelling error in comment: "it doesnt" should be "it doesn't" (missing apostrophe).
| " it doesnt have the lock, or another session has the lock | |
| " it doesn't have the lock, or another session has the lock |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The DELETE statement uses unquoted variables in the WHERE clause which may not be bound correctly. Consider using @table_name and @lv_lock_key to ensure proper parameter binding.
| DELETE FROM kernel_locks WHERE table_name = table_name AND lock_key = lv_lock_key. | |
| DELETE FROM kernel_locks WHERE table_name = @table_name AND lock_key = @lv_lock_key. |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment says "advisory locks stack" but calling unlock twice suggests each lock operation may need to be balanced. However, in the dequeue method, only one lock is acquired (line 118) but two unlock calls are made. This appears to be an off-by-one error that could cause issues with the lock state.
| lcl_advisory=>unlock( lcl_key=>encode( lv_lock_key ) ). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
licensefield is empty. This should either specify a license (e.g., "MIT", "Apache-2.0") or be set to "UNLICENSED" if the code is proprietary. An empty string is not a valid license identifier.