Store Systems in Mockarty
Table of Contents
- Store Systems Overview
- Mock Store (MStore)
- Chain Store (CStore)
- Global Store (GStore)
- Store Management API
- Usage Examples
- Best Practices
Store Systems Overview
Store Concept
Store is a data storage system in Mockarty that allows you to:
- Save data between mock invocations
- Share data between related mocks
- Accumulate state for complex scenarios
- Create dynamic responses based on accumulated data using JsonPath and Faker
Store Architecture
graph TB
subgraph "Store Hierarchy"
MSTORE[Mock Store - mS]
CSTORE[Chain Store - cS]
GSTORE[Global Store - gS]
end
subgraph "Scope"
MOCK_SCOPE[Single Mock]
CHAIN_SCOPE[Chain of Mocks]
GLOBAL_SCOPE[All Mocks in Namespace]
end
subgraph "Persistence"
SESSION[Session]
PERMANENT[Permanent]
NAMESPACE_ISOLATED[Namespace Isolated]
end
MSTORE --> MOCK_SCOPE
CSTORE --> CHAIN_SCOPE
GSTORE --> GLOBAL_SCOPE
MSTORE --> SESSION
CSTORE --> PERMANENT
GSTORE --> NAMESPACE_ISOLATED
classDef store fill:#e3f2fd
classDef scope fill:#f3e5f5
classDef persistence fill:#e8f5e8
class MSTORE,CSTORE,GSTORE store
class MOCK_SCOPE,CHAIN_SCOPE,GLOBAL_SCOPE scope
class SESSION,PERMANENT,NAMESPACE_ISOLATED persistence
Store Type Comparison
| Store Type | Scope | Lifetime | Namespace | JsonPath Access |
|---|---|---|---|---|
| MStore | Local mock | During mock processing | N/A | $.mS.key |
| CStore | All mocks in Chain | Permanent | Yes | $.cS.key |
| GStore | All mocks in Namespace | Permanent | Yes | $.gS.key |
Mock Store (MStore)
What is Mock Store?
Mock Store (MStore) is a local data storage for a specific mock, available only during the processing of that mock.
Features:
- Isolation – data is accessible only within a specific mock
- Ephemeral – data exists only during request processing
- Fast – stored in mock memory
- Simple – does not require namespace or chainId management
Using MStore
Extracting to MStore
{
"id": "user-create",
"http": {
"route": "/api/users",
"httpMethod": "POST"
},
"response": {
"payload": {
"id": "$.mS.generatedId",
"name": "$.req.name",
"email": "$.req.email",
"clientIP": "$.mS.clientIP",
"userAgent": "$.mS.userAgent"
}
},
"extract": {
"mStore": {
"generatedId": "$.fake.UUIDDigit",
"requestTime": "$.fake.RFC3339",
"clientIP": "$.reqHeader['X-Forwarded-For'][0]",
"userAgent": "$.reqHeader['User-Agent'][0]",
"requestSize": "$.length($.req)"
}
}
}
Accessing MStore in the Response
{
"response": {
"payload": {
"userId": "$.mS.generatedId",
"processedAt": "$.mS.requestTime",
"metadata": {
"clientIP": "$.mS.clientIP",
"userAgent": "$.mS.userAgent",
"requestSize": "$.mS.requestSize"
}
}
}
}
Typical MStore Use Cases
-
Generating related IDs:
"extract": { "mStore": { "userId": "$.fake.UUIDDigit", "profileId": "$.concat('profile-', $.fake.UUIDDigit)", "sessionId": "$.fake.UUID" } } -
Processing request metadata:
"extract": { "mStore": { "timestamp": "$.fake.RFC3339", "requestHash": "$.hash($.req)", "contentLength": "$.length($.req)" } } -
Conditional computations:
"extract": { "mStore": { "discountPercent": "$.req.isVip ? 0.2 : 0.1", "finalPrice": "$.multiply($.req.price, $.subtract(1, $.mS.discountPercent))" } }
Chain Store (CStore)
What is Chain Store?
Chain Store (CStore) is a shared data storage across all mocks with the same chainId within a single namespace.
Features:
- Shared – data is accessible to all mocks in the chain
- Persistent – data is preserved between invocations
- Namespace isolation – data is isolated by namespace
- Accumulation – data accumulates as the chain progresses
CStore Lifecycle
sequenceDiagram
participant M1 as Mock 1
participant CS as Chain Store
participant M2 as Mock 2
participant M3 as Mock 3
M1->>CS: Extract data (step 1)
CS-->>M1: Store updated
M2->>CS: Read data from step 1
CS-->>M2: Return step 1 data
M2->>CS: Extract additional data (step 2)
CS-->>M2: Store updated
M3->>CS: Read data from steps 1 & 2
CS-->>M3: Return accumulated data
M3->>CS: Extract final data (step 3)
CS-->>M3: Store updated (complete)
Using CStore
Initial Mock in the Chain
{
"id": "order-start",
"chainId": "order-processing",
"namespace": "e-commerce",
"http": {
"route": "/api/orders/create",
"httpMethod": "POST"
},
"response": {
"payload": {
"orderId": "$.fake.UUIDDigit",
"status": "created",
"items": "$.req.items"
}
},
"extract": {
"cStore": {
"orderId": "$.fake.UUIDDigit",
"customerId": "$.req.customerId",
"items": "$.req.items",
"totalAmount": "$.sum($.req.items[*].price)",
"createdAt": "$.fake.RFC3339",
"currentStep": "created"
}
}
}
Intermediate Mock in the Chain
{
"id": "order-payment",
"chainId": "order-processing",
"namespace": "e-commerce",
"http": {
"route": "/api/orders/payment",
"httpMethod": "POST"
},
"response": {
"payload": {
"orderId": "$.cS.orderId",
"customerId": "$.cS.customerId",
"amount": "$.cS.totalAmount",
"paymentId": "$.fake.UUIDDigit",
"status": "paid"
}
},
"extract": {
"cStore": {
"paymentId": "$.fake.UUIDDigit",
"paidAt": "$.fake.RFC3339",
"paymentMethod": "$.req.paymentMethod",
"currentStep": "paid"
}
}
}
Final Mock in the Chain
{
"id": "order-fulfill",
"chainId": "order-processing",
"namespace": "e-commerce",
"http": {
"route": "/api/orders/fulfill",
"httpMethod": "POST"
},
"response": {
"payload": {
"orderId": "$.cS.orderId",
"customerId": "$.cS.customerId",
"paymentId": "$.cS.paymentId",
"trackingNumber": "$.fake.Zip",
"estimatedDelivery": "$.fake.FutureDate",
"orderSummary": {
"items": "$.cS.items",
"totalAmount": "$.cS.totalAmount",
"createdAt": "$.cS.createdAt",
"paidAt": "$.cS.paidAt",
"fulfilledAt": "$.fake.RFC3339"
}
}
},
"extract": {
"cStore": {
"trackingNumber": "$.fake.Zip",
"fulfilledAt": "$.fake.RFC3339",
"currentStep": "fulfilled",
"isComplete": true
}
}
}
Chain Store API
Retrieving Chain Store Data
GET /mock/store/chain/{chainId}?namespace=e-commerce
Adding Data to Chain Store
POST /mock/store/chain/order-processing?namespace=e-commerce
Content-Type: application/json
{
"manualStep": "admin-review",
"reviewedBy": "admin-123",
"reviewedAt": "2024-01-01T15:00:00Z"
}
Deleting Data from Chain Store
DELETE /mock/store/chain/order-processing?namespace=e-commerce
Content-Type: application/json
{
"keys": ["temporaryData", "debugInfo"]
}
Global Store (GStore)
What is Global Store?
Global Store (GStore) is a global data storage accessible to all mocks within a single namespace.
Features:
- Global – data is accessible to all mocks in the namespace
- Persistent – data is preserved across all invocations
- Namespace isolation – data is isolated by namespace
- Accumulation – ideal for counters and statistics
Using GStore
Counters and Statistics
{
"id": "api-request-counter",
"namespace": "monitoring",
"http": {
"route": "/api/*"
},
"response": {
"payload": {
"requestId": "$.fake.UUID",
"timestamp": "$.fake.RFC3339",
"stats": {
"totalRequests": "$.increment($.gS.totalRequests || 0)",
"todayRequests": "$.increment($.gS.todayRequests || 0)",
"uniqueUsers": "$.gS.uniqueUsers"
}
}
},
"extract": {
"gStore": {
"totalRequests": "$.increment($.gS.totalRequests || 0)",
"todayRequests": "$.increment($.gS.todayRequests || 0)",
"lastRequestAt": "$.fake.RFC3339",
"uniqueUsers": "$.addToSet($.gS.uniqueUsers || [], $.reqHeader['X-User-ID'][0])"
}
}
}
System Configuration
{
"id": "system-config",
"namespace": "system",
"http": {
"route": "/api/config"
},
"response": {
"payload": {
"config": {
"version": "$.gS.systemVersion",
"maintenanceMode": "$.gS.maintenanceMode",
"features": "$.gS.enabledFeatures",
"lastUpdated": "$.gS.configLastUpdated"
}
}
},
"extract": {
"gStore": {
"configAccessed": "$.increment($.gS.configAccessed || 0)",
"lastConfigAccess": "$.fake.RFC3339"
}
}
}
Global State
{
"id": "feature-toggle",
"namespace": "features",
"http": {
"route": "/api/features/:featureName"
},
"response": {
"payload": {
"feature": "$.pathParam.featureName",
"enabled": "$.gS.features[$.pathParam.featureName].enabled",
"config": "$.gS.features[$.pathParam.featureName].config",
"rolloutPercentage": "$.gS.features[$.pathParam.featureName].rollout"
}
},
"extract": {
"gStore": {
"featureAccessCount": {
"$.pathParam.featureName": "$.increment($.gS.featureAccessCount[$.pathParam.featureName] || 0)"
},
"lastFeatureAccess": "$.fake.RFC3339"
}
}
}
Global Store API
Retrieving Global Store Data
GET /mock/store/global?namespace=monitoring
Adding Data to Global Store
POST /mock/store/global?namespace=monitoring
Content-Type: application/json
{
"systemVersion": "1.2.3",
"maintenanceMode": false,
"enabledFeatures": ["feature-a", "feature-b"],
"configLastUpdated": "2024-01-01T12:00:00Z"
}
Deleting Data from Global Store
DELETE /mock/store/global?namespace=monitoring
Content-Type: application/json
{
"keys": ["oldConfig", "deprecatedFeature"]
}
Store Management API
Full API Reference
For the complete API documentation, see the API Reference.
Global Store Endpoints
| Method | Endpoint | Description |
|---|---|---|
| GET | /mock/store/global |
Get Global Store |
| POST | /mock/store/global |
Add data to Global Store |
| DELETE | /mock/store/global |
Delete keys from Global Store |
Query Parameters:
namespace(optional) – namespace (default: “default”)
Chain Store Endpoints
| Method | Endpoint | Description |
|---|---|---|
| GET | /mock/store/chain/{chainId} |
Get Chain Store |
| POST | /mock/store/chain/{chainId} |
Add data to Chain Store |
| DELETE | /mock/store/chain/{chainId} |
Delete keys from Chain Store |
Path Parameters:
chainId– chain ID
Query Parameters:
namespace(optional) – namespace (default: “default”)
API Call Examples
Initializing Global Store
curl -X POST http://localhost:5770/mock/store/global?namespace=testing \
-H "Content-Type: application/json" \
-d '{
"systemStats": {
"totalRequests": 0,
"totalUsers": 0,
"totalErrors": 0
},
"features": {
"newUI": {"enabled": true, "rollout": 100},
"betaFeature": {"enabled": false, "rollout": 0}
},
"config": {
"version": "1.0.0",
"environment": "testing"
}
}'
Initializing Chain Store
curl -X POST http://localhost:5770/mock/store/chain/user-journey?namespace=testing \
-H "Content-Type: application/json" \
-d '{
"journeyStarted": true,
"startTime": "2024-01-01T10:00:00Z",
"steps": [],
"currentStep": 0
}'
Clearing Store Data
# Clear specific keys from Global Store
curl -X DELETE http://localhost:5770/mock/store/global?namespace=testing \
-H "Content-Type: application/json" \
-d '{"keys": ["tempData", "debugInfo"]}'
# Clear specific keys from Chain Store
curl -X DELETE http://localhost:5770/mock/store/chain/user-journey?namespace=testing \
-H "Content-Type: application/json" \
-d '{"keys": ["tempStep", "debugData"]}'
Usage Examples
Counters and Metrics
Global API Request Counter
{
"id": "api-metrics",
"namespace": "monitoring",
"http": {
"route": "/api/metrics/increment"
},
"response": {
"payload": {
"totalRequests": "$.gS.totalRequests",
"requestsThisHour": "$.gS.requestsThisHour",
"averageResponseTime": "$.gS.avgResponseTime",
"errorRate": "$.gS.errorRate"
}
},
"extract": {
"gStore": {
"totalRequests": "$.increment($.gS.totalRequests || 0)",
"requestsThisHour": "$.increment($.gS.requestsThisHour || 0)",
"lastRequestTime": "$.fake.RFC3339"
}
}
}
User Sessions
{
"id": "user-session",
"namespace": "sessions",
"http": {
"route": "/api/users/session"
},
"response": {
"payload": {
"userId": "$.req.userId",
"sessionId": "$.fake.UUID",
"activeSessions": "$.gS.activeSessions",
"totalSessions": "$.gS.totalSessions"
}
},
"extract": {
"gStore": {
"activeSessions": "$.addToSet($.gS.activeSessions || [], $.req.userId)",
"totalSessions": "$.increment($.gS.totalSessions || 0)",
"lastActivity": "$.fake.RFC3339"
}
}
}
System State
Feature Flags
{
"id": "feature-flags",
"namespace": "features",
"http": {
"route": "/api/features"
},
"response": {
"payload": {
"features": {
"newDashboard": "$.gS.features.newDashboard",
"advancedSearch": "$.gS.features.advancedSearch",
"betaEditor": "$.gS.features.betaEditor"
},
"userSegment": "$.req.segment",
"rolloutConfig": "$.gS.rolloutConfig"
}
},
"extract": {
"gStore": {
"featureRequests": "$.increment($.gS.featureRequests || 0)",
"lastFeatureCheck": "$.fake.RFC3339"
}
}
}
System Health
{
"id": "system-health",
"namespace": "monitoring",
"http": {
"route": "/api/health/detailed"
},
"response": {
"payload": {
"status": "$.gS.systemStatus",
"uptime": "$.gS.systemUptime",
"services": {
"database": "$.gS.services.database",
"redis": "$.gS.services.redis",
"api": "$.gS.services.api"
},
"metrics": {
"requestCount": "$.gS.totalRequests",
"errorCount": "$.gS.totalErrors",
"averageResponseTime": "$.gS.avgResponseTime"
}
}
},
"extract": {
"gStore": {
"healthCheckCount": "$.increment($.gS.healthCheckCount || 0)",
"lastHealthCheck": "$.fake.RFC3339"
}
}
}
Complex Chain Scenarios
Multi-step Workflow
{
"id": "workflow-step-1",
"chainId": "approval-workflow",
"namespace": "workflows",
"http": {
"route": "/api/workflow/submit",
"httpMethod": "POST"
},
"response": {
"payload": {
"workflowId": "$.fake.UUIDDigit",
"status": "submitted",
"submittedBy": "$.req.userId",
"nextStep": "manager-review"
}
},
"extract": {
"cStore": {
"workflowId": "$.fake.UUIDDigit",
"submittedBy": "$.req.userId",
"submittedAt": "$.fake.RFC3339",
"currentStep": "submitted",
"steps": ["submitted"],
"approvalChain": ["manager", "director", "ceo"]
},
"gStore": {
"totalWorkflows": "$.increment($.gS.totalWorkflows || 0)"
}
}
}
{
"id": "workflow-step-2",
"chainId": "approval-workflow",
"namespace": "workflows",
"http": {
"route": "/api/workflow/approve",
"httpMethod": "POST"
},
"response": {
"payload": {
"workflowId": "$.cS.workflowId",
"approvedBy": "$.req.approverId",
"currentStep": "manager-approved",
"nextStep": "director-review",
"progress": {
"completed": "$.append($.cS.steps, 'manager-approved')",
"remaining": "$.cS.approvalChain[1:]",
"percentage": 33
}
}
},
"extract": {
"cStore": {
"managerApprovedBy": "$.req.approverId",
"managerApprovedAt": "$.fake.RFC3339",
"currentStep": "manager-approved",
"steps": "$.append($.cS.steps, 'manager-approved')"
}
}
}
A/B Testing with Stores
Variant Assignment
{
"id": "ab-test-assignment",
"namespace": "experiments",
"http": {
"route": "/api/experiment/assign"
},
"response": {
"payload": {
"userId": "$.req.userId",
"experiment": "new-checkout-flow",
"variant": "$.hash($.req.userId) % 2 == 0 ? 'A' : 'B'",
"assignedAt": "$.fake.RFC3339"
}
},
"extract": {
"gStore": {
"experiments": {
"new-checkout-flow": {
"totalAssignments": "$.increment($.gS.experiments['new-checkout-flow'].totalAssignments || 0)",
"variantA": "$.hash($.req.userId) % 2 == 0 ? $.increment($.gS.experiments['new-checkout-flow'].variantA || 0) : $.gS.experiments['new-checkout-flow'].variantA",
"variantB": "$.hash($.req.userId) % 2 != 0 ? $.increment($.gS.experiments['new-checkout-flow'].variantB || 0) : $.gS.experiments['new-checkout-flow'].variantB"
}
}
}
}
}
Best Practices
Recommendations
-
Use the right Store type for the task:
- MStore – for temporary computations within a mock
- CStore – for passing data between scenario steps
- GStore – for global counters and configuration
-
Structure data in Stores:
"extract": { "gStore": { "users": { "total": "$.increment($.gS.users.total || 0)", "active": "$.gS.users.active || 0", "lastRegistered": "$.fake.RFC3339" }, "stats": { "requests": "$.increment($.gS.stats.requests || 0)", "errors": "$.gS.stats.errors || 0" } } } -
Use meaningful keys:
// Good "userRegistrationCount": "$.increment($.gS.userRegistrationCount || 0)" // Bad "count": "$.increment($.gS.count || 0)" -
Initialize default values:
"totalUsers": "$.increment($.gS.totalUsers || 0)" // With default "totalUsers": "$.increment($.gS.totalUsers)" // Without default -
Group related data:
"extract": { "cStore": { "order": { "id": "$.fake.UUIDDigit", "createdAt": "$.fake.RFC3339", "status": "created" }, "customer": { "id": "$.req.customerId", "email": "$.req.email" } } }
Things to Avoid
- Do not store sensitive data in Stores (passwords, tokens)
- Do not create overly deep nesting (more than 3 levels)
- Do not forget about namespace isolation
- Do not use Stores for simple static responses
- Do not overload Stores with large data objects
Data Management
Cleaning Up Stale Data
{
"id": "cleanup-stores",
"namespace": "maintenance",
"http": {
"route": "/api/maintenance/cleanup"
},
"extract": {
"gStore": {
"tempData": null,
"debugInfo": null,
"lastCleanup": "$.fake.RFC3339",
"cleanupCount": "$.increment($.gS.cleanupCount || 0)"
}
}
}
Archiving Data
{
"id": "archive-data",
"extract": {
"gStore": {
"archived": {
"data": "$.gS.currentData",
"archivedAt": "$.fake.RFC3339"
},
"currentData": null
}
}
}
Use Store systems to create powerful dynamic scenarios with state preservation!
See Also
- JsonPath Guide – query language for accessing and manipulating Store data
- Faker Reference – generate random data to populate Stores
- API Reference – complete REST API for Store management endpoints
- Web UI Guide – manage Stores visually through the web interface
- Webhooks & Callbacks – use Store data in webhook payloads