Add social-media, order-hub ingestion tutorial source codes - #144
Add social-media, order-hub ingestion tutorial source codes#144pasindufernando1 wants to merge 2 commits into
Conversation
📝 WalkthroughAdded the social-media and order-hub tutorial source code to the integrator-default-profile workspace.
Overall, the change set wires up the tutorial projects end to end with their source code, data models, and package configuration. WalkthroughThis PR adds three new Ballerina integration samples and tutorials under
Each project includes full project scaffolding (Ballerina.toml, Dependencies.toml, .gitignore, context/workspace configs) and a README. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 15
🧹 Nitpick comments (1)
integrator-default-profile/samples/order-management-automation/orderprocessingautomation/automation.bal (1)
16-17: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueUse string templates instead of concatenation.
- subject: placedOrder.orderId + ": status update", - body: "Your order bearing id :" + placedOrder.orderId + " is now under process" + subject: string `${placedOrder.orderId}: status update`, + body: string `Your order bearing id: ${placedOrder.orderId} is now under process`🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@integrator-default-profile/samples/order-management-automation/orderprocessingautomation/automation.bal` around lines 16 - 17, The email subject/body in the order status message is built with string concatenation; update the literals in the order-processing logic to use string templates instead. Locate the status update message around placedOrder.orderId in the automation flow and rewrite both the subject and body expressions using template interpolation for clearer, more consistent formatting.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@integrator-default-profile/samples/order-management-automation/orderprocessingautomation/automation.bal`:
- Around line 5-26: The per-order processing in main updates each order through
ordersDB->/orders/[placedOrder.orderId].put before calling
emailSmtpclient->sendMessage, which can leave orders stuck in PROCESSING if the
email send fails. Move the status update and email delivery into a transaction
block so they succeed or fail together, or make the flow idempotent so retries
are safe. Keep the existing placedOrders loop and error handling in main, but
ensure the DB write and notification are coordinated per order.
In
`@integrator-default-profile/samples/order-management-automation/orderprocessingautomation/connections.bal`:
- Line 7: The SMTP client initialization in the emailSmtpclient declaration
hardcodes START_TLS_NEVER, which should not be used as a default for production.
Update the emailSmtpclient setup to make the security mode configurable via a
parameter or environment-driven setting, and if this value must remain for the
sample, add a clear comment near the new expression explaining it is only for
local development. Reference the emailSmtpclient and its new() constructor usage
so the change stays localized.
In
`@integrator-default-profile/tutorials/order-hub-freshmart/daily_summary/automation.bal`:
- Around line 35-39: The sender address in emailSmtpclient->sendMessage is
hard-coded to a placeholder, which can break delivery on SMTP servers. Update
the automation.bal daily summary flow to read the from value from configuration
and ensure it matches the authenticated SMTP account, keeping the existing
sendMessage call in sync with the configured sender.
In
`@integrator-default-profile/tutorials/order-hub-freshmart/daily_summary/config.bal`:
- Around line 9-12: The SMTP defaults in the daily summary config are
inconsistent because `smtpHost`/`smtpPort`/`smtpUser` target a local
unauthenticated server while `smtpPassword` remains mandatory. Update the
`configurable` settings in `config.bal` so `smtpPassword` is optional when
`smtpUser` is empty, or else change both `smtpUser` and `smtpPassword` to
matching authenticated defaults. Use the existing `smtpHost`, `smtpPort`,
`smtpUser`, and `smtpPassword` declarations to keep the tutorial runnable
without extra setup.
In
`@integrator-default-profile/tutorials/order-hub-freshmart/daily_summary/Dependencies.toml`:
- Around line 253-256: The self-referenced package version is inconsistent
between Ballerina.toml and Dependencies.toml, so update the package version to
match in the relevant manifest and then regenerate Dependencies.toml if the
version bump is intentional. Use the daily_summary package entry and its version
field to align both files and remove the stale lockfile mismatch.
In
`@integrator-default-profile/tutorials/order-hub-freshmart/order_intake/Ballerina.toml`:
- Around line 19-23: The `[[dependency]]` entry for `tool.persist` is out of
sync with the resolved version; update the pinned version in `Ballerina.toml` to
match the `Dependencies.toml` resolution or remove the explicit pin if version
management should be automatic. Use the `tool.persist` dependency block in
`order_intake/Ballerina.toml` as the target and ensure the declared version no
longer conflicts with the resolved `1.9.2`.
In
`@integrator-default-profile/tutorials/order-hub-freshmart/order_intake/data_mappings.bal`:
- Around line 15-22: The transformHarborOrders mapping currently masks invalid
numeric values by defaulting decimal:int parsing failures to zero, which lets
bad Harbor rows pass through. Update transformHarborOrders in data_mappings.bal
so price and units conversion failures are propagated as an error instead of
using 0 defaults, and keep the row/file invalid for the ingest flow to route it
to /errors. Focus on the conversion logic inside the lineTotals computation and
the lines record construction where decimal:fromString and int:fromString are
used.
- Around line 2-13: The transformGreenFieldOrders mapper currently dereferences
greenFieldRows[0] immediately, so it must first validate that greenFieldRows is
non-empty. Update transformGreenFieldOrders to return an error when the input
array is empty, and let the caller propagate that failure so the batch can be
routed to /errors instead of crashing. Use the existing
transformGreenFieldOrders and GreenfieldRow[] handling to add the guard before
building the Order record.
In
`@integrator-default-profile/tutorials/order-hub-freshmart/order_intake/main.bal`:
- Around line 25-49: The order import logic in the order intake flow writes the
parent order and then each line item separately, which can leave partial data if
a later insert fails. Update the handler around the dbClient->/orders.post and
dbClient->/orderlines.post calls to persist the order and its lines atomically,
preferably by using a single transaction scope for both inserts. If
transactional support is not available in this flow, add failure handling that
rolls back or deletes the created order when any line insert fails, and apply
the same fix to the other matching import handler.
In `@integrator-default-profile/tutorials/social-media/post_notifier/main.bal`:
- Around line 9-12: The Slack post in post_notifier main.bal is hardcoded to an
invalid channel value, so update the slackClient->/chat.postMessage call to use
a valid lowercase channel name or, preferably, a channel ID sourced from
configuration instead of the literal "New post creations". Keep the change
localized to the chat.postMessage invocation and ensure the channel argument
matches a real Slack destination that can receive messages.
In `@integrator-default-profile/tutorials/social-media/sentiment_api/main.bal`:
- Around line 8-12: The stubbed Probability values in the sentiment API sample
are inconsistent because the neg/neutral/pos scores do not sum to 1.0; update
the sample response in main.bal so the Probability object represents a
normalized distribution. Keep the existing Probability symbol and adjust the
three values so their total is exactly 1.0, preserving realistic sentiment
proportions.
In
`@integrator-default-profile/tutorials/social-media/social_media/Ballerina.toml`:
- Around line 25-29: The `[[dependency]]` entry for `ballerina/tool.persist` is
pinned to a version that conflicts with the resolved lock version; update the
version in `Ballerina.toml` to match the resolved `Dependencies.toml` version or
remove the override if you want automatic resolution. Check the `tool.persist`
dependency block in `Ballerina.toml` and keep it only when intentionally pinning
or overriding a minimum required version.
- Line 5: The Ballerina distribution version is out of sync with the resolved
lockfile version. Update the distribution setting in Ballerina.toml to match the
distribution-version used in Dependencies.toml so the tutorial project uses a
consistent version; use the Ballerina.toml distribution field and the lockfile’s
distribution-version as the source of truth.
In
`@integrator-default-profile/tutorials/social-media/social_media/connections.bal`:
- Line 8: The sentiment service endpoint is hardcoded in the social_media
connection setup, which makes the tutorial environment-coupled. Update the
client initialization in connections.bal so the http:Client in the
sentimentClient declaration is created from a configurable base URL instead of a
fixed localhost:9000 value. Introduce configuration for this endpoint and use
that config when constructing the client so the post flow can work across
separate deployments.
In `@integrator-default-profile/tutorials/social-media/social_media/main.bal`:
- Around line 33-45: The post creation logic in main.bal is hardcoding
createdDate inside the dbClient->/posts.post call, which causes every inserted
post to share the same date. Update the post insertion flow to derive
createdDate dynamically from the current time or the incoming event payload, and
keep the change within the same post creation block so the persisted data
reflects the actual post date.
---
Nitpick comments:
In
`@integrator-default-profile/samples/order-management-automation/orderprocessingautomation/automation.bal`:
- Around line 16-17: The email subject/body in the order status message is built
with string concatenation; update the literals in the order-processing logic to
use string templates instead. Locate the status update message around
placedOrder.orderId in the automation flow and rewrite both the subject and body
expressions using template interpolation for clearer, more consistent
formatting.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 9285ef66-07d8-485f-9f5d-d75b42964b5d
📒 Files selected for processing (79)
integrator-default-profile/samples/order-management-automation/.choreo/context.yamlintegrator-default-profile/samples/order-management-automation/Ballerina.tomlintegrator-default-profile/samples/order-management-automation/orderprocessingautomation/.gitignoreintegrator-default-profile/samples/order-management-automation/orderprocessingautomation/Ballerina.tomlintegrator-default-profile/samples/order-management-automation/orderprocessingautomation/Dependencies.tomlintegrator-default-profile/samples/order-management-automation/orderprocessingautomation/README.mdintegrator-default-profile/samples/order-management-automation/orderprocessingautomation/agents.balintegrator-default-profile/samples/order-management-automation/orderprocessingautomation/automation.balintegrator-default-profile/samples/order-management-automation/orderprocessingautomation/config.balintegrator-default-profile/samples/order-management-automation/orderprocessingautomation/connections.balintegrator-default-profile/samples/order-management-automation/orderprocessingautomation/data_mappings.balintegrator-default-profile/samples/order-management-automation/orderprocessingautomation/functions.balintegrator-default-profile/samples/order-management-automation/orderprocessingautomation/main.balintegrator-default-profile/samples/order-management-automation/orderprocessingautomation/persist/ordersDB/model.balintegrator-default-profile/samples/order-management-automation/orderprocessingautomation/types.balintegrator-default-profile/tutorials/order-hub-freshmart/.wso2/context.yamlintegrator-default-profile/tutorials/order-hub-freshmart/Ballerina.tomlintegrator-default-profile/tutorials/order-hub-freshmart/README.mdintegrator-default-profile/tutorials/order-hub-freshmart/daily_summary/.gitignoreintegrator-default-profile/tutorials/order-hub-freshmart/daily_summary/Ballerina.tomlintegrator-default-profile/tutorials/order-hub-freshmart/daily_summary/Dependencies.tomlintegrator-default-profile/tutorials/order-hub-freshmart/daily_summary/agents.balintegrator-default-profile/tutorials/order-hub-freshmart/daily_summary/automation.balintegrator-default-profile/tutorials/order-hub-freshmart/daily_summary/config.balintegrator-default-profile/tutorials/order-hub-freshmart/daily_summary/connections.balintegrator-default-profile/tutorials/order-hub-freshmart/daily_summary/data_mappings.balintegrator-default-profile/tutorials/order-hub-freshmart/daily_summary/functions.balintegrator-default-profile/tutorials/order-hub-freshmart/daily_summary/main.balintegrator-default-profile/tutorials/order-hub-freshmart/daily_summary/persist/dbClient/model.balintegrator-default-profile/tutorials/order-hub-freshmart/daily_summary/types.balintegrator-default-profile/tutorials/order-hub-freshmart/order_intake/.gitignoreintegrator-default-profile/tutorials/order-hub-freshmart/order_intake/Ballerina.tomlintegrator-default-profile/tutorials/order-hub-freshmart/order_intake/Dependencies.tomlintegrator-default-profile/tutorials/order-hub-freshmart/order_intake/agents.balintegrator-default-profile/tutorials/order-hub-freshmart/order_intake/automation.balintegrator-default-profile/tutorials/order-hub-freshmart/order_intake/config.balintegrator-default-profile/tutorials/order-hub-freshmart/order_intake/connections.balintegrator-default-profile/tutorials/order-hub-freshmart/order_intake/data_mappings.balintegrator-default-profile/tutorials/order-hub-freshmart/order_intake/functions.balintegrator-default-profile/tutorials/order-hub-freshmart/order_intake/main.balintegrator-default-profile/tutorials/order-hub-freshmart/order_intake/persist/dbClient/model.balintegrator-default-profile/tutorials/order-hub-freshmart/order_intake/types.balintegrator-default-profile/tutorials/social-media/.choreo/context.yamlintegrator-default-profile/tutorials/social-media/Ballerina.tomlintegrator-default-profile/tutorials/social-media/README.mdintegrator-default-profile/tutorials/social-media/post_notifier/.gitignoreintegrator-default-profile/tutorials/social-media/post_notifier/Ballerina.tomlintegrator-default-profile/tutorials/social-media/post_notifier/Dependencies.tomlintegrator-default-profile/tutorials/social-media/post_notifier/agents.balintegrator-default-profile/tutorials/social-media/post_notifier/automation.balintegrator-default-profile/tutorials/social-media/post_notifier/config.balintegrator-default-profile/tutorials/social-media/post_notifier/connections.balintegrator-default-profile/tutorials/social-media/post_notifier/data_mappings.balintegrator-default-profile/tutorials/social-media/post_notifier/functions.balintegrator-default-profile/tutorials/social-media/post_notifier/main.balintegrator-default-profile/tutorials/social-media/post_notifier/types.balintegrator-default-profile/tutorials/social-media/sentiment_api/.gitignoreintegrator-default-profile/tutorials/social-media/sentiment_api/Ballerina.tomlintegrator-default-profile/tutorials/social-media/sentiment_api/Dependencies.tomlintegrator-default-profile/tutorials/social-media/sentiment_api/agents.balintegrator-default-profile/tutorials/social-media/sentiment_api/automation.balintegrator-default-profile/tutorials/social-media/sentiment_api/config.balintegrator-default-profile/tutorials/social-media/sentiment_api/connections.balintegrator-default-profile/tutorials/social-media/sentiment_api/data_mappings.balintegrator-default-profile/tutorials/social-media/sentiment_api/functions.balintegrator-default-profile/tutorials/social-media/sentiment_api/main.balintegrator-default-profile/tutorials/social-media/sentiment_api/types.balintegrator-default-profile/tutorials/social-media/social_media/.gitignoreintegrator-default-profile/tutorials/social-media/social_media/Ballerina.tomlintegrator-default-profile/tutorials/social-media/social_media/Dependencies.tomlintegrator-default-profile/tutorials/social-media/social_media/agents.balintegrator-default-profile/tutorials/social-media/social_media/automation.balintegrator-default-profile/tutorials/social-media/social_media/config.balintegrator-default-profile/tutorials/social-media/social_media/connections.balintegrator-default-profile/tutorials/social-media/social_media/data_mappings.balintegrator-default-profile/tutorials/social-media/social_media/functions.balintegrator-default-profile/tutorials/social-media/social_media/main.balintegrator-default-profile/tutorials/social-media/social_media/persist/dbClient/model.balintegrator-default-profile/tutorials/social-media/social_media/types.bal
| public function main() returns error? { | ||
| do { | ||
| PlacedOrdersType[] placedOrders = check ordersDB->/orders.get(whereClause = `status = ${"PLACED"}`); | ||
| if placedOrders.length() == 0 { | ||
| log:printInfo("No new orders to process."); | ||
| return; | ||
| } | ||
| foreach PlacedOrdersType placedOrder in placedOrders { | ||
| ordersdb:Order updatedOrder = check ordersDB->/orders/[placedOrder.orderId].put({status: "PROCESSING"}); | ||
| check emailSmtpclient->sendMessage({ | ||
| to: placedOrder.customer.email, | ||
| subject: placedOrder.orderId + ": status update", | ||
| body: "Your order bearing id :" + placedOrder.orderId + " is now under process" | ||
| }); | ||
| log:printInfo(string `Order advanced to PROCESSING: ${updatedOrder.orderId}`); | ||
| } | ||
| log:printInfo(string `Done - processed ${placedOrders.length()} orders`); | ||
| } on fail error e { | ||
| log:printError("Error occurred", 'error = e); | ||
| return e; | ||
| } | ||
| } |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🔴 Critical | 🏗️ Heavy lift
Risk of partial failure: order status updated without guaranteed email delivery.
The loop updates each order to PROCESSING before sending the corresponding email. If an email fails partway through the batch, those orders remain in PROCESSING but the customer was never notified. Subsequent runs skip them because of the status filter. Wrap the per-order DB update and email send in a transaction block, or redesign for idempotency so retries are safe.
foreach PlacedOrdersType placedOrder in placedOrders {
- ordersdb:Order updatedOrder = check ordersDB->/orders/[placedOrder.orderId].put({status: "PROCESSING"});
- check emailSmtpclient->sendMessage({
- to: placedOrder.customer.email,
- subject: placedOrder.orderId + ": status update",
- body: "Your order bearing id :" + placedOrder.orderId + " is now under process"
- });
- log:printInfo(string `Order advanced to PROCESSING: ${updatedOrder.orderId}`);
+ transaction {
+ ordersdb:Order updatedOrder = check ordersDB->/orders/[placedOrder.orderId].put({status: "PROCESSING"});
+ check emailSmtpclient->sendMessage({
+ to: placedOrder.customer.email,
+ subject: string `${placedOrder.orderId}: status update`,
+ body: string `Your order bearing id: ${placedOrder.orderId} is now under process`
+ });
+ log:printInfo(string `Order advanced to PROCESSING: ${updatedOrder.orderId}`);
+ } on fail error e {
+ log:printError(string `Failed to process order ${placedOrder.orderId}`, 'error = e);
+ // Consider compensation: revert status or queue for retry
+ continue;
+ }
}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@integrator-default-profile/samples/order-management-automation/orderprocessingautomation/automation.bal`
around lines 5 - 26, The per-order processing in main updates each order through
ordersDB->/orders/[placedOrder.orderId].put before calling
emailSmtpclient->sendMessage, which can leave orders stuck in PROCESSING if the
email send fails. Move the status update and email delivery into a transaction
block so they succeed or fail together, or make the flow idempotent so retries
are safe. Keep the existing placedOrders loop and error handling in main, but
ensure the DB write and notification are coordinated per order.
|
|
||
| final ordersdb:Client ordersDB = check new (ordersDBHost, ordersDBPort, ordersDBUser, ordersDBPassword, ordersDBDatabase); | ||
|
|
||
| final email:SmtpClient emailSmtpclient = check new (string `${emailHost}`, string `${emailUserName}`, string `${emailPassword}`, port = emailPort, security = "START_TLS_NEVER"); |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Avoid hardcoding START_TLS_NEVER for SMTP security.
Explicitly disabling TLS encryption is unsafe for production SMTP. Make the security mode configurable or add a prominent comment warning that this setting is for local development only.
- final email:SmtpClient emailSmtpclient = check new (string `${emailHost}`, string `${emailUserName}`, string `${emailPassword}`, port = emailPort, security = "START_TLS_NEVER");
+ configurable string emailSecurity = "START_TLS_AUTO";
+ final email:SmtpClient emailSmtpclient = check new (emailHost, emailUserName, emailPassword, port = emailPort, security = emailSecurity);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| final email:SmtpClient emailSmtpclient = check new (string `${emailHost}`, string `${emailUserName}`, string `${emailPassword}`, port = emailPort, security = "START_TLS_NEVER"); | |
| configurable string emailSecurity = "START_TLS_AUTO"; | |
| final email:SmtpClient emailSmtpclient = check new (emailHost, emailUserName, emailPassword, port = emailPort, security = emailSecurity); |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@integrator-default-profile/samples/order-management-automation/orderprocessingautomation/connections.bal`
at line 7, The SMTP client initialization in the emailSmtpclient declaration
hardcodes START_TLS_NEVER, which should not be used as a default for production.
Update the emailSmtpclient setup to make the security mode configurable via a
parameter or environment-driven setting, and if this value must remain for the
sample, add a clear comment near the new expression explaining it is only for
local development. Reference the emailSmtpclient and its new() constructor usage
so the change stays localized.
| check emailSmtpclient->sendMessage({ | ||
| to: "procurement@freshmart.com", | ||
| subject: string `Daily summary : ${date.day}/${date.month}/${date.year}`, | ||
| 'from: "procurementbot@example", | ||
| htmlBody: htmlBody |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Use a configurable, valid sender address.
Line 38 hard-codes a placeholder from value. Many SMTP setups reject messages when the sender address is not a real mailbox for the configured account, so this can stop the daily summary from being delivered. Move the sender into configuration and align it with the authenticated SMTP user.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@integrator-default-profile/tutorials/order-hub-freshmart/daily_summary/automation.bal`
around lines 35 - 39, The sender address in emailSmtpclient->sendMessage is
hard-coded to a placeholder, which can break delivery on SMTP servers. Update
the automation.bal daily summary flow to read the from value from configuration
and ensure it matches the authenticated SMTP account, keeping the existing
sendMessage call in sync with the configured sender.
| configurable string smtpHost = "localhost"; | ||
| configurable int smtpPort = 1025; | ||
| configurable string smtpUser = ""; | ||
| configurable string smtpPassword = ?; No newline at end of file |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Make the SMTP defaults internally consistent.
These defaults point to a local test SMTP server (localhost:1025) with no username, but smtpPassword is still mandatory. That forces extra configuration before the tutorial can start. Make the password optional when smtpUser is empty, or provide authenticated defaults for both fields.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@integrator-default-profile/tutorials/order-hub-freshmart/daily_summary/config.bal`
around lines 9 - 12, The SMTP defaults in the daily summary config are
inconsistent because `smtpHost`/`smtpPort`/`smtpUser` target a local
unauthenticated server while `smtpPassword` remains mandatory. Update the
`configurable` settings in `config.bal` so `smtpPassword` is optional when
`smtpUser` is empty, or else change both `smtpUser` and `smtpPassword` to
matching authenticated defaults. Use the existing `smtpHost`, `smtpPort`,
`smtpUser`, and `smtpPassword` declarations to keep the tutorial runnable
without extra setup.
| org = "wso2" | ||
| name = "daily_summary" | ||
| version = "0.1.0" | ||
| dependencies = [ |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win
Resolve version mismatch between Ballerina.toml and Dependencies.toml.
The self-referenced package version in Dependencies.toml is 0.1.1, but Ballerina.toml declares 0.1.0. Align the versions to prevent stale lockfile warnings. Regenerate Dependencies.toml after updating Ballerina.toml if the version bump was intentional.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@integrator-default-profile/tutorials/order-hub-freshmart/daily_summary/Dependencies.toml`
around lines 253 - 256, The self-referenced package version is inconsistent
between Ballerina.toml and Dependencies.toml, so update the package version to
match in the relevant manifest and then regenerate Dependencies.toml if the
version bump is intentional. Use the daily_summary package entry and its version
field to align both files and remove the stale lockfile mismatch.
| Probability probability = { | ||
| "neg": 0.30135019761690551, | ||
| "neutral": 0.27119050546800266, | ||
| "pos": 0.69864980238309449 | ||
| }; |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Return normalized probability values.
These three values add up to 1.27119050546800266, so the stub response is internally inconsistent. Please adjust the sample scores so the probability breakdown sums to 1.0.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@integrator-default-profile/tutorials/social-media/sentiment_api/main.bal`
around lines 8 - 12, The stubbed Probability values in the sentiment API sample
are inconsistent because the neg/neutral/pos scores do not sum to 1.0; update
the sample response in main.bal so the Probability object represents a
normalized distribution. Keep the existing Probability symbol and adjust the
three values so their total is exactly 1.0, preserving realistic sentiment
proportions.
| org = "wso2" | ||
| name = "social_media" | ||
| version = "0.1.0" | ||
| distribution = "2201.13.3" |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Distribution version mismatch with lock file.
distribution = "2201.13.3" does not match the resolved distribution-version = "2201.13.4" in Dependencies.toml. Align these to ensure reproducible builds and avoid confusion.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@integrator-default-profile/tutorials/social-media/social_media/Ballerina.toml`
at line 5, The Ballerina distribution version is out of sync with the resolved
lockfile version. Update the distribution setting in Ballerina.toml to match the
distribution-version used in Dependencies.toml so the tutorial project uses a
consistent version; use the Ballerina.toml distribution field and the lockfile’s
distribution-version as the source of truth.
| [[dependency]] | ||
| org = "ballerina" | ||
| name = "tool.persist" | ||
| version = "1.9.1" | ||
|
|
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Pinned tool.persist version does not match resolved lock version.
Ballerina.toml pins tool.persist to 1.9.1, but Dependencies.toml resolves 1.9.2. Update the pin or remove it if automatic resolution is preferred. Based on learnings, [[dependency]] should only be used when overriding or pinning a minimum required version intentionally.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@integrator-default-profile/tutorials/social-media/social_media/Ballerina.toml`
around lines 25 - 29, The `[[dependency]]` entry for `ballerina/tool.persist` is
pinned to a version that conflicts with the resolved lock version; update the
version in `Ballerina.toml` to match the resolved `Dependencies.toml` version or
remove the override if you want automatic resolution. Check the `tool.persist`
dependency block in `Ballerina.toml` and keep it only when intentionally pinning
or overriding a minimum required version.
Source: Learnings
|
|
||
| final socialmedia:Client dbClient = check new (dbClientHost, dbClientPort, dbClientUser, dbClientPassword, dbClientDatabase); | ||
| final rabbitmq:Client rabbitmqClient = check new (rabbitmqHost, rabbitmqPort); | ||
| final http:Client sentimentClient = check new ("http://localhost:9000/text-processing"); |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Make the sentiment service URL configurable.
localhost:9000 only works when social_media and sentiment_api run on the same host. Since this tutorial adds them as separate packages, the post flow becomes environment-coupled. Move the base URL into configuration and create the client from that value.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@integrator-default-profile/tutorials/social-media/social_media/connections.bal`
at line 8, The sentiment service endpoint is hardcoded in the social_media
connection setup, which makes the tutorial environment-coupled. Update the
client initialization in connections.bal so the http:Client in the
sentimentClient declaration is created from a configurable base URL instead of a
fixed localhost:9000 value. Introduce configuration for this endpoint and use
that config when constructing the client so the post flow can work across
separate deployments.
| int[] insertResult = check dbClient->/posts.post([ | ||
| { | ||
| description: newPost.description, | ||
| category: newPost.category, | ||
| tags: newPost.tags, | ||
| createdDate: { | ||
| year: 2026, | ||
| month: 7, | ||
| day: 17 | ||
| }, | ||
| userId: id | ||
| } | ||
| ]); |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Do not persist a fixed post date.
Lines 38-42 write every new post with 2026-07-17, so stored data and any date-based behavior will be wrong as soon as the sample runs on a different day. Derive createdDate from the current time or the incoming event instead.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@integrator-default-profile/tutorials/social-media/social_media/main.bal`
around lines 33 - 45, The post creation logic in main.bal is hardcoding
createdDate inside the dbClient->/posts.post call, which causes every inserted
post to share the same date. Update the post insertion flow to derive
createdDate dynamically from the current time or the incoming event payload, and
keep the change within the same post creation block so the persisted data
reflects the actual post date.
There was a problem hiding this comment.
Pull request overview
Note
Copilot couldn't run its full agentic review because no GitHub Actions runner was available. Make sure your repository has a runner available to run Copilot's review, or add a copilot-setup-steps.yml file specifying one with the runs-on attribute. See the docs for more details.
Adds new tutorial/source packages for “social-media” and “order-hub-freshmart”, plus an “order-management-automation” sample, to demonstrate event-driven and file-ingestion integration patterns in WSO2 Integrator.
Changes:
- Added
social-mediaworkspace with REST API + sentiment service + RabbitMQ-to-Slack notifier. - Added
order-hub-freshmartworkspace with FTP ingestion + daily email summary automation. - Added
order-management-automationsample workspace with DB-driven scheduled processing + email notifications.
Reviewed changes
Copilot reviewed 79 out of 79 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| integrator-default-profile/tutorials/social-media/social_media/types.bal | Defines public request/response types for the Social Media API. |
| integrator-default-profile/tutorials/social-media/social_media/persist/dbClient/model.bal | Adds persist model (MySQL) for users, posts, and followers. |
| integrator-default-profile/tutorials/social-media/social_media/main.bal | Implements REST resources for users and posts, sentiment check, DB write, RabbitMQ publish. |
| integrator-default-profile/tutorials/social-media/social_media/functions.bal | Placeholder file for tutorial scaffold. |
| integrator-default-profile/tutorials/social-media/social_media/data_mappings.bal | Placeholder file for tutorial scaffold. |
| integrator-default-profile/tutorials/social-media/social_media/connections.bal | Creates DB, RabbitMQ, and sentiment HTTP clients. |
| integrator-default-profile/tutorials/social-media/social_media/config.bal | Declares configurables for DB and RabbitMQ connectivity. |
| integrator-default-profile/tutorials/social-media/social_media/automation.bal | Placeholder file for tutorial scaffold. |
| integrator-default-profile/tutorials/social-media/social_media/agents.bal | Placeholder file for tutorial scaffold. |
| integrator-default-profile/tutorials/social-media/social_media/Dependencies.toml | Captures resolved dependencies for the social_media package. |
| integrator-default-profile/tutorials/social-media/social_media/Ballerina.toml | Declares package metadata + persist tool config for social_media. |
| integrator-default-profile/tutorials/social-media/social_media/.gitignore | Ignores build artifacts and local config for social_media. |
| integrator-default-profile/tutorials/social-media/sentiment_api/types.bal | Defines request/response types for the sentiment service. |
| integrator-default-profile/tutorials/social-media/sentiment_api/main.bal | Implements a sentiment scoring HTTP API used by social_media. |
| integrator-default-profile/tutorials/social-media/sentiment_api/functions.bal | Placeholder file for tutorial scaffold. |
| integrator-default-profile/tutorials/social-media/sentiment_api/data_mappings.bal | Placeholder file for tutorial scaffold. |
| integrator-default-profile/tutorials/social-media/sentiment_api/connections.bal | Placeholder file for tutorial scaffold. |
| integrator-default-profile/tutorials/social-media/sentiment_api/config.bal | Placeholder file for tutorial scaffold. |
| integrator-default-profile/tutorials/social-media/sentiment_api/automation.bal | Placeholder file for tutorial scaffold. |
| integrator-default-profile/tutorials/social-media/sentiment_api/agents.bal | Placeholder file for tutorial scaffold. |
| integrator-default-profile/tutorials/social-media/sentiment_api/Dependencies.toml | Captures resolved dependencies for the sentiment_api package. |
| integrator-default-profile/tutorials/social-media/sentiment_api/Ballerina.toml | Declares package metadata for sentiment_api. |
| integrator-default-profile/tutorials/social-media/sentiment_api/.gitignore | Ignores build artifacts and local config for sentiment_api. |
| integrator-default-profile/tutorials/social-media/post_notifier/types.bal | Defines RabbitMQ message payload types for post notifications. |
| integrator-default-profile/tutorials/social-media/post_notifier/main.bal | Consumes RabbitMQ events and posts a Slack message. |
| integrator-default-profile/tutorials/social-media/post_notifier/functions.bal | Placeholder file for tutorial scaffold. |
| integrator-default-profile/tutorials/social-media/post_notifier/data_mappings.bal | Placeholder file for tutorial scaffold. |
| integrator-default-profile/tutorials/social-media/post_notifier/connections.bal | Creates Slack client used by the notifier. |
| integrator-default-profile/tutorials/social-media/post_notifier/config.bal | Declares configurables for RabbitMQ + Slack auth. |
| integrator-default-profile/tutorials/social-media/post_notifier/automation.bal | Placeholder file for tutorial scaffold. |
| integrator-default-profile/tutorials/social-media/post_notifier/agents.bal | Placeholder file for tutorial scaffold. |
| integrator-default-profile/tutorials/social-media/post_notifier/Dependencies.toml | Captures resolved dependencies for the post_notifier package. |
| integrator-default-profile/tutorials/social-media/post_notifier/Ballerina.toml | Declares package metadata for post_notifier. |
| integrator-default-profile/tutorials/social-media/post_notifier/.gitignore | Ignores build artifacts and local config for post_notifier. |
| integrator-default-profile/tutorials/social-media/README.md | Documents the event-driven social media tutorial and how to run it. |
| integrator-default-profile/tutorials/social-media/Ballerina.toml | Defines the social-media workspace packages. |
| integrator-default-profile/tutorials/social-media/.choreo/context.yaml | Adds Choreo project context metadata for the tutorial. |
| integrator-default-profile/tutorials/order-hub-freshmart/order_intake/types.bal | Defines canonical order types + supplier-specific input record shapes. |
| integrator-default-profile/tutorials/order-hub-freshmart/order_intake/persist/dbClient/model.bal | Adds persist model (MySQL) for orders and order lines. |
| integrator-default-profile/tutorials/order-hub-freshmart/order_intake/main.bal | Implements FTP services to ingest CSV/XML orders and persist them. |
| integrator-default-profile/tutorials/order-hub-freshmart/order_intake/functions.bal | Placeholder file for tutorial scaffold. |
| integrator-default-profile/tutorials/order-hub-freshmart/order_intake/data_mappings.bal | Implements transformations from supplier formats to canonical orders. |
| integrator-default-profile/tutorials/order-hub-freshmart/order_intake/connections.bal | Creates DB client used by order ingestion services. |
| integrator-default-profile/tutorials/order-hub-freshmart/order_intake/config.bal | Declares configurables for DB and FTP connectivity. |
| integrator-default-profile/tutorials/order-hub-freshmart/order_intake/automation.bal | Placeholder file for tutorial scaffold. |
| integrator-default-profile/tutorials/order-hub-freshmart/order_intake/agents.bal | Placeholder file for tutorial scaffold. |
| integrator-default-profile/tutorials/order-hub-freshmart/order_intake/Dependencies.toml | Captures resolved dependencies for the order_intake package. |
| integrator-default-profile/tutorials/order-hub-freshmart/order_intake/Ballerina.toml | Declares package metadata + persist tool config for order_intake. |
| integrator-default-profile/tutorials/order-hub-freshmart/order_intake/.gitignore | Ignores build artifacts and local config for order_intake. |
| integrator-default-profile/tutorials/order-hub-freshmart/daily_summary/types.bal | Defines DB projection type for daily order summaries. |
| integrator-default-profile/tutorials/order-hub-freshmart/daily_summary/persist/dbClient/model.bal | Adds persist model (MySQL) for reading orders/order lines. |
| integrator-default-profile/tutorials/order-hub-freshmart/daily_summary/main.bal | Placeholder file for tutorial scaffold. |
| integrator-default-profile/tutorials/order-hub-freshmart/daily_summary/functions.bal | Placeholder file for tutorial scaffold. |
| integrator-default-profile/tutorials/order-hub-freshmart/daily_summary/data_mappings.bal | Placeholder file for tutorial scaffold. |
| integrator-default-profile/tutorials/order-hub-freshmart/daily_summary/connections.bal | Creates DB + SMTP clients for summary emails. |
| integrator-default-profile/tutorials/order-hub-freshmart/daily_summary/config.bal | Declares configurables for DB and SMTP configuration. |
| integrator-default-profile/tutorials/order-hub-freshmart/daily_summary/automation.bal | Implements the daily summary automation email job. |
| integrator-default-profile/tutorials/order-hub-freshmart/daily_summary/agents.bal | Placeholder file for tutorial scaffold. |
| integrator-default-profile/tutorials/order-hub-freshmart/daily_summary/Dependencies.toml | Captures resolved dependencies for the daily_summary package. |
| integrator-default-profile/tutorials/order-hub-freshmart/daily_summary/Ballerina.toml | Declares package metadata + persist tool config for daily_summary. |
| integrator-default-profile/tutorials/order-hub-freshmart/daily_summary/.gitignore | Ignores build artifacts and local config for daily_summary. |
| integrator-default-profile/tutorials/order-hub-freshmart/README.md | Documents the supplier order ingestion tutorial and how to run it. |
| integrator-default-profile/tutorials/order-hub-freshmart/Ballerina.toml | Defines the order-hub-freshmart workspace packages. |
| integrator-default-profile/tutorials/order-hub-freshmart/.wso2/context.yaml | Adds WSO2 project context metadata for the tutorial. |
| integrator-default-profile/samples/order-management-automation/orderprocessingautomation/types.bal | Defines projection types for placed orders and related entities. |
| integrator-default-profile/samples/order-management-automation/orderprocessingautomation/persist/ordersDB/model.bal | Adds persist model (MySQL) for orders/customers/products. |
| integrator-default-profile/samples/order-management-automation/orderprocessingautomation/main.bal | Placeholder file for sample scaffold. |
| integrator-default-profile/samples/order-management-automation/orderprocessingautomation/functions.bal | Placeholder file for sample scaffold. |
| integrator-default-profile/samples/order-management-automation/orderprocessingautomation/data_mappings.bal | Placeholder file for sample scaffold. |
| integrator-default-profile/samples/order-management-automation/orderprocessingautomation/connections.bal | Creates DB + SMTP clients for the automation sample. |
| integrator-default-profile/samples/order-management-automation/orderprocessingautomation/config.bal | Declares configurables for DB and SMTP configuration. |
| integrator-default-profile/samples/order-management-automation/orderprocessingautomation/automation.bal | Implements scheduled processing of placed orders + email notifications. |
| integrator-default-profile/samples/order-management-automation/orderprocessingautomation/agents.bal | Placeholder file for sample scaffold. |
| integrator-default-profile/samples/order-management-automation/orderprocessingautomation/README.md | Documents the sample, DB setup, configuration, and run steps. |
| integrator-default-profile/samples/order-management-automation/orderprocessingautomation/Dependencies.toml | Captures resolved dependencies for the sample package. |
| integrator-default-profile/samples/order-management-automation/orderprocessingautomation/Ballerina.toml | Declares package metadata + persist tool config for the sample package. |
| integrator-default-profile/samples/order-management-automation/orderprocessingautomation/.gitignore | Ignores build artifacts and local config for the sample package. |
| integrator-default-profile/samples/order-management-automation/Ballerina.toml | Defines the order-management-automation workspace packages. |
| integrator-default-profile/samples/order-management-automation/.choreo/context.yaml | Adds Choreo project context metadata for the sample. |
Comments suppressed due to low confidence (12)
integrator-default-profile/tutorials/social-media/social_media/types.bal:1
- Using
time:Date|()for an optional field is valid but non-idiomatic and harder to read. Prefertime:Date? birthDate;for clarity and consistency with the persist model (which already usestime:Date?).
integrator-default-profile/tutorials/social-media/social_media/types.bal:1 - The exported types
UsersTypeandUserTypeare confusing/inconsistent (plural vs singular) and don’t communicate intent (e.g., details vs identifier). Consider renaming to something likeUser/UserRef(orUserDetails/UserId) to make API payloads clearer.
integrator-default-profile/tutorials/social-media/social_media/types.bal:1 - The exported types
UsersTypeandUserTypeare confusing/inconsistent (plural vs singular) and don’t communicate intent (e.g., details vs identifier). Consider renaming to something likeUser/UserRef(orUserDetails/UserId) to make API payloads clearer.
integrator-default-profile/tutorials/social-media/social_media/persist/dbClient/model.bal:1 - The
Followertable annotations declare duplicate@sql:UniqueIndexnames (leader_id) and makeleaderIdunique, which would prevent a leader from having multiple followers. This is likely to break schema generation and/or enforce incorrect constraints. Consider removing the uniqueness onleaderId, and if uniqueness is required, use a composite unique constraint (leaderId + followerId) with a distinct index name.
integrator-default-profile/tutorials/social-media/social_media/persist/dbClient/model.bal:1 - Fields like
followers1anduser1are ambiguous and will make query results harder to interpret. Prefer descriptive names that reflect the relationship roles (e.g.,leaderFollowers/following,leader/follower) to improve readability and reduce mistakes.
integrator-default-profile/tutorials/social-media/social_media/persist/dbClient/model.bal:1 - Fields like
followers1anduser1are ambiguous and will make query results harder to interpret. Prefer descriptive names that reflect the relationship roles (e.g.,leaderFollowers/following,leader/follower) to improve readability and reduce mistakes.
integrator-default-profile/tutorials/social-media/social_media/Ballerina.toml:1 - The package
distributionversion should align with the generatedDependencies.tomlfor reproducible builds. HereBallerina.tomluses2201.13.3, whilesocial_media/Dependencies.tomlindicatesdistribution-version = \"2201.13.4\". Please regenerate dependencies with the intended distribution, or update the package distribution to match.
integrator-default-profile/tutorials/social-media/post_notifier/main.bal:1 - Slack
chat.postMessagetypically requireschannelto be a channel ID (e.g.,C123...), not a human-readable name, which can cause runtime failures. Also, the message text concatenation misses a space beforejust posted, and the response variable is unused (can be assigned to_if you only need to ensure the call succeeds).
integrator-default-profile/tutorials/order-hub-freshmart/order_intake/persist/dbClient/model.bal:1 supplierCodeis marked with@sql:UniqueIndex {name: \"order_id\"}, which both reuses the index name and incorrectly enforces uniqueness on supplier code. This can block valid inserts (multiple orders from the same supplier) and may conflict with the existing unique constraint onorderId. Consider removing unique constraints fromsupplierCodeand using a properly named non-unique index if needed.
integrator-default-profile/tutorials/order-hub-freshmart/order_intake/data_mappings.bal:1- Indexing
greenFieldRows[0]will cause a runtime panic if the CSV mapping yields an empty array. Consider returning an error (or a typed empty result) when no rows are available, so the FTP handler can move the file to/errorswith a clear reason.
integrator-default-profile/tutorials/order-hub-freshmart/order_intake/data_mappings.bal:1 - Conversion errors from
price/unitsare silently replaced with0, which can produce incorrect order totals while still persisting the order. For ingestion correctness, it’s better to fail the transformation (returnerror) when numeric parsing fails, so the file can be routed to/errorsrather than storing bad financial data.
integrator-default-profile/tutorials/social-media/README.md:1 - The PR description’s Purpose still contains a placeholder (
$subject), which doesn’t match the actual change set (adding multiple tutorial/sample workspaces). Update the PR description to summarize what’s being added and why, so reviewers and release notes have accurate context.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| @sql:Name {value: "supplier_code"} | ||
| @sql:Varchar {length: 32} | ||
| @sql:UniqueIndex {name: "order_id"} | ||
| string supplierCode; |
| check emailSmtpclient->sendMessage({ | ||
| to: "procurement@freshmart.com", | ||
| subject: string `Daily summary : ${date.day}/${date.month}/${date.year}`, | ||
| 'from: "procurementbot@example", | ||
| htmlBody: htmlBody | ||
| }); |
| [ballerina] | ||
| dependencies-toml-version = "2" | ||
| distribution-version = "2201.13.3-20260411-175200-6a2a1e46" |
Purpose
$subject