├── .gitignore
├── Makefile
├── README.md
├── demo
├── commands.md
└── script.md
├── docker-compose-dashboard-enriched-quarkus.yml
├── docker-compose-dashboard.yml
├── docker-compose-kafka.yml
├── docker-compose-pinot-quickstart.yml
├── docker-compose-pinot.yml
├── docker-compose.yml
├── enrichment-bytewax
├── Dockerfile
├── README.md
├── data
│ ├── generate_orders.py
│ ├── orders.jsonl
│ └── products.jsonl
├── dataflow.py
├── dataflow_pre.py
└── requirements.txt
├── enrichment-kafka-streams
├── Dockerfile
├── pom.xml
└── src
│ └── main
│ ├── java
│ └── pizzashop
│ │ ├── deser
│ │ ├── JsonDeserializer.java
│ │ ├── JsonSerializer.java
│ │ ├── OrderItemSerde.java
│ │ └── OrderItemWithContextSerde.java
│ │ ├── models
│ │ ├── CompleteOrder.java
│ │ ├── CompleteOrderItem.java
│ │ ├── HydratedOrder.java
│ │ ├── HydratedOrderItem.java
│ │ ├── Order.java
│ │ ├── OrderItem.java
│ │ ├── OrderItemWithContext.java
│ │ ├── Product.java
│ │ └── UpdatedOrder.java
│ │ └── streams
│ │ └── TopologyProducer.java
│ └── resources
│ └── application.properties
├── images
└── architecture.png
├── mysql
├── data
│ ├── products.csv
│ ├── products.json
│ └── users.csv
├── mysql.cnf
└── mysql_bootstrap.sql
├── orders-service
├── Dockerfile
├── multiseeder.py
├── requirements.txt
└── seeder.py
├── pinot
└── config
│ ├── order_items_enriched
│ ├── schema.json
│ └── table.json
│ ├── orders
│ ├── schema.json
│ └── table.json
│ ├── orders_enriched
│ ├── schema.json
│ └── table.json
│ ├── schema.json
│ └── table.json
├── raw_data
└── .gitkeep
├── scripts
├── add_tables.sh
├── download_products.py
├── requirements.txt
└── scrape_products.py
└── streamlit
├── Dockerfile
├── app.py
├── app_enriched.py
├── app_v1.py
├── requirements.txt
└── schema.json
/.gitignore:
--------------------------------------------------------------------------------
1 | venv
2 | raw_data
3 | .cache
4 | */__pycache__
5 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | all: build run tables info
2 |
3 | build:
4 | #docker compose build --no-cache
5 | docker compose build
6 |
7 | run:
8 | docker compose up -d
9 |
10 | @echo "Waiting for Pinot Controller to be ready..."
11 | @while true; do \
12 | STATUS_CODE=$$(curl -s -o /dev/null -w '%{http_code}' \
13 | 'http://localhost:9000/health'); \
14 | if [ "$$STATUS_CODE" -eq 200 ]; then \
15 | break; \
16 | fi; \
17 | sleep 2; \
18 | echo "Waiting for Pinot Controller..."; \
19 | done
20 | @echo "🍷 Pinot Controller is ready."
21 |
22 | @echo "Waiting for Pinot Broker to be ready..."
23 | @while true; do \
24 | STATUS_CODE=$$(curl -s -o /dev/null -w '%{http_code}' \
25 | 'http://localhost:8099/health'); \
26 | if [ "$$STATUS_CODE" -eq 200 ]; then \
27 | break; \
28 | fi; \
29 | sleep 1; \
30 | echo "Waiting for Pinot Broker..."; \
31 | done
32 | @echo "🍷 Pinot Broker is ready to receive queries."
33 |
34 | @echo "🪲 Waiting for Kafka to be ready..."
35 | @while ! nc -z localhost 9092; do \
36 | sleep 1; \
37 | echo "Waiting for Kafka..."; \
38 | done
39 | @echo "🪲 Kafka is ready."
40 |
41 | tables:
42 | docker exec pinot-controller ./bin/pinot-admin.sh \
43 | AddTable \
44 | -tableConfigFile /config/orders/table.json \
45 | -schemaFile /config/orders/schema.json \
46 | -exec
47 |
48 | sleep 5
49 |
50 | docker exec pinot-controller ./bin/pinot-admin.sh \
51 | AddTable \
52 | -tableConfigFile /config/order_items_enriched/table.json \
53 | -schemaFile /config/order_items_enriched/schema.json \
54 | -exec
55 |
56 | info:
57 | @printf "🍷 Pinot Query UI - \033[4mhttp://localhost:9000\033[0m\n"
58 | @printf "🦝 Redpanda Console - \033[4mhttp://localhost:9080\033[0m\n"
59 | @printf "👑 Streamlit Dashboard - \033[4mhttp://localhost:8502\033[0m\n"
60 |
61 |
62 | stop:
63 | docker compose down -v
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Pizza Shop Demo
2 |
3 | This repository contains the code for the Pizza Shop Demo, showcasing a real-time analytics application using Apache Pinot.
4 |
5 | ## Prerequisites
6 |
7 | - [Docker Desktop](https://www.docker.com/products/docker-desktop): Ensure Docker Desktop is installed and running on your machine before starting the demo.
8 |
9 | 
10 |
11 | ## How to Run the Demo
12 |
13 | To start the demo, execute the following command in your terminal:
14 |
15 | ```bash
16 | make
17 | ```
18 |
19 | After the demo is up and running, you can access the following interfaces in your web browser:
20 |
21 | - **Pinot UI:** [http://localhost:9000](http://localhost:9000)
22 | - **Streamlit Dashboard:** [http://localhost:8502](http://localhost:8502)
23 |
24 | For a detailed explanation of each component in the demo, visit the [documentation page](https://dev.startree.ai/docs/pinot/demo-apps/pizza-shop).
25 |
26 | ## Common Issues
27 |
28 | Occasionally, the `pinot-add-table` service may not return a success code (0) if it creates one table but fails to create the other.
29 | To resolve this issue, you can manually stop the service by running:
30 |
31 | ```bash
32 | docker stop pinot-add-table
33 | ```
34 |
35 | ## Stopping the Demo
36 |
37 | To stop all the services and clean up the resources used by the demo, run:
38 |
39 | ```bash
40 | make stop
41 | ```
42 |
--------------------------------------------------------------------------------
/demo/commands.md:
--------------------------------------------------------------------------------
1 | # Demo Script Commands to Run
2 |
3 | This is the demo for the Real-Time Analytics Stack Demo.
4 |
5 | ## Existing Architecture
6 |
7 | To connect to the MySQL database, run:
8 |
9 | ```bash
10 | docker exec -it mysql mysql -u mysqluser -p
11 | ```
12 |
13 | Execute the following SQL queries to view sample data:
14 |
15 | ```sql
16 | select id, first_name, last_name, email, country
17 | FROM pizzashop.users LIMIT 5;
18 | ```
19 |
20 | ```sql
21 | select id, name, category, price
22 | FROM pizzashop.products LIMIT 5;
23 | ```
24 |
25 | Exit the MySQL prompt:
26 |
27 | ```sql
28 | exit
29 | ```
30 |
31 | ## RTA Architecture
32 |
33 | Consume messages from the `orders` topic using kcat:
34 |
35 | ```bash
36 | kcat -C -b localhost:29092 -t orders -u | jq '.'
37 | ```
38 |
39 | View configuration files using a generic editor or `cat` command:
40 |
41 | ```bash
42 | cat ../pinot/config/orders/schema.json | jq
43 | ```
44 |
45 | ```bash
46 | cat ../pinot/config/orders/table.json | jq
47 | ```
48 |
49 | Access the Pinot UI and execute the following SQL query:
50 |
51 | ```sql
52 | select id, price, productsOrdered, status, totalQuantity, ts, userId
53 | from orders limit 10
54 | ```
55 |
56 | Return to the terminal and consume messages from the `products` topic:
57 |
58 | ```bash
59 | kcat -C -b localhost:29092 -t products -u | jq '.'
60 | ```
61 |
62 | View the `TopologyProducer.java` file:
63 |
64 | ```bash
65 | cat TopologyProducer.java
66 | ```
67 |
68 | Back in the terminal, consume a single message from the `enriched-order-items` topic:
69 |
70 | ```bash
71 | kcat -C -b localhost:29092 -t enriched-order-items -c1 | jq '.'
72 | ```
73 |
74 | View the configuration files for enriched order items:
75 |
76 | ```bash
77 | cat ../pinot/config/order_items_enriched/schema.json | jq
78 | ```
79 |
80 | ```bash
81 | cat ../pinot/config/order_items_enriched/table.json | jq
82 | ```
83 |
84 | Switch to the Pinot UI and execute the following SQL queries:
85 |
86 | ```sql
87 | select *
88 | from order_items_enriched LIMIT 10;
89 | ```
90 |
91 | ```sql
92 | select "product.category" AS category, count(*)
93 | FROM order_items_enriched
94 | WHERE ts > ago('PT5M')
95 | group by category
96 | order by count(*) DESC
97 | ```
98 |
99 | Open the Streamlit dashboard at [http://localhost:8502](http://localhost:8502):
100 |
101 | - Change the amount of data being shown.
102 | - Change the refresh rate.
103 |
104 | Finally, review the Streamlit app code:
105 |
106 | ```bash
107 | cat app_enriched.py
108 | ```
109 |
--------------------------------------------------------------------------------
/demo/script.md:
--------------------------------------------------------------------------------
1 | # Demo Script
2 |
3 | The Pizza Shop Demo shows how to build a real-time dashboard for the operators of a fictional pizza delivery service.
4 |
5 | ## Dependencies
6 |
7 | * [kcat](https://docs.confluent.io/platform/current/app-development/kafkacat-usage.html) - produce, consume, and list topic and partition information for Kafka.
8 | * [jq](https://stedolan.github.io/jq/) - Sed for JSON data
9 |
10 | ## Initial Architecture
11 |
12 | Spin everything up on your machine:
13 |
14 | ```
15 | docker-compose up
16 | ```
17 |
18 | You can navigate to those Docker files to show how we're running each of the components.
19 |
20 | We start with products and users loaded into a MySQL database.
21 | You can query those tables by connecting to the MySQL service:
22 |
23 | ```
24 | docker exec -it mysql mysql -u mysqluser -p
25 | ```
26 |
27 | The password is `mysqlpw`.
28 |
29 | ```sql
30 | SELECT name, description, category, price
31 | FROM pizzashop.products
32 | LIMIT 10;
33 | ```
34 |
35 | ```sql
36 | SELECT id, first_name, last_name, email, country
37 | FROM pizzashop.users
38 | LIMIT 10;
39 | ```
40 |
41 | We also have a stream of orders in Apache Kafka.
42 |
43 | ```bash
44 | kcat -C -b localhost:29092 -t orders | jq '.'
45 | ```
46 |
47 | or
48 |
49 | ```bash
50 | kafkacat -C -b localhost:29092 -t orders | jq '.'
51 | ```
52 |
53 | The code for the data generation is in [orders-service/multiseeder.py)(orders-service/multiseeder.py).
54 |
55 | ## Adding Real-Time Analytics
56 |
57 | We're going to put a Streamlit app on top of this data, but first we need to get a stream of the order items that contains all the product details.
58 | We use Kafka Streams to do that and the code is in [TopologyProducer.java](kafka-streams-quarkus/src/main/java/pizzashop/streams/TopologyProducer.java)
59 |
60 | We flat map the orders and key the resulting stream by product id, join that stream to the products stream, which results in the enriched stream.
61 |
62 | Query the resulting stream:
63 |
64 | ```bash
65 | kcat -C -b localhost:29092 -t enriched-order-items | jq '.'
66 | ```
67 |
68 | or
69 |
70 | ```bash
71 | kafkacat -C -b localhost:29092 -t enriched-order-items | jq '.'
72 | ```
73 |
74 | Both the `orders` and `enriched-order-items` are ingested into Apache Pinot.
75 | You can find the config for the corresponding schema/table config in [pinot/config/orders](pinot/config/orders) and [pinot/config/order_items_enriched](pinot/config/order_items_enriched)
76 |
77 | Navigate to http://localhost:9000 to demo the data in Pinot and write some ad hoc queries.
78 | Below are some examples:
79 |
80 | ```sql
81 | select count(*) FILTER(WHERE ts > ago('PT1M')) AS events1Min,
82 | count(*) FILTER(WHERE ts <= ago('PT1M') AND ts > ago('PT2M')) AS events1Min2Min,
83 | sum("price") FILTER(WHERE ts > ago('PT1M')) AS total1Min,
84 | sum("price") FILTER(WHERE ts <= ago('PT1M') AND ts > ago('PT2M')) AS total1Min2Min
85 | from orders
86 | where ts > ago('PT2M')
87 | limit 1
88 | ```
89 |
90 |
91 | ```sql
92 | SELECT "product.name" AS product,
93 | "product.image" AS image,
94 | distinctcount(orderId) AS orders,
95 | sum("orderItem.quantity") AS quantity
96 | FROM order_items_enriched
97 | where ts > ago('PT2M')
98 | group by product, image
99 | LIMIT 5
100 | ```
101 |
102 | Streamlit is running at http://localhost:8502.
103 | The code for Streamlit is at [streamlit/app_enriched.py](streamlit/app_enriched.py).
--------------------------------------------------------------------------------
/docker-compose-dashboard-enriched-quarkus.yml:
--------------------------------------------------------------------------------
1 | version: "3"
2 | services:
3 | dashboard-enriched:
4 | build: streamlit
5 | restart: unless-stopped
6 | container_name: dashboard-enriched
7 | ports:
8 | - "8502:8501"
9 | depends_on:
10 | - pinot-controller
11 | volumes:
12 | - ./streamlit/app_enriched.py:/workdir/app.py
13 | environment:
14 | - PINOT_SERVER
15 | - PINOT_PORT
16 | kafka-streams-quarkus:
17 | build: kafka-streams-quarkus
18 | restart: unless-stopped
19 | container_name: kafka-streams-quarkus
20 | environment:
21 | - QUARKUS_KAFKA_STREAMS_BOOTSTRAP_SERVERS=kafka:9092
22 | - ORDERS_TOPIC=orders
23 | - PRODUCTS_TOPIC=products
24 | - ENRICHED_ORDERS_TOPIC=enriched-order-items
25 | depends_on:
26 | - kafka
--------------------------------------------------------------------------------
/docker-compose-dashboard.yml:
--------------------------------------------------------------------------------
1 | version: "3"
2 | services:
3 | dashboard:
4 | build: streamlit
5 | restart: unless-stopped
6 | container_name: dashboard
7 | ports:
8 | - "8501:8501"
9 | volumes:
10 | - ./streamlit/app.py:/workdir/app.py
11 | environment:
12 | - PINOT_SERVER
13 | - PINOT_PORT
--------------------------------------------------------------------------------
/docker-compose-kafka.yml:
--------------------------------------------------------------------------------
1 | version: "3.8"
2 |
3 | services:
4 | kafka:
5 | image: docker.io/bitnami/kafka:3.6
6 | hostname: kafka
7 | container_name: kafka
8 | ports:
9 | - "9092:9092"
10 | - "29092:29092"
11 | healthcheck: { test: nc -z localhost 9092, interval: 20s }
12 | environment:
13 | # KRaft settings
14 | - KAFKA_CFG_NODE_ID=0
15 | - KAFKA_CFG_PROCESS_ROLES=controller,broker
16 | - KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=0@kafka:9093
17 | # Listeners
18 | - KAFKA_CFG_LISTENERS=PLAINTEXT://:9092,CONTROLLER://:9093,PLAINTEXT_HOST://:29092
19 | - KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://:9092,PLAINTEXT_HOST://localhost:29092
20 | - KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
21 | - KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER
22 | - KAFKA_CFG_INTER_BROKER_LISTENER_NAME=PLAINTEXT
23 |
24 | orders-service:
25 | build: orders-service
26 | restart: unless-stopped
27 | container_name: orders-service
28 | depends_on:
29 | - mysql
30 | - kafka
31 | environment:
32 | - MYSQL_SERVER=mysql
33 | - KAFKA_BROKER_HOSTNAME=kafka
34 | - KAFKA_BROKER_PORT=9092
35 |
36 | mysql:
37 | image: mysql/mysql-server:8.0.27
38 | hostname: mysql
39 | container_name: mysql
40 | ports:
41 | - "3306:3306"
42 | environment:
43 | - MYSQL_ROOT_PASSWORD=debezium
44 | - MYSQL_USER=mysqluser
45 | - MYSQL_PASSWORD=mysqlpw
46 | volumes:
47 | - ./mysql/mysql.cnf:/etc/mysql/conf.d
48 | - ./mysql/mysql_bootstrap.sql:/docker-entrypoint-initdb.d/mysql_bootstrap.sql
49 | - ./mysql/data:/var/lib/mysql-files/data
50 |
51 | dataflow:
52 | image: enrichment-bytewax
53 | build: enrichment-bytewax
54 | container_name: enrichment-bytewax
55 | depends_on:
56 | - kafka
57 |
58 | console:
59 | hostname: console
60 | container_name: console
61 | image: docker.redpanda.com/redpandadata/console:latest
62 | restart: on-failure
63 | entrypoint: /bin/sh
64 | command: -c "echo \"$$CONSOLE_CONFIG_FILE\" > /tmp/config.yml; /app/console"
65 | environment:
66 | CONFIG_FILEPATH: /tmp/config.yml
67 | CONSOLE_CONFIG_FILE: |
68 | server:
69 | listenPort: 9080
70 | kafka:
71 | brokers: ["kafka:9092"]
72 | schemaRegistry:
73 | enabled: false
74 | urls: ["http://schema-registry:8081"]
75 | connect:
76 | enabled: false
77 | ports:
78 | - "9080:9080"
79 | depends_on:
80 | - kafka
81 |
--------------------------------------------------------------------------------
/docker-compose-pinot-quickstart.yml:
--------------------------------------------------------------------------------
1 | version: "3"
2 | services:
3 | pinot-controller:
4 | image: apachepinot/pinot:0.12.0
5 | command: "QuickStart -type EMPTY"
6 | container_name: "pinot-controller"
7 | restart: unless-stopped
8 | ports:
9 | - "9000:9000"
10 | - "8000:8000"
11 | depends_on:
12 | - zookeeper
13 | pinot-add-table:
14 | image: apachepinot/pinot:0.12.0
15 | container_name: "pinot-add-table"
16 | volumes:
17 | - ./pinot/config:/config
18 | command: "'./bin/pinot-admin.sh AddTable -schemaFile /config/orders/schema.json -tableConfigFile /config/orders/table.json -controllerHost pinot-controller -exec && \
19 | ./bin/pinot-admin.sh AddTable -schemaFile /config/order_items_enriched/schema.json -tableConfigFile /config/order_items_enriched/table.json -controllerHost pinot-controller -exec'"
20 | restart: on-failure
21 | entrypoint: "bash -c"
22 | environment:
23 | - "JAVA_OPTS=-Dpinot.admin.system.exit=true"
24 | depends_on:
25 | - pinot-controller
26 |
--------------------------------------------------------------------------------
/docker-compose-pinot.yml:
--------------------------------------------------------------------------------
1 | version: "3"
2 | services:
3 | pinot-controller:
4 | image: apachepinot/pinot:1.0.0
5 | command: "StartController -zkAddress zookeeper:2181"
6 | container_name: "pinot-controller"
7 | restart: unless-stopped
8 | ports:
9 | - "9000:9000"
10 | depends_on:
11 | - zookeeper
12 | healthcheck: {test: nc -z localhost 9000, interval: 1s}
13 | pinot-broker:
14 | image: apachepinot/pinot:1.0.0
15 | command: "StartBroker -zkAddress zookeeper:2181"
16 | restart: unless-stopped
17 | container_name: "pinot-broker"
18 | ports:
19 | - "8099:8099"
20 | depends_on:
21 | - pinot-controller
22 | pinot-server:
23 | image: apachepinot/pinot:1.0.0
24 | container_name: "pinot-server"
25 | command: "StartServer -zkAddress zookeeper:2181"
26 | restart: unless-stopped
27 | depends_on:
28 | - pinot-broker
29 | pinot-add-table:
30 | image: apachepinot/pinot:1.0.0
31 | container_name: "pinot-add-table"
32 | volumes:
33 | - ./pinot/config:/config
34 | - ./scripts/:/scripts
35 | command: "/scripts/add_tables.sh"
36 | restart: on-failure
37 | entrypoint: "bash -c"
38 | environment:
39 | - "JAVA_OPTS=-Dpinot.admin.system.exit=true"
40 | depends_on:
41 | - pinot-controller
42 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: "3.8"
2 | services:
3 |
4 | mysql:
5 | image: mysql/mysql-server:8.0.27
6 | hostname: mysql
7 | container_name: mysql
8 | ports:
9 | - "3306:3306"
10 | environment:
11 | - MYSQL_ROOT_PASSWORD=debezium
12 | - MYSQL_USER=mysqluser
13 | - MYSQL_PASSWORD=mysqlpw
14 | volumes:
15 | - ./mysql/mysql.cnf:/etc/mysql/conf.d
16 | - ./mysql/mysql_bootstrap.sql:/docker-entrypoint-initdb.d/mysql_bootstrap.sql
17 | - ./mysql/data:/var/lib/mysql-files/data
18 |
19 | zookeeper:
20 | image: confluentinc/cp-zookeeper:7.6.0
21 | hostname: zookeeper
22 | container_name: zookeeper
23 | ports:
24 | - "2181:2181"
25 | environment:
26 | ZOOKEEPER_CLIENT_PORT: 2181
27 | ZOOKEEPER_TICK_TIME: 2000
28 | healthcheck: { test: echo srvr | nc localhost 2181 }
29 |
30 | kafka:
31 | image: confluentinc/cp-kafka:7.6.0
32 | hostname: kafka
33 | container_name: kafka
34 | depends_on:
35 | [ zookeeper ]
36 | ports:
37 | - "29092:29092"
38 | - "9092:9092"
39 | - "9101:9101"
40 | environment:
41 | KAFKA_BROKER_ID: 1
42 | KAFKA_ZOOKEEPER_CONNECT: 'zookeeper:2181'
43 | KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
44 | KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092,PLAINTEXT_HOST://localhost:29092
45 | KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
46 | KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
47 | KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
48 | KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0
49 | KAFKA_TOOLS_LOG4J_LOGLEVEL: ERROR
50 | KAFKA_JMX_PORT: 9101
51 | KAFKA_JMX_HOSTNAME: localhost
52 | healthcheck: { test: nc -z localhost 9092, interval: 1s }
53 |
54 | console:
55 | hostname: console
56 | container_name: console
57 | image: docker.redpanda.com/redpandadata/console:latest
58 | restart: on-failure
59 | entrypoint: /bin/sh
60 | command: -c "echo \"$$CONSOLE_CONFIG_FILE\" > /tmp/config.yml; /app/console"
61 | environment:
62 | CONFIG_FILEPATH: /tmp/config.yml
63 | CONSOLE_CONFIG_FILE: |
64 | server:
65 | listenPort: 9080
66 | kafka:
67 | brokers: ["kafka:9092"]
68 | schemaRegistry:
69 | enabled: false
70 | urls: ["http://schema-registry:8081"]
71 | connect:
72 | enabled: false
73 | ports:
74 | - "9080:9080"
75 | depends_on:
76 | - kafka
77 |
78 | # enrichment:
79 | # build: enrichment-bytewax
80 | # restart: unless-stopped
81 | # image: enrichment-bytewax
82 | # container_name: enrichment-bytewax
83 | # environment:
84 | # - BOOTSTRAP_SERVERS=kafka:9092
85 | # - ORDERS_TOPIC=orders
86 | # - PRODUCTS_TOPIC=products
87 | # - ENRICHED_ORDERS_TOPIC=enriched-order-items
88 | # depends_on:
89 | # - kafka
90 |
91 | enrichment:
92 | build: enrichment-kafka-streams
93 | restart: unless-stopped
94 | container_name: enrichment-kafka-streams
95 | environment:
96 | - QUARKUS_KAFKA_STREAMS_BOOTSTRAP_SERVERS=kafka:9092
97 | - ORDERS_TOPIC=orders
98 | - PRODUCTS_TOPIC=products
99 | - ENRICHED_ORDERS_TOPIC=enriched-order-items
100 | depends_on:
101 | - kafka
102 |
103 | pinot-controller:
104 | image: apachepinot/pinot:1.1.0
105 | command: "StartController -zkAddress zookeeper:2181"
106 | container_name: "pinot-controller"
107 | restart: unless-stopped
108 | ports:
109 | - "9000:9000"
110 | depends_on:
111 | - zookeeper
112 | healthcheck:
113 | test: [ "CMD-SHELL", "curl -f http://localhost:9000/health || exit 1" ]
114 | interval: 30s
115 | timeout: 10s
116 | retries: 3
117 | start_period: 10s
118 | volumes:
119 | - ./pinot/config:/config
120 |
121 | pinot-broker:
122 | image: apachepinot/pinot:1.1.0
123 | command: "StartBroker -zkAddress zookeeper:2181"
124 | restart: unless-stopped
125 | container_name: "pinot-broker"
126 | ports:
127 | - "8099:8099"
128 | depends_on:
129 | pinot-controller:
130 | condition: service_healthy
131 | healthcheck:
132 | test: [ "CMD-SHELL", "curl -f http://localhost:8099/health || exit 1" ]
133 | interval: 30s
134 | timeout: 10s
135 | retries: 3
136 | start_period: 10s
137 |
138 | pinot-server:
139 | image: apachepinot/pinot:1.1.0
140 | container_name: "pinot-server"
141 | command: "StartServer -zkAddress zookeeper:2181"
142 | restart: unless-stopped
143 | depends_on:
144 | pinot-broker:
145 | condition: service_healthy
146 |
147 | dashboard-enriched:
148 | build: streamlit
149 | restart: unless-stopped
150 | container_name: dashboard-enriched
151 | ports:
152 | - "8502:8501"
153 | depends_on:
154 | pinot-controller:
155 | condition: service_healthy
156 | volumes:
157 | - ./streamlit/app_enriched.py:/workdir/app.py
158 | environment:
159 | - PINOT_SERVER
160 | - PINOT_PORT
161 |
162 | orders-service:
163 | build: orders-service
164 | restart: unless-stopped
165 | container_name: orders-service
166 | depends_on:
167 | - mysql
168 | - kafka
169 | environment:
170 | - MYSQL_SERVER=mysql
171 | - KAFKA_BROKER_HOSTNAME=kafka
172 | - KAFKA_BROKER_PORT=9092
--------------------------------------------------------------------------------
/enrichment-bytewax/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.11-slim-bullseye
2 |
3 | RUN apt-get update -y && \
4 | apt-get install -y build-essential && \
5 | apt-get install -y librdkafka-dev
6 |
7 | WORKDIR /bytewax
8 | # Install bytewax and the dependencies you need here
9 |
10 | COPY requirements.txt requirements.txt
11 | COPY dataflow.py dataflow.py
12 | RUN mkdir data
13 | COPY data/products.jsonl data/products.jsonl
14 |
15 | RUN pip install --upgrade pip
16 | RUN python3 --version && pip install -r requirements.txt
17 |
18 | ENV PYTHONUNBUFFERED 1
19 | CMD ["python", "-m", "bytewax.run", "dataflow"]
--------------------------------------------------------------------------------
/enrichment-bytewax/README.md:
--------------------------------------------------------------------------------
1 | # Bytewax Enrichment
2 |
3 | This directory contains files to enrich the stream of items contained in each order. It also contains a dataflow (`dataflow_pre.py`) that can be ran without the rest of the stack to test during development.
4 |
5 | To run the local version, simply run"
6 |
7 | ```bash
8 | pip install -r requirements.txt
9 | python -m bytewax.run dataflow.pre:flow
10 | ```
11 |
12 | ## How it works
13 |
14 | The dataflow will first load the products into memory in a `product_id:product_data` dictionary and then while listening to new orders it will flat map the list of items in the order and then enrich those items from the product data in the dictionary.
15 |
16 | If the products are constantly changing, this could be redesigned to make an initial request from the products database and if a product id is encountered that can't be found in the dictionary, the products could be pulled again.
17 |
18 | ### Generating Orders
19 |
20 | in the `data/` directory you can find the `generate_orders.py` file that is used to generate the `orders.jsonl` file.
21 |
--------------------------------------------------------------------------------
/enrichment-bytewax/data/generate_orders.py:
--------------------------------------------------------------------------------
1 | import random, time
2 | from faker import Faker
3 | from faker.providers import company
4 | import json
5 | import datetime
6 | import uuid
7 | import math
8 | import os
9 |
10 |
11 | # Generate fake users
12 | fake = Faker()
13 | users = []
14 | for i in range(100):
15 | users.append(
16 | {
17 | "id": str(i),
18 | "firstName": fake.first_name(),
19 | "lastName": fake.last_name(),
20 | "email": fake.email(),
21 | "country": fake.country(),
22 | }
23 | )
24 | print(users[:5])
25 |
26 | # Get products
27 | products = [json.loads(line) for line in open("products.jsonl", "r")]
28 | print(products[:5])
29 |
30 | product_prices = [(x["id"], float(x["price"])) for x in products]
31 | print(product_prices[:5])
32 |
33 | orders_to_generate = 1000
34 | orders = []
35 |
36 | while len(orders) < orders_to_generate:
37 |
38 | # Get a random a user and a product to order
39 | number_of_items = random.randint(1, 10)
40 |
41 | items = []
42 | for _ in range(0, number_of_items):
43 | product = random.choice(product_prices)
44 | user = random.choice(users)["id"]
45 | purchase_quantity = random.randint(1, 5)
46 | items.append(
47 | {
48 | "productId": str(product[0]),
49 | "quantity": purchase_quantity,
50 | "price": product[1],
51 | }
52 | )
53 |
54 | prices = [item["quantity"] * item["price"] for item in items]
55 | total_price = round(math.fsum(prices), 2)
56 |
57 | order_event = {
58 | "id": str(uuid.uuid4()),
59 | "createdAt": datetime.datetime.now().isoformat(),
60 | "userId": user,
61 | "status": "PLACED_ORDER",
62 | "price": total_price,
63 | "items": items,
64 | }
65 |
66 | orders.append(order_event)
67 |
68 | # save to jsonl file
69 | with open("orders.jsonl", "w") as file:
70 | for ord in orders:
71 | json_line = json.dumps(ord)
72 | file.write(json_line + "\n")
73 |
--------------------------------------------------------------------------------
/enrichment-bytewax/data/products.jsonl:
--------------------------------------------------------------------------------
1 | {"id": 0, "name": "Paneer & Onion", "description": "Creamy Paneer I Onion", "price": "89", "category": "pizza mania", "image": "https://www.dominos.co.in//files/items/Paneer_Special.jpg", "crusts": ["New Hand Tossed", "New Hand Tossed"], "crustSizes": ["regular"], "prices": {}}
2 | {"id": 1, "name": "Pepsi Black Can", "description": "PEPSI BLACK CAN", "price": "60.00", "category": "beverages", "image": "https://www.dominos.co.in//files/items/pepsi_black.png"}
3 | {"id": 2, "name": "Moroccan Spice Pasta Non Veg", "description": "", "price": "165", "category": "pasta", "image": "https://www.dominos.co.in//files/items/MoroccanPastaNonVeg_N.jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
4 | {"id": 3, "name": "Non Veg Supreme", "description": "Bite into supreme delight of Black Olives, Onions, Grilled Mushrooms, Pepper BBQ Chicken, Peri-Peri Chicken, Grilled Chicken Rashers", "price": "609", "category": "non veg pizzas", "image": "https://www.dominos.co.in//files/items/MicrosoftTeams-image_(13).png", "crusts": ["Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "365", "Medium": "609", "Large": "935"}}
5 | {"id": 4, "name": "Deluxe Veggie", "description": "For a vegetarian looking for a BIG treat that goes easy on the spices, this one's got it all.. The onions, the capsicum, those delectable mushrooms - with paneer and golden corn to top it all.", "price": "385", "category": "veg pizzas", "image": "https://www.dominos.co.in//files/items/Deluxe_Veggie.jpg", "crusts": ["Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "219", "Medium": "385", "Large": "619"}}
6 | {"id": 5, "name": "Taco Mexicana-veg(single)", "description": "Truly irresistible! Crispy taco with a decicious veg patty & creamy sauce", "price": "85", "category": "side orders", "image": "https://www.dominos.co.in//files/items/taco.png", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
7 | {"id": 6, "name": "Cheese N Tomato", "description": "A delectable combination of cheese and juicy tomato", "price": "305", "category": "pizza mania", "image": "https://www.dominos.co.in//files/items/cheese_and_tomato.png", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
8 | {"id": 7, "name": "The 4 Cheese Pizza", "description": "Cheese Overloaded pizza with 4 different varieties of cheese and 4 times the cheese of a normal pizza, including a spicy hit of Ghost", "price": "649", "category": "veg pizzas", "image": "https://www.dominos.co.in//files/items/PIZ0171.jpg", "crusts": ["New Hand Tossed", "Fresh Pan Pizza", "New Hand Tossed", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "355", "Medium": "649", "Large": "979"}}
9 | {"id": 8, "name": "Keema Do Pyaza", "description": "Delicious minced chicken keema topped with crunchy onions on your favourite cheesy pizza", "price": "455", "category": "non veg pizzas", "image": "https://www.dominos.co.in//files/items/updated_keema_do_pyaza.webp", "crusts": ["New Hand Tossed", "Wheat Thin Crust", "New Hand Tossed", "Wheat Thin Crust"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "255", "Medium": "455", "Large": "679"}}
10 | {"id": 9, "name": "Cheese N Corn", "description": "Cheese I Golden Corn | Cheese n Corn Pizza", "price": "305", "category": "veg pizzas", "image": "https://www.dominos.co.in//files/items/Corn_&_Cheese.jpg", "crusts": ["Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "179", "Medium": "319", "Large": "519"}}
11 | {"id": 10, "name": "Brownie Fantasy", "description": "Sweet Temptation! Hot Chocolate Brownie drizzled with chocolate fudge sauce", "price": "59.00", "category": "side orders", "image": "https://www.dominos.co.in//files/items/brownie_fantasy.png", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
12 | {"id": 11, "name": "Crunchy Strips", "description": "Oven baked wheat thin crips with peri peri seasoning with a cheesy dip", "price": "75", "category": "side orders", "image": "https://www.dominos.co.in//files/items/crunchy_strips.png", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
13 | {"id": 12, "name": "Capsicum", "description": "Capsicum", "price": "69", "category": "pizza mania", "image": "https://www.dominos.co.in//files/items/CapsicumVeg.jpg", "crusts": ["New Hand Tossed", "New Hand Tossed"], "crustSizes": ["regular"], "prices": {}}
14 | {"id": 13, "name": "Double Cheese Margherita", "description": "The ever-popular Margherita - loaded with extra cheese... oodies of it!", "price": "385", "category": "veg pizzas", "image": "https://www.dominos.co.in//files/items/Double_Cheese_Margherita.jpg", "crusts": ["Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "215", "Medium": "385", "Large": "619"}}
15 | {"id": 14, "name": "Non Veg Loaded", "description": "Peri - Peri chicken | Pepper Barbecue | Chicken Sausage in a fresh pan crust", "price": "175", "category": "pizza mania", "image": "https://www.dominos.co.in//files/items/LoadedC.jpg", "crusts": [], "crustSizes": ["regular"], "prices": {}}
16 | {"id": 15, "name": "Indi Chicken Tikka", "description": "The wholesome flavour of tandoori masala with Chicken tikka I onion I red paprika I mint mayo", "price": "295", "category": "non veg pizzas", "image": "https://www.dominos.co.in//files/items/MicrosoftTeams-image_(18).png", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "339", "Medium": "599", "Large": "879"}}
17 | {"id": 16, "name": "New Hand Tossed", "description": "Classic Domino's crust. Fresh, hand stretched.", "price": "295", "category": "choice of crusts", "image": "https://www.dominos.co.in//files/items/Crust_272X272.jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
18 | {"id": 17, "name": "Chicken Sausage", "description": "Chicken Sausage & Cheese", "price": "375", "category": "pizza mania", "image": "https://www.dominos.co.in//files/items/MicrosoftTeams-image_(17).png", "crusts": ["New Hand Tossed", "New Hand Tossed"], "crustSizes": ["regular"], "prices": {"Regular": "205", "Medium": "375", "Large": "605"}}
19 | {"id": 18, "name": "Chicken Dominator", "description": "Treat your taste buds with Double Pepper Barbecue Chicken, Peri-Peri Chicken, Chicken Tikka & Grilled Chicken Rashers", "price": "609", "category": "non veg pizzas", "image": "https://www.dominos.co.in//files/items/MicrosoftTeams-image_(11).png", "crusts": ["Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "365", "Medium": "609", "Large": "935"}}
20 | {"id": 19, "name": "Burger Pizza- Classic Veg", "description": "", "price": "125", "category": "burger pizza", "image": "https://www.dominos.co.in//files/items/160790_Burger_Pizza_427X298_Pixel.jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
21 | {"id": 20, "name": "5 Pepper", "description": "Dominos introduces \"5 Peppers\" an exotic new Pizza. Topped with red bell pepper, yellow bell pepper, capsicum, red paprika, jalapeno &\u00a0sprinkled\u00a0with exotic herb", "price": "450", "category": "veg pizzas", "image": "https://www.dominos.co.in//files/items/5_Pepper.jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
22 | {"id": 21, "name": "Mirinda (500ml)", "description": "", "price": "60.00", "category": "beverages", "image": "https://www.dominos.co.in//files/items/mirinda.png"}
23 | {"id": 22, "name": "Stuffed Garlic Bread", "description": "Freshly Baked Garlic Bread stuffed with mozzarella cheese, sweet corns & tangy and spicy jalape\u00f1os", "price": "139", "category": "side orders", "image": "https://www.dominos.co.in//files/items/stuffed-garlic-breadstick_1346070564.webp", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
24 | {"id": 23, "name": "Paneer Paratha Pizza", "description": "An epic fusion of paratha and pizza with melting cheese & soft paneer fillings to satisfy all your indulgent cravings", "price": "215", "category": "paratha pizza", "image": "https://www.dominos.co.in//files/items/paneerparatha.jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
25 | {"id": 24, "name": "Cheese Dip", "description": "A dreamy creamy cheese dip to add that extra tang to your snack.", "price": "25", "category": "side orders", "image": "https://www.dominos.co.in//files/items/_thumb_17450.png", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
26 | {"id": 25, "name": "Burger Pizza- Classic Non Veg", "description": "", "price": "165", "category": "burger pizza", "image": "https://www.dominos.co.in//files/items/Burger_Pizza_Non.jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "", "Medium": ""}}
27 | {"id": 26, "name": "Achari Do Pyaza", "description": "Tangy & spicy achari flavours on a super cheesy onion pizza- as desi as it gets!", "price": "335", "category": "veg pizzas", "image": "https://www.dominos.co.in//files/items/updated_achari_do_pyaza.webp", "crusts": ["New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "185", "Medium": "335", "Large": "559"}}
28 | {"id": 27, "name": "Taco Mexicana Non Veg", "description": "A crispy flaky wrap filled with Hot and Smoky Chicken Patty rolled over a creamy Harissa Sauce.", "price": "175", "category": "side orders", "image": "https://www.dominos.co.in//files/items/Main_Menu-NVG.jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "", "Medium": ""}}
29 | {"id": 28, "name": "Onion", "description": "Onion", "price": "59", "category": "pizza mania", "image": "https://www.dominos.co.in//files/items/onion_veg.jpg", "crusts": ["New Hand Tossed", "New Hand Tossed"], "crustSizes": ["regular"], "prices": {}}
30 | {"id": 29, "name": "Chicken Pepperoni", "description": "A classic American taste! Relish the delectable flavor of Chicken Pepperoni, topped with extra cheese", "price": "365", "category": "non veg pizzas", "image": "https://www.dominos.co.in//files/items/MicrosoftTeams-image_(20).png", "crusts": ["New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "365", "Medium": "609", "Large": "935"}}
31 | {"id": 30, "name": "Paneer Tikka Stuffed Garlic Bread", "description": "Freshly Baked Stuffed Garlic Bread with Cheese, Onion and Paneer Tikka fillings. Comes with a dash of Basil Parsley Sprinkle", "price": "175", "category": "side orders", "image": "https://www.dominos.co.in//files/items/BRD0030.webp", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
32 | {"id": 31, "name": "Indo Fusion Chicken Pizza", "description": "Relish the fusion of 5 of your favorite chicken toppings - Peri Peri Chicken, Chicken Pepperoni, Chicken Tikka, Pepper Barbecue Chicken and Chicken Meatballs", "price": "709", "category": "chicken lovers pizza", "image": "https://www.dominos.co.in//files/items/ind_fus.jpg", "crusts": ["New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "405", "Medium": "709", "Large": "1049"}}
33 | {"id": 32, "name": "Roasted Chicken Wings Peri-peri", "description": "", "price": "175", "category": "chicken", "image": "https://www.dominos.co.in//files/items/Roasted-chicken-192x192.png", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
34 | {"id": 33, "name": "Creamy Tomato Pasta Veg", "description": "", "price": "145", "category": "pasta", "image": "https://www.dominos.co.in//files/items/CreamyTomatoVeg_N_(3).jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
35 | {"id": 34, "name": "Roasted Chicken Wings Classic Hot Sauce", "description": "", "price": "175", "category": "chicken", "image": "https://www.dominos.co.in//files/items/Roasted-chicken-192x192.png", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "", "Medium": ""}}
36 | {"id": 35, "name": "Cheesy", "description": "Orange Cheddar Cheese I Mozzarella", "price": "95", "category": "pizza mania", "image": "https://www.dominos.co.in//files/items/PrimeCheesyL.jpg", "crusts": ["New Hand Tossed", "New Hand Tossed"], "crustSizes": ["regular"], "prices": {}}
37 | {"id": 36, "name": "Crinkle Fries", "description": "Crispy wavy masala coated fries served with a spicy tomato chilli sauce", "price": "75", "category": "side orders", "image": "https://www.dominos.co.in//files/items/crinkle_fries.png", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
38 | {"id": 37, "name": "Margherita", "description": "A hugely popular margherita, with a deliciously tangy single cheese topping", "price": "245", "category": "veg pizzas", "image": "https://www.dominos.co.in//files/items/Margherit.jpg", "crusts": ["Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "109", "Medium": "245", "Large": "455"}}
39 | {"id": 38, "name": "Chicken Pepperoni Stuffed Garlic Bread", "description": "Freshly Baked Garlic Bread stuffed with Delectable Chicken Pepperoni, Cheese and sprinkled with Basil Parsley", "price": "175", "category": "side orders", "image": "https://www.dominos.co.in//files/items/BRD0031.webp", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
40 | {"id": 39, "name": "The 5 Chicken Feast Pizza", "description": "Loaded with 5 different Chicken toppings - grilled Chicken Rashers, Chicken Meatballs, Chicken Tikka, herby Chicken Sausage and flavorful Chicken Keema", "price": "709", "category": "chicken lovers pizza", "image": "https://www.dominos.co.in//files/items/chicken_feast.jpg", "crusts": ["New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "405", "Medium": "709", "Large": "1049"}}
41 | {"id": 40, "name": "Spiced Double Chicken", "description": "Delightful combination of our spicy duo- Pepper Barbecue Chicken and Peri Peri Chicken for Chicken Lovers.", "price": "569", "category": "chicken lovers pizza", "image": "https://www.dominos.co.in//files/items/spiced_doubled.jpg", "crusts": ["New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "315", "Medium": "569", "Large": "845"}}
42 | {"id": 41, "name": "Corn N Cheese Paratha Pizza", "description": "A crazy fusion like never before. A delicious fusion of corn stuffed paratha and cheesy pizza.", "price": "179", "category": "paratha pizza", "image": "https://www.dominos.co.in//files/items/cornncheesepp.jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
43 | {"id": 42, "name": "Red Velvet Lava Cake", "description": "A truly indulgent experience with sweet and rich red velvet cake on a creamy cheese flavoured base to give a burst of flavour in", "price": "145", "category": "side orders", "image": "https://www.dominos.co.in//files/items/CAKE03.jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
44 | {"id": 43, "name": "Chicken Meatballs Peri-peri ", "description": "", "price": "155", "category": "chicken", "image": "https://www.dominos.co.in//files/items/Chicken-Meat-balls-192x192.png", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
45 | {"id": 44, "name": "Boneless Chicken Wings Peri-peri", "description": "", "price": "185", "category": "chicken", "image": "https://www.dominos.co.in//files/items/Boneless-Chicken-wings-192x192.png", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
46 | {"id": 45, "name": "Chicken Parcel", "description": "", "price": "55", "category": "side orders", "image": "https://www.dominos.co.in//files/items/150135_Aha_Non_Veg_439x307-01.jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "", "Medium": ""}}
47 | {"id": 46, "name": "Taco Mexicana Veg", "description": "A crispy flaky wrap filled with Mexican Arancini Bean Patty rolled over a creamy Harissa Sauce.", "price": "145", "category": "side orders", "image": "https://www.dominos.co.in//files/items/Main_Menu-VG.jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
48 | {"id": 47, "name": "Veg Parcel", "description": "", "price": "45", "category": "side orders", "image": "https://www.dominos.co.in//files/items/150135_AHA_Menu_main_1.jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
49 | {"id": 48, "name": "Paneer Makhani", "description": "Paneer and Capsicum on Makhani Sauce", "price": "559", "category": "veg pizzas", "image": "https://www.dominos.co.in//files/items/Paneer_Makhni.jpg", "crusts": ["Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "305", "Medium": "559", "Large": "815"}}
50 | {"id": 49, "name": "Veggie Paradise", "description": "Goldern Corn, Black Olives, Capsicum & Red Paprika", "price": "385", "category": "veg pizzas", "image": "https://www.dominos.co.in//files/items/Digital_Veggie_Paradise_olo_266x265.jpg", "crusts": ["Classic Hand Tossed", "Cheese Burst", "Wheat Thin Crust", "Fresh Pan Pizza", "Classic Hand Tossed", "Cheese Burst", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "239", "Medium": "419", "Large": "629"}}
51 | {"id": 50, "name": "Moroccan Spice Pasta Pizza - Non Veg", "description": "A pizza loaded with a spicy combination of Harissa sauce, Peri Peri chicken chunks and delicious pasta.", "price": "509", "category": "non veg pizzas", "image": "https://www.dominos.co.in//files/items/MoroccanSpicePPNV_N.jpg", "crusts": ["New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium"], "prices": {"Regular": "285", "Medium": "509"}}
52 | {"id": 51, "name": "Potato Cheese Shots", "description": "Crisp and golden outside,flavorful burst of cheese, potato & spice inside", "price": "85", "category": "side orders", "image": "https://www.dominos.co.in//files/items/potato_cheese_shots.png", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
53 | {"id": 52, "name": "Moroccan Spice Pasta Veg", "description": "Instant Fusilli Pasta, Harissa Sauce, Onion, Mushroom, Olives, Parsley sprinkle", "price": "145", "category": "pasta", "image": "https://www.dominos.co.in//files/items/MoroccanPastaVeg_N_(1).jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
54 | {"id": 53, "name": "Mexican Green Wave", "description": "A pizza loaded with crunchy onions, crisp capsicum, juicy tomatoes and jalapeno with a liberal sprinkling of exotic Mexican herbs.", "price": "469", "category": "veg pizzas", "image": "https://www.dominos.co.in//files/items/Mexican_Green_Wave.jpg", "crusts": ["Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "265", "Medium": "469", "Large": "705"}}
55 | {"id": 54, "name": "Creamy Tomato Pasta Non Veg", "description": "Instant Fusilli Pasta, Creamy Culinary Dressing, Onion, Olives, BBQ Pepper Chicken, Parsley sprinkle", "price": "509", "category": "pasta", "image": "https://www.dominos.co.in//files/items/CreamyTomatoNV_N.jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "285", "Medium": "509"}}
56 | {"id": 55, "name": "Burger Pizza- Premium Veg", "description": "", "price": "149", "category": "burger pizza", "image": "https://www.dominos.co.in//files/items/160790_Burger_Pizza_427X298_Pixel.jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "", "Medium": ""}}
57 | {"id": 56, "name": "Pepper Barbecue Chicken", "description": "Pepper Barbecue Chicken I Cheese", "price": "455", "category": "non veg pizzas", "image": "https://www.dominos.co.in//files/items/MicrosoftTeams-image_(15).png", "crusts": ["Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "255", "Medium": "455", "Large": "679"}}
58 | {"id": 57, "name": "Butterscotch Mousse Cake", "description": "A Creamy & Chocolaty indulgence with layers of rich, fluffy Butterscotch Cream and delicious Dark Chocolate Cake, topped with crunchy Dark Chocolate morsels - for a perfect dessert treat!", "price": "109", "category": "side orders", "image": "https://www.dominos.co.in//files/items/170046_BMC_image_for_Website_272X272.jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
59 | {"id": 58, "name": "Fresh Veggie", "description": "Onion & Capsicum", "price": "385", "category": "veg pizzas", "image": "https://www.dominos.co.in//files/items/Fresh_Veggie.jpg", "crusts": ["Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "215", "Medium": "385", "Large": "619"}}
60 | {"id": 59, "name": "Cheese Jalapeno Dip", "description": "A soft creamy cheese dip spiced with jalapeno.", "price": "25", "category": "side orders", "image": "https://www.dominos.co.in//files/items/_thumb_17451.png", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
61 | {"id": 60, "name": "Veg Extravaganza", "description": "A pizza that decidedly staggers under an overload of golden corn, exotic black olives, crunchy onions, crisp capsicum, succulent mushrooms, juicyfresh tomatoes and jalapeno - with extra cheese to go all around.", "price": "450", "category": "veg pizzas", "image": "https://www.dominos.co.in//files/items/Veg_Extravaganz.jpg", "crusts": ["Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "279", "Medium": "499", "Large": "729"}}
62 | {"id": 61, "name": "Golden Corn", "description": "Golden Corn - Sweet Corn Pizza", "price": "75", "category": "pizza mania", "image": "https://www.dominos.co.in//files/items/golden_corn_veg.jpg", "crusts": ["New Hand Tossed", "New Hand Tossed"], "crustSizes": ["regular"], "prices": {}}
63 | {"id": 62, "name": "Farm House", "description": "A pizza that goes ballistic on veggies! Check out this mouth watering overload of crunchy, crisp capsicum, succulent mushrooms and fresh tomatoes", "price": "469", "category": "veg pizzas", "image": "https://www.dominos.co.in//files/items/Farmhouse.jpg", "crusts": ["Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "265", "Medium": "469", "Large": "705"}}
64 | {"id": 63, "name": "Lava Cake", "description": "Filled with delecious molten chocolate inside.", "price": "99", "category": "side orders", "image": "https://www.dominos.co.in//files/items/choco-lava-cake-771.jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
65 | {"id": 64, "name": "Pepper Barbecue Chicken", "description": "Pepper Barbecue Chicken", "price": "455", "category": "pizza mania", "image": "https://www.dominos.co.in//files/items/PepperBarbecueChicken.jpg", "crusts": ["New Hand Tossed", "New Hand Tossed"], "crustSizes": ["regular"], "prices": {"Regular": "255", "Medium": "455", "Large": "679"}}
66 | {"id": 65, "name": "7up (500ml)", "description": "", "price": "60.00", "category": "beverages", "image": "https://www.dominos.co.in//files/items/7up.png"}
67 | {"id": 66, "name": "Pepper Barbecue & Onion", "description": "Pepper Barbecue Chicken I Onion", "price": "385", "category": "non veg pizzas", "image": "https://www.dominos.co.in//files/items/Pepper_Barbeque_&_Onion.jpg", "crusts": ["Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "239", "Medium": "419", "Large": "629"}}
68 | {"id": 67, "name": "Chicken Fiesta", "description": "Grilled Chicken Rashers I Peri-Peri Chicken I Onion I Capsicum", "price": "559", "category": "non veg pizzas", "image": "https://www.dominos.co.in//files/items/MicrosoftTeams-image_(10).png", "crusts": ["Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "315", "Medium": "559", "Large": "829"}}
69 | {"id": 68, "name": "Chicken Golden Delight", "description": "Mmm! Barbeque chicken with a topping of golden corn loaded with extra cheese. Worth its weight in gold!", "price": "450", "category": "non veg pizzas", "image": "https://www.dominos.co.in//files/items/MicrosoftTeams-image_(14).png", "crusts": ["Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "279", "Medium": "499", "Large": "729"}}
70 | {"id": 69, "name": "Tikka Masala Pasta Non Veg", "description": "Instant Fusilli Pasta, Spicy Red dressing, Onion, Chicken Tikka, Parsley sprinkle", "price": "155", "category": "pasta", "image": "https://www.dominos.co.in//files/items/ChickenTikkaMasala_N.jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
71 | {"id": 70, "name": "Peppy Paneer", "description": "Chunky paneer with crisp capsicum and spicy red pepper - quite a mouthful!", "price": "469", "category": "veg pizzas", "image": "https://www.dominos.co.in//files/items/Peppy_Paneer.jpg", "crusts": ["Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "265", "Medium": "419", "Large": "705"}}
72 | {"id": 71, "name": "Moroccan Spice Pasta Pizza - Veg", "description": "A pizza loaded with a spicy combination of Harissa sauce and delicious pasta.", "price": "335", "category": "veg pizzas", "image": "https://www.dominos.co.in//files/items/MoroccanSpicePPVG_N.jpg", "crusts": ["New Hand Tossed", "Wheat Thin Crust", "New Hand Tossed", "Wheat Thin Crust"], "crustSizes": ["regular", "medium"], "prices": {"Regular": "185", "Medium": "335"}}
73 | {"id": 72, "name": "Garlic Breadsticks", "description": "The endearing tang of garlic in breadstics baked to perfection.", "price": "95", "category": "side orders", "image": "https://www.dominos.co.in//files/items/garlic-bread.webp", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
74 | {"id": 73, "name": "Chicken Maximus", "description": "Loaded to the Max with Chicken Tikka, Chicken Keema, Chicken Sausage and a double dose of grilled Chicken Rashers.", "price": "709", "category": "chicken lovers pizza", "image": "https://www.dominos.co.in//files/items/chi_max.jpg", "crusts": ["New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "405", "Medium": "709", "Large": "1049"}}
75 | {"id": 74, "name": "Creamy Tomato Pasta Pizza - Non Veg", "description": "Loaded with a delicious creamy tomato pasta topping , green capsicum, crunchy red and yellow bell peppers and black olives", "price": "509", "category": "non veg pizzas", "image": "https://www.dominos.co.in//files/items/CreamyTomatoPPVG.jpg", "crusts": ["New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium"], "prices": {"Regular": "285", "Medium": "509"}}
76 | {"id": 75, "name": "Tomato", "description": "Juicy tomato in a flavourful combination with cheese I tangy sauce", "price": "59", "category": "pizza mania", "image": "https://www.dominos.co.in//files/items/pizza_mania_tomato.png", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
77 | {"id": 76, "name": "Pepsi (500ml)", "description": "", "price": "60", "category": "beverages", "image": "https://www.dominos.co.in//files/items/pepsi.png"}
78 | {"id": 77, "name": "Chicken Keema Paratha Pizza", "description": "Flavourful & meaty chicken keema paratha and goodness of cheesy pizza coming together in an epic crossover!", "price": "255", "category": "paratha pizza", "image": "https://www.dominos.co.in//files/items/chickenkeemaparatha.jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
79 | {"id": 78, "name": "Indi Tandoori Paneer", "description": "It is hot. It is spicy. It is oh-so-Indian. Tandoori paneer with capsicum I red paprika I mint mayo", "price": "559", "category": "veg pizzas", "image": "https://www.dominos.co.in//files/items/IndianTandooriPaneer.jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "305", "Medium": "559", "Large": "815"}}
80 | {"id": 79, "name": "Tikka Masala Pasta Veg", "description": "", "price": "129", "category": "pasta", "image": "https://www.dominos.co.in//files/items/PaneerTikkaMasala_N.jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
81 | {"id": 80, "name": "Veg Loaded", "description": "Tomato | Grilled Mushroom |Jalapeno |Golden Corn | Beans in a fresh pan crust", "price": "119", "category": "pizza mania", "image": "https://www.dominos.co.in//files/items/PrimeLoadedL.jpg", "crusts": [], "crustSizes": ["regular"], "prices": {}}
82 | {"id": 81, "name": "Lipton Ice Tea (250ml)", "description": "", "price": "50.00", "category": "beverages", "image": "https://www.dominos.co.in//files/items/lipton.png"}
83 |
--------------------------------------------------------------------------------
/enrichment-bytewax/dataflow.py:
--------------------------------------------------------------------------------
1 | import os
2 | from dataclasses import dataclass
3 | from typing import Dict, Any, List, Tuple
4 |
5 | import orjson
6 | from bytewax import operators as op
7 | from bytewax.connectors.kafka import (
8 | KafkaSinkMessage,
9 | KafkaSourceMessage,
10 | operators as kop,
11 | )
12 | from bytewax.dataflow import Dataflow
13 |
14 |
15 | # define product dataclass
16 | @dataclass
17 | class Product:
18 | id: str
19 | name: str
20 | description: str
21 | price: float
22 | category: str
23 | image: str
24 |
25 |
26 | def load_products(file_path: str) -> Dict[int, Product]:
27 | products = {}
28 | with open(file_path, "r") as file:
29 | for line in file:
30 | data = orjson.loads(line)
31 | product = Product(
32 | id=str(data.get("id", 0)), # Provide default values if key is missing
33 | name=data.get("name", "Unknown"),
34 | description=data.get("description", "No description"),
35 | price=data.get("price", "0"),
36 | category=data.get("category", "Unknown category"),
37 | image=data.get("image", "No image available"),
38 | )
39 | products[product.id] = product
40 | return products
41 |
42 |
43 | @dataclass
44 | class OrderItemWithContext:
45 | id: str
46 | item: str
47 | createdAt: str
48 |
49 |
50 | orders_topic = os.getenv("ORDERS_TOPIC", "orders")
51 | enriched_order_items_topic = os.getenv("ENRICHED_ORDERS_TOPIC", "enriched-order-items")
52 | brokers = os.getenv("BOOTSTRAP_SERVERS", "[localhost:29092]").split(",")
53 |
54 |
55 | def extract_items(msg: KafkaSourceMessage) -> List:
56 | json_value = orjson.loads(msg.value)
57 |
58 | result = []
59 | for item in json_value["items"]:
60 | order_item_with_context = OrderItemWithContext(
61 | id=json_value["id"], item=item, createdAt=json_value["createdAt"]
62 | )
63 | result.append((item["productId"], order_item_with_context))
64 | return result
65 |
66 |
67 | def enrich_items(
68 | products: Dict[int, Product],
69 | product_id__order_item: Tuple[str, OrderItemWithContext],
70 | ) -> KafkaSinkMessage:
71 | product_id, order_item = product_id__order_item
72 | product = products[product_id]
73 | result = {
74 | "orderId": order_item.id,
75 | "orderItem": order_item.item,
76 | "createdAt": order_item.createdAt,
77 | "product": product,
78 | }
79 | return KafkaSinkMessage(product_id.encode(), orjson.dumps(result))
80 |
81 |
82 | flow = Dataflow("product-enrichment")
83 | in_orders = kop.input("kafka-in-orders", flow, brokers=brokers, topics=[orders_topic])
84 |
85 | # Inspect errors and crash
86 | op.inspect("inspect-kafka-errors", in_orders.errs).then(op.raises, "kafka-error")
87 | op.inspect("inspect-items", in_orders.oks)
88 |
89 | # Expand order into items
90 | items = op.flat_map("flat_map", in_orders.oks, extract_items)
91 |
92 | # enrich items with product data
93 | products = load_products("data/products.jsonl")
94 | enriched = op.map("enrich", items, lambda order: enrich_items(products, order))
95 |
96 | op.inspect("out", enriched)
97 | kop.output("kafka-out", enriched, brokers=brokers, topic=enriched_order_items_topic)
98 |
--------------------------------------------------------------------------------
/enrichment-bytewax/dataflow_pre.py:
--------------------------------------------------------------------------------
1 | from dataclasses import dataclass
2 | from typing import Dict, Any, List, Tuple
3 |
4 | import orjson
5 | from bytewax import operators as op
6 | from bytewax.dataflow import Dataflow
7 | from bytewax.connectors.stdio import StdOutSink
8 | from bytewax.testing import TestingSource
9 |
10 |
11 | # define product dataclass
12 | @dataclass
13 | class Product:
14 | id: str
15 | name: str
16 | description: str
17 | price: float
18 | category: str
19 | image: str
20 |
21 |
22 | def load_products(file_path: str) -> Dict[int, Product]:
23 | products = {}
24 | with open(file_path, "r") as file:
25 | for line in file:
26 | data = orjson.loads(line)
27 | product = Product(
28 | id=str(data.get("id", 0)),
29 | name=data.get("name", "Unknown"),
30 | description=data.get("description", "No description"),
31 | price=data.get("price", "0"),
32 | category=data.get("category", "Unknown category"),
33 | image=data.get("image", "No image available"),
34 | )
35 | products[product.id] = product
36 | return products
37 |
38 |
39 | # define order item dataclass
40 | @dataclass
41 | class OrderItemWithContext:
42 | id: str
43 | item: str
44 | createdAt: str
45 |
46 |
47 | # take an order and return a list of items
48 | def extract_items(orders: bytes) -> List:
49 | json_value = orjson.loads(orders)
50 |
51 | result = []
52 | for item in json_value["items"]:
53 | order_item_with_context = OrderItemWithContext(
54 | id=json_value["id"], item=item, createdAt=json_value["createdAt"]
55 | )
56 | result.append((item["productId"], order_item_with_context))
57 | return result
58 |
59 |
60 | def enrich_items(
61 | products: Dict[int, Product],
62 | product_id__order_item: Tuple[str, OrderItemWithContext],
63 | ) -> str:
64 | product_id, order_item = product_id__order_item
65 | product = products[product_id]
66 | result = {
67 | "orderId": order_item.id,
68 | "orderItem": order_item.item,
69 | "createdAt": order_item.createdAt,
70 | "product": product,
71 | }
72 | return orjson.dumps(result)
73 |
74 |
75 | flow = Dataflow("product-enrichment")
76 | in_orders = op.input(
77 | "testing-in-orders",
78 | flow,
79 | TestingSource([line for line in open("data/orders.jsonl", "r")]),
80 | )
81 | op.inspect("orders", in_orders)
82 | items = op.flat_map("flat_map", in_orders, extract_items)
83 |
84 | products = load_products("data/products.jsonl")
85 | enriched = op.map("enrich", items, lambda order: enrich_items(products, order))
86 |
87 | op.inspect("joined", enriched)
88 | op.output("print-out", enriched, StdOutSink())
89 |
--------------------------------------------------------------------------------
/enrichment-bytewax/requirements.txt:
--------------------------------------------------------------------------------
1 | confluent-kafka==2.3.0
2 | bytewax==0.18.2
3 | requests==2.31.0
4 | fastavro==1.9.4
5 | orjson==3.9.15
6 | Faker==24.2.0
--------------------------------------------------------------------------------
/enrichment-kafka-streams/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM maven:3.5-jdk-11 AS build
2 | COPY src /usr/src/app/src
3 | COPY pom.xml /usr/src/app
4 | RUN mvn -f /usr/src/app/pom.xml clean package
5 |
6 | FROM registry.access.redhat.com/ubi8/ubi-minimal:8.1
7 |
8 | ARG JAVA_PACKAGE=java-11-openjdk-headless
9 | ARG RUN_JAVA_VERSION=1.3.5
10 |
11 | ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en'
12 |
13 | # Install java and the run-java script
14 | # Also set up permissions for user `1001`
15 | RUN microdnf install openssl curl ca-certificates ${JAVA_PACKAGE} \
16 | && microdnf update \
17 | && microdnf clean all \
18 | && mkdir /deployments \
19 | && chown 1001 /deployments \
20 | && chmod "g+rwX" /deployments \
21 | && chown 1001:root /deployments \
22 | && curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh \
23 | && chown 1001 /deployments/run-java.sh \
24 | && chmod 540 /deployments/run-java.sh \
25 | && echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/lib/security/java.security
26 |
27 | # Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size.
28 | ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
29 |
30 | COPY --from=build /usr/src/app/target/quarkus-app/lib/ /deployments/lib/
31 | COPY --from=build /usr/src/app/target/quarkus-app/*.jar /deployments/
32 | COPY --from=build /usr/src/app/target/quarkus-app/app/ /deployments/app/
33 | COPY --from=build /usr/src/app/target/quarkus-app/quarkus/ /deployments/quarkus/
34 |
35 | EXPOSE 8080
36 | USER 1001
37 |
38 | ENTRYPOINT [ "/deployments/run-java.sh" ]
--------------------------------------------------------------------------------
/enrichment-kafka-streams/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 | pizzashop
6 | pizzashop
7 | 0.0.1
8 |
9 | 3.0.0-M7
10 | 11
11 | 11
12 | quarkus-bom
13 | io.quarkus
14 | 2.13.1.Final
15 | UTF-8
16 | UTF-8
17 |
18 |
19 |
20 |
21 | ${quarkus.platform.group-id}
22 | ${quarkus.platform.artifact-id}
23 | ${quarkus.platform.version}
24 | pom
25 | import
26 |
27 |
28 |
29 |
30 |
31 | io.quarkus
32 | quarkus-resteasy-reactive
33 |
34 |
35 | io.quarkus
36 | quarkus-resteasy-reactive-jackson
37 |
38 |
39 | io.quarkus
40 | quarkus-kafka-streams
41 |
42 |
43 | io.quarkus
44 | quarkus-junit5
45 | test
46 |
47 |
48 | io.rest-assured
49 | rest-assured
50 | test
51 |
52 |
53 | org.apache.kafka
54 | kafka-streams-test-utils
55 | test
56 |
57 |
58 | org.testcontainers
59 | kafka
60 | test
61 |
62 |
63 |
64 |
65 |
66 | ${quarkus.platform.group-id}
67 | quarkus-maven-plugin
68 | ${quarkus.platform.version}
69 |
70 |
71 |
72 | build
73 |
74 |
75 |
76 |
77 |
78 | maven-surefire-plugin
79 | ${surefire-plugin.version}
80 |
81 |
82 | org.jboss.logmanager.LogManager
83 | ${maven.home}
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 | native
92 |
93 |
94 | native
95 |
96 |
97 |
98 | native
99 |
100 |
101 |
102 |
103 | maven-failsafe-plugin
104 | ${surefire-plugin.version}
105 |
106 |
107 |
108 | integration-test
109 | verify
110 |
111 |
112 |
113 | ${project.build.directory}/${project.build.finalName}-runner
114 | org.jboss.logmanager.LogManager
115 | ${maven.home}
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
--------------------------------------------------------------------------------
/enrichment-kafka-streams/src/main/java/pizzashop/deser/JsonDeserializer.java:
--------------------------------------------------------------------------------
1 | package pizzashop.deser;
2 |
3 | import com.fasterxml.jackson.databind.ObjectMapper;
4 | import org.apache.kafka.common.errors.SerializationException;
5 | import org.apache.kafka.common.serialization.Deserializer;
6 |
7 | import java.io.IOException;
8 | import java.util.Map;
9 |
10 | public class JsonDeserializer implements Deserializer {
11 | private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
12 | private Class deserializedClass;
13 |
14 | public JsonDeserializer(Class deserializedClass) {
15 | this.deserializedClass = deserializedClass;
16 | }
17 |
18 | public JsonDeserializer() {
19 | }
20 |
21 | @Override
22 | public void configure(Map configs, boolean isKey) {
23 | if (deserializedClass == null) {
24 | deserializedClass = (Class) configs.get("serializedClass");
25 | }
26 | }
27 |
28 | @Override
29 | public T deserialize(final String topic, final byte[] data) {
30 | if (data == null) {
31 | return null;
32 | }
33 |
34 | try {
35 | return (T) OBJECT_MAPPER.readValue(data, deserializedClass);
36 | } catch (final IOException e) {
37 | throw new SerializationException(e);
38 | }
39 | }
40 |
41 | @Override
42 | public void close() {
43 | Deserializer.super.close();
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/enrichment-kafka-streams/src/main/java/pizzashop/deser/JsonSerializer.java:
--------------------------------------------------------------------------------
1 | package pizzashop.deser;
2 |
3 | import com.fasterxml.jackson.databind.ObjectMapper;
4 | import org.apache.kafka.common.errors.SerializationException;
5 | import org.apache.kafka.common.serialization.Serializer;
6 |
7 | import java.util.Map;
8 |
9 | public class JsonSerializer implements Serializer {
10 | private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
11 |
12 | @Override
13 | public byte[] serialize(final String topic, final T data) {
14 | if (data == null) {
15 | return null;
16 | }
17 |
18 | try {
19 | return OBJECT_MAPPER.writeValueAsBytes(data);
20 | } catch (final Exception e) {
21 | throw new SerializationException("Error serializing JSON message", e);
22 | }
23 | }
24 |
25 | @Override
26 | public void configure(Map configs, boolean isKey) {
27 |
28 | }
29 |
30 | @Override
31 | public void close() {
32 |
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/enrichment-kafka-streams/src/main/java/pizzashop/deser/OrderItemSerde.java:
--------------------------------------------------------------------------------
1 | package pizzashop.deser;
2 |
3 | import org.apache.kafka.common.serialization.Serdes;
4 | import pizzashop.deser.JsonDeserializer;
5 | import pizzashop.deser.JsonSerializer;
6 | import pizzashop.models.OrderItem;
7 |
8 | public class OrderItemSerde extends Serdes.WrapperSerde {
9 | public OrderItemSerde() {
10 | super(new JsonSerializer<>(), new JsonDeserializer<>(OrderItem.class));
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/enrichment-kafka-streams/src/main/java/pizzashop/deser/OrderItemWithContextSerde.java:
--------------------------------------------------------------------------------
1 | package pizzashop.deser;
2 |
3 | import org.apache.kafka.common.serialization.Serdes;
4 | import pizzashop.models.OrderItemWithContext;
5 |
6 | public class OrderItemWithContextSerde extends Serdes.WrapperSerde {
7 | public OrderItemWithContextSerde() {
8 | super(new JsonSerializer<>(), new JsonDeserializer<>(OrderItemWithContext.class));
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/enrichment-kafka-streams/src/main/java/pizzashop/models/CompleteOrder.java:
--------------------------------------------------------------------------------
1 | package pizzashop.models;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | public class CompleteOrder {
7 | public String id;
8 | public String userId;
9 | public String status;
10 | public String createdAt;
11 |
12 | public double price;
13 | public List items = new ArrayList<>();
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/enrichment-kafka-streams/src/main/java/pizzashop/models/CompleteOrderItem.java:
--------------------------------------------------------------------------------
1 | package pizzashop.models;
2 |
3 | public class CompleteOrderItem {
4 | public Product product;
5 | public int quantity;
6 | }
7 |
--------------------------------------------------------------------------------
/enrichment-kafka-streams/src/main/java/pizzashop/models/HydratedOrder.java:
--------------------------------------------------------------------------------
1 | package pizzashop.models;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | public class HydratedOrder {
7 | public String orderId;
8 | public List orderItems = new ArrayList<>();
9 |
10 | public void addOrderItem(HydratedOrderItem item) {
11 | orderItems.add(item);
12 | orderId = item.orderId;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/enrichment-kafka-streams/src/main/java/pizzashop/models/HydratedOrderItem.java:
--------------------------------------------------------------------------------
1 | package pizzashop.models;
2 |
3 | public class HydratedOrderItem {
4 | public String orderId;
5 | public String createdAt;
6 | public Product product;
7 | public OrderItem orderItem;
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/enrichment-kafka-streams/src/main/java/pizzashop/models/Order.java:
--------------------------------------------------------------------------------
1 | package pizzashop.models;
2 |
3 | import java.util.List;
4 |
5 | public class Order {
6 | public Order() {
7 |
8 | }
9 |
10 | public String id;
11 | public String userId;
12 | public String status;
13 | public String createdAt;
14 |
15 | public double price;
16 |
17 | public List items;
18 |
19 | // public int productId;
20 | // public int quantity;
21 | // public double total;
22 | }
23 |
--------------------------------------------------------------------------------
/enrichment-kafka-streams/src/main/java/pizzashop/models/OrderItem.java:
--------------------------------------------------------------------------------
1 | package pizzashop.models;
2 |
3 | public class OrderItem {
4 | public String productId;
5 | public int quantity;
6 | public double price;
7 | }
8 |
--------------------------------------------------------------------------------
/enrichment-kafka-streams/src/main/java/pizzashop/models/OrderItemWithContext.java:
--------------------------------------------------------------------------------
1 | package pizzashop.models;
2 |
3 | public class OrderItemWithContext {
4 | public String orderId;
5 | public String createdAt;
6 | public OrderItem orderItem;
7 | }
8 |
--------------------------------------------------------------------------------
/enrichment-kafka-streams/src/main/java/pizzashop/models/Product.java:
--------------------------------------------------------------------------------
1 | package pizzashop.models;
2 |
3 | // POJO classes
4 | public class Product {
5 | public Product() {
6 |
7 | }
8 |
9 | public String id;
10 | public String name;
11 | public String description;
12 | public String category;
13 | public String image;
14 | public double price;
15 | }
16 |
--------------------------------------------------------------------------------
/enrichment-kafka-streams/src/main/java/pizzashop/models/UpdatedOrder.java:
--------------------------------------------------------------------------------
1 | package pizzashop.models;
2 |
3 | public class UpdatedOrder {
4 | public UpdatedOrder() {
5 |
6 | }
7 |
8 | // public String id;
9 | // public String userId;
10 | // public int productId;
11 | // public int quantity;
12 | // public double total;
13 | // public String status;
14 | // public String createdAt;
15 | //
16 | // public String productName;
17 | // public String productCategory;
18 | // public String productImage;
19 |
20 | //
21 | public Order order;
22 | //
23 | public Product product;
24 | }
25 |
--------------------------------------------------------------------------------
/enrichment-kafka-streams/src/main/java/pizzashop/streams/TopologyProducer.java:
--------------------------------------------------------------------------------
1 | package pizzashop.streams;
2 |
3 | import org.apache.kafka.common.serialization.Serde;
4 | import org.apache.kafka.common.serialization.Serdes;
5 | import org.apache.kafka.streams.KeyValue;
6 | import org.apache.kafka.streams.StreamsBuilder;
7 | import org.apache.kafka.streams.Topology;
8 | import org.apache.kafka.streams.kstream.*;
9 | import pizzashop.deser.JsonDeserializer;
10 | import pizzashop.deser.JsonSerializer;
11 | import pizzashop.deser.OrderItemWithContextSerde;
12 | import pizzashop.models.*;
13 |
14 | import javax.enterprise.context.ApplicationScoped;
15 | import javax.enterprise.inject.Produces;
16 | import java.util.ArrayList;
17 | import java.util.List;
18 |
19 | @ApplicationScoped
20 | public class TopologyProducer {
21 | @Produces
22 | public Topology buildTopology() {
23 | String ordersTopic = System.getenv().getOrDefault("ORDERS_TOPIC", "orders");
24 | String productsTopic = System.getenv().getOrDefault("PRODUCTS_TOPIC", "products");
25 | String enrichedOrderItemsTopic = System.getenv().getOrDefault("ENRICHED_ORDERS_TOPIC", "enriched-order-items");
26 |
27 | final Serde orderSerde = Serdes.serdeFrom(new JsonSerializer<>(), new JsonDeserializer<>(Order.class));
28 | OrderItemWithContextSerde orderItemWithContextSerde = new OrderItemWithContextSerde();
29 | final Serde productSerde = Serdes.serdeFrom(new JsonSerializer<>(),
30 | new JsonDeserializer<>(Product.class));
31 | final Serde hydratedOrderItemsSerde = Serdes.serdeFrom(new JsonSerializer<>(),
32 | new JsonDeserializer<>(HydratedOrderItem.class));
33 |
34 | StreamsBuilder builder = new StreamsBuilder();
35 |
36 | KStream orders = builder.stream(ordersTopic, Consumed.with(Serdes.String(), orderSerde));
37 | KTable products = builder.table(productsTopic, Consumed.with(Serdes.String(), productSerde));
38 |
39 | KStream orderItems = orders.flatMap((key, value) -> {
40 | List> result = new ArrayList<>();
41 | for (OrderItem item : value.items) {
42 | OrderItemWithContext orderItemWithContext = new OrderItemWithContext();
43 | orderItemWithContext.orderId = value.id;
44 | orderItemWithContext.orderItem = item;
45 | orderItemWithContext.createdAt = value.createdAt;
46 | result.add(new KeyValue<>(String.valueOf(item.productId), orderItemWithContext));
47 | }
48 | return result;
49 | });
50 |
51 | orderItems.join(products, (orderItem, product) -> {
52 | HydratedOrderItem hydratedOrderItem = new HydratedOrderItem();
53 | hydratedOrderItem.createdAt = orderItem.createdAt;
54 | hydratedOrderItem.orderId = orderItem.orderId;
55 | hydratedOrderItem.orderItem = orderItem.orderItem;
56 | hydratedOrderItem.product = product;
57 | return hydratedOrderItem;
58 | }, Joined.with(Serdes.String(), orderItemWithContextSerde, productSerde))
59 | .to(enrichedOrderItemsTopic, Produced.with(Serdes.String(), hydratedOrderItemsSerde));
60 |
61 | return builder.build();
62 | }
63 | }
--------------------------------------------------------------------------------
/enrichment-kafka-streams/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | quarkus.kafka-streams.application-id=pizza-shop
2 | quarkus.kafka-streams.topics=products,orders
3 |
4 | # streams options
5 | kafka-streams.cache.max.bytes.buffering=10240
6 | kafka-streams.commit.interval.ms=1000
7 | kafka-streams.metadata.max.age.ms=500
8 | kafka-streams.auto.offset.reset=earliest
9 | kafka-streams.metrics.recording.level=DEBUG
10 | kafka-streams.consumer.heartbeat.interval.ms=200
11 | # Use sub-folder of embedded broker, so it gets cleaned by KafkaResource between re-runs
12 | # This does not work for native tests, manually clean-up /tmp/kafka-streams/temperature-aggregator
13 | %test.kafka-streams.state.dir=target/data/kafka-data/stores
14 |
--------------------------------------------------------------------------------
/images/architecture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/startreedata/pizza-shop-demo/b054ac85925e0033604499caabbe7aed87ed0827/images/architecture.png
--------------------------------------------------------------------------------
/mysql/data/products.csv:
--------------------------------------------------------------------------------
1 | name,description,price,category,image
2 | Moroccan Spice Pasta Pizza - Veg,A pizza loaded with a spicy combination of Harissa sauce and delicious pasta.,335.0,veg pizzas,https://www.dominos.co.in//files/items/MoroccanSpicePPVG_N.jpg
3 | Pepsi (500ml),"",60.0,beverages,https://www.dominos.co.in//files/items/pepsi.png
4 | Pepsi Black Can,PEPSI BLACK CAN,60.0,beverages,https://www.dominos.co.in//files/items/pepsi_black.png
5 | Tikka Masala Pasta Veg,,129.0,pasta,https://www.dominos.co.in//files/items/PaneerTikkaMasala_N.jpg
6 | Veggie Paradise,"Goldern Corn, Black Olives, Capsicum & Red Paprika",385.0,veg pizzas,https://www.dominos.co.in//files/items/Digital_Veggie_Paradise_olo_266x265.jpg
7 | Lipton Ice Tea (250ml),,50.0,beverages,https://www.dominos.co.in//files/items/lipton.png
8 | The 4 Cheese Pizza,"Cheese Overloaded pizza with 4 different varieties of cheese and 4 times the cheese of a normal pizza, including a spicy hit of Ghost",649.0,veg pizzas,https://www.dominos.co.in//files/items/PIZ0171.jpg
9 | Chicken Pepperoni,"A classic American taste! Relish the delectable flavor of Chicken Pepperoni, topped with extra cheese",365.0,non veg pizzas,https://www.dominos.co.in//files/items/MicrosoftTeams-image_(20).png
10 | Stuffed Garlic Bread,"Freshly Baked Garlic Bread stuffed with mozzarella cheese, sweet corns & tangy and spicy jalapeños",139.0,side orders,https://www.dominos.co.in//files/items/stuffed-garlic-breadstick_1346070564.webp
11 | Cheese Dip,A dreamy creamy cheese dip to add that extra tang to your snack.,25.0,side orders,https://www.dominos.co.in//files/items/_thumb_17450.png
12 | Taco Mexicana Non Veg,A crispy flaky wrap filled with Hot and Smoky Chicken Patty rolled over a creamy Harissa Sauce.,175.0,side orders,https://www.dominos.co.in//files/items/Main_Menu-NVG.jpg
13 | Creamy Tomato Pasta Non Veg,"Instant Fusilli Pasta, Creamy Culinary Dressing, Onion, Olives, BBQ Pepper Chicken, Parsley sprinkle",509.0,pasta,https://www.dominos.co.in//files/items/CreamyTomatoNV_N.jpg
14 | Veg Loaded,Tomato | Grilled Mushroom |Jalapeno |Golden Corn | Beans in a fresh pan crust,119.0,pizza mania,https://www.dominos.co.in//files/items/PrimeLoadedL.jpg
15 | Spiced Double Chicken,Delightful combination of our spicy duo- Pepper Barbecue Chicken and Peri Peri Chicken for Chicken Lovers.,569.0,chicken lovers pizza,https://www.dominos.co.in//files/items/spiced_doubled.jpg
16 | Paneer & Onion,Creamy Paneer I Onion,89.0,pizza mania,https://www.dominos.co.in//files/items/Paneer_Special.jpg
17 | Double Cheese Margherita,The ever-popular Margherita - loaded with extra cheese... oodies of it!,385.0,veg pizzas,https://www.dominos.co.in//files/items/Double_Cheese_Margherita.jpg
18 | Roasted Chicken Wings Classic Hot Sauce,,175.0,chicken,https://www.dominos.co.in//files/items/Roasted-chicken-192x192.png
19 | Pepper Barbecue & Onion,Pepper Barbecue Chicken I Onion,385.0,non veg pizzas,https://www.dominos.co.in//files/items/Pepper_Barbeque_&_Onion.jpg
20 | Taco Mexicana Veg,A crispy flaky wrap filled with Mexican Arancini Bean Patty rolled over a creamy Harissa Sauce.,145.0,side orders,https://www.dominos.co.in//files/items/Main_Menu-VG.jpg
21 | Taco Mexicana-veg(single),Truly irresistible! Crispy taco with a decicious veg patty & creamy sauce,85.0,side orders,https://www.dominos.co.in//files/items/taco.png
22 | Veg Parcel,,45.0,side orders,https://www.dominos.co.in//files/items/150135_AHA_Menu_main_1.jpg
23 | Margherita,"A hugely popular margherita, with a deliciously tangy single cheese topping",245.0,veg pizzas,https://www.dominos.co.in//files/items/Margherit.jpg
24 | Indi Tandoori Paneer,It is hot. It is spicy. It is oh-so-Indian. Tandoori paneer with capsicum I red paprika I mint mayo,559.0,veg pizzas,https://www.dominos.co.in//files/items/IndianTandooriPaneer.jpg
25 | Paneer Paratha Pizza,An epic fusion of paratha and pizza with melting cheese & soft paneer fillings to satisfy all your indulgent cravings,215.0,paratha pizza,https://www.dominos.co.in//files/items/paneerparatha.jpg
26 | Red Velvet Lava Cake,A truly indulgent experience with sweet and rich red velvet cake on a creamy cheese flavoured base to give a burst of flavour in,145.0,side orders,https://www.dominos.co.in//files/items/CAKE03.jpg
27 | Indi Chicken Tikka,The wholesome flavour of tandoori masala with Chicken tikka I onion I red paprika I mint mayo,295.0,non veg pizzas,https://www.dominos.co.in//files/items/MicrosoftTeams-image_(18).png
28 | Tomato,Juicy tomato in a flavourful combination with cheese I tangy sauce,59.0,pizza mania,https://www.dominos.co.in//files/items/pizza_mania_tomato.png
29 | Cheesy,Orange Cheddar Cheese I Mozzarella,95.0,pizza mania,https://www.dominos.co.in//files/items/PrimeCheesyL.jpg
30 | Crinkle Fries,Crispy wavy masala coated fries served with a spicy tomato chilli sauce,75.0,side orders,https://www.dominos.co.in//files/items/crinkle_fries.png
31 | Creamy Tomato Pasta Veg,"",145.0,pasta,https://www.dominos.co.in//files/items/CreamyTomatoVeg_N_(3).jpg
32 | Capsicum,Capsicum,69.0,pizza mania,https://www.dominos.co.in//files/items/CapsicumVeg.jpg
33 | Butterscotch Mousse Cake,"A Creamy & Chocolaty indulgence with layers of rich, fluffy Butterscotch Cream and delicious Dark Chocolate Cake, topped with crunchy Dark Chocolate morsels - for a perfect dessert treat!",109.0,side orders,https://www.dominos.co.in//files/items/170046_BMC_image_for_Website_272X272.jpg
34 | Creamy Tomato Pasta Pizza - Non Veg,"Loaded with a delicious creamy tomato pasta topping , green capsicum, crunchy red and yellow bell peppers and black olives",509.0,non veg pizzas,https://www.dominos.co.in//files/items/CreamyTomatoPPVG.jpg
35 | 5 Pepper,"Dominos introduces ""5 Peppers"" an exotic new Pizza. Topped with red bell pepper, yellow bell pepper, capsicum, red paprika, jalapeno & sprinkled with exotic herb",450.0,veg pizzas,https://www.dominos.co.in//files/items/5_Pepper.jpg
36 | Moroccan Spice Pasta Non Veg,,165.0,pasta,https://www.dominos.co.in//files/items/MoroccanPastaNonVeg_N.jpg
37 | 7up (500ml),,60.0,beverages,https://www.dominos.co.in//files/items/7up.png
38 | Achari Do Pyaza,Tangy & spicy achari flavours on a super cheesy onion pizza- as desi as it gets!,335.0,veg pizzas,https://www.dominos.co.in//files/items/updated_achari_do_pyaza.webp
39 | Peppy Paneer,Chunky paneer with crisp capsicum and spicy red pepper - quite a mouthful!,469.0,veg pizzas,https://www.dominos.co.in//files/items/Peppy_Paneer.jpg
40 | Cheese N Corn,Cheese I Golden Corn | Cheese n Corn Pizza,305.0,veg pizzas,https://www.dominos.co.in//files/items/Corn_&_Cheese.jpg
41 | Pepper Barbecue Chicken,Pepper Barbecue Chicken,455.0,pizza mania,https://www.dominos.co.in//files/items/PepperBarbecueChicken.jpg
42 | Cheese Jalapeno Dip,A soft creamy cheese dip spiced with jalapeno.,25.0,side orders,https://www.dominos.co.in//files/items/_thumb_17451.png
43 | Indo Fusion Chicken Pizza,"Relish the fusion of 5 of your favorite chicken toppings - Peri Peri Chicken, Chicken Pepperoni, Chicken Tikka, Pepper Barbecue Chicken and Chicken Meatballs",709.0,chicken lovers pizza,https://www.dominos.co.in//files/items/ind_fus.jpg
44 | Chicken Dominator,"Treat your taste buds with Double Pepper Barbecue Chicken, Peri-Peri Chicken, Chicken Tikka & Grilled Chicken Rashers",609.0,non veg pizzas,https://www.dominos.co.in//files/items/MicrosoftTeams-image_(11).png
45 | Moroccan Spice Pasta Veg,"Instant Fusilli Pasta, Harissa Sauce, Onion, Mushroom, Olives, Parsley sprinkle",145.0,pasta,https://www.dominos.co.in//files/items/MoroccanPastaVeg_N_(1).jpg
46 | Chicken Sausage,Chicken Sausage & Cheese,375.0,pizza mania,https://www.dominos.co.in//files/items/MicrosoftTeams-image_(17).png
47 | Keema Do Pyaza,Delicious minced chicken keema topped with crunchy onions on your favourite cheesy pizza,455.0,non veg pizzas,https://www.dominos.co.in//files/items/updated_keema_do_pyaza.webp
48 | Onion,Onion,59.0,pizza mania,https://www.dominos.co.in//files/items/onion_veg.jpg
49 | Moroccan Spice Pasta Pizza - Non Veg,"A pizza loaded with a spicy combination of Harissa sauce, Peri Peri chicken chunks and delicious pasta.",509.0,non veg pizzas,https://www.dominos.co.in//files/items/MoroccanSpicePPNV_N.jpg
50 | Roasted Chicken Wings Peri-peri,,175.0,chicken,https://www.dominos.co.in//files/items/Roasted-chicken-192x192.png
51 | Burger Pizza- Premium Veg,,149.0,burger pizza,https://www.dominos.co.in//files/items/160790_Burger_Pizza_427X298_Pixel.jpg
52 | Paneer Makhani,Paneer and Capsicum on Makhani Sauce,559.0,veg pizzas,https://www.dominos.co.in//files/items/Paneer_Makhni.jpg
53 | Burger Pizza- Classic Veg,,125.0,burger pizza,https://www.dominos.co.in//files/items/160790_Burger_Pizza_427X298_Pixel.jpg
54 | Potato Cheese Shots,"Crisp and golden outside,flavorful burst of cheese, potato & spice inside",85.0,side orders,https://www.dominos.co.in//files/items/potato_cheese_shots.png
55 | Corn N Cheese Paratha Pizza,A crazy fusion like never before. A delicious fusion of corn stuffed paratha and cheesy pizza.,179.0,paratha pizza,https://www.dominos.co.in//files/items/cornncheesepp.jpg
56 | Cheese N Tomato,A delectable combination of cheese and juicy tomato,305.0,pizza mania,https://www.dominos.co.in//files/items/cheese_and_tomato.png
57 | Tikka Masala Pasta Non Veg,"Instant Fusilli Pasta, Spicy Red dressing, Onion, Chicken Tikka, Parsley sprinkle",155.0,pasta,https://www.dominos.co.in//files/items/ChickenTikkaMasala_N.jpg
58 | Chicken Pepperoni Stuffed Garlic Bread,"Freshly Baked Garlic Bread stuffed with Delectable Chicken Pepperoni, Cheese and sprinkled with Basil Parsley",175.0,side orders,https://www.dominos.co.in//files/items/BRD0031.webp
59 | Golden Corn,Golden Corn - Sweet Corn Pizza,75.0,pizza mania,https://www.dominos.co.in//files/items/golden_corn_veg.jpg
60 | Garlic Breadsticks,The endearing tang of garlic in breadstics baked to perfection.,95.0,side orders,https://www.dominos.co.in//files/items/garlic-bread.webp
61 | The 5 Chicken Feast Pizza,"Loaded with 5 different Chicken toppings - grilled Chicken Rashers, Chicken Meatballs, Chicken Tikka, herby Chicken Sausage and flavorful Chicken Keema",709.0,chicken lovers pizza,https://www.dominos.co.in//files/items/chicken_feast.jpg
62 | Boneless Chicken Wings Peri-peri,,185.0,chicken,https://www.dominos.co.in//files/items/Boneless-Chicken-wings-192x192.png
63 | Crunchy Strips,Oven baked wheat thin crips with peri peri seasoning with a cheesy dip,75.0,side orders,https://www.dominos.co.in//files/items/crunchy_strips.png
64 | Chicken Meatballs Peri-peri ,,155.0,chicken,https://www.dominos.co.in//files/items/Chicken-Meat-balls-192x192.png
65 | Chicken Maximus,"Loaded to the Max with Chicken Tikka, Chicken Keema, Chicken Sausage and a double dose of grilled Chicken Rashers.",709.0,chicken lovers pizza,https://www.dominos.co.in//files/items/chi_max.jpg
66 | Non Veg Loaded,Peri - Peri chicken | Pepper Barbecue | Chicken Sausage in a fresh pan crust,175.0,pizza mania,https://www.dominos.co.in//files/items/LoadedC.jpg
67 | Chicken Fiesta,Grilled Chicken Rashers I Peri-Peri Chicken I Onion I Capsicum,559.0,non veg pizzas,https://www.dominos.co.in//files/items/MicrosoftTeams-image_(10).png
68 | Fresh Veggie,Onion & Capsicum,385.0,veg pizzas,https://www.dominos.co.in//files/items/Fresh_Veggie.jpg
69 | Non Veg Supreme,"Bite into supreme delight of Black Olives, Onions, Grilled Mushrooms, Pepper BBQ Chicken, Peri-Peri Chicken, Grilled Chicken Rashers",609.0,non veg pizzas,https://www.dominos.co.in//files/items/MicrosoftTeams-image_(13).png
70 | Burger Pizza- Classic Non Veg,,165.0,burger pizza,https://www.dominos.co.in//files/items/Burger_Pizza_Non.jpg
71 | New Hand Tossed,"Classic Domino's crust. Fresh, hand stretched.",295.0,choice of crusts,https://www.dominos.co.in//files/items/Crust_272X272.jpg
72 | Mirinda (500ml),,60.0,beverages,https://www.dominos.co.in//files/items/mirinda.png
73 | Deluxe Veggie,"For a vegetarian looking for a BIG treat that goes easy on the spices, this one's got it all.. The onions, the capsicum, those delectable mushrooms - with paneer and golden corn to top it all.",385.0,veg pizzas,https://www.dominos.co.in//files/items/Deluxe_Veggie.jpg
74 | Pepper Barbecue Chicken,Pepper Barbecue Chicken I Cheese,455.0,non veg pizzas,https://www.dominos.co.in//files/items/MicrosoftTeams-image_(15).png
75 | Paneer Tikka Stuffed Garlic Bread,"Freshly Baked Stuffed Garlic Bread with Cheese, Onion and Paneer Tikka fillings. Comes with a dash of Basil Parsley Sprinkle",175.0,side orders,https://www.dominos.co.in//files/items/BRD0030.webp
76 | Chicken Keema Paratha Pizza,Flavourful & meaty chicken keema paratha and goodness of cheesy pizza coming together in an epic crossover!,255.0,paratha pizza,https://www.dominos.co.in//files/items/chickenkeemaparatha.jpg
77 | Brownie Fantasy,Sweet Temptation! Hot Chocolate Brownie drizzled with chocolate fudge sauce,59.0,side orders,https://www.dominos.co.in//files/items/brownie_fantasy.png
78 | Chicken Golden Delight,Mmm! Barbeque chicken with a topping of golden corn loaded with extra cheese. Worth its weight in gold!,450.0,non veg pizzas,https://www.dominos.co.in//files/items/MicrosoftTeams-image_(14).png
79 | Mexican Green Wave,"A pizza loaded with crunchy onions, crisp capsicum, juicy tomatoes and jalapeno with a liberal sprinkling of exotic Mexican herbs.",469.0,veg pizzas,https://www.dominos.co.in//files/items/Mexican_Green_Wave.jpg
80 | Lava Cake,Filled with delecious molten chocolate inside.,99.0,side orders,https://www.dominos.co.in//files/items/choco-lava-cake-771.jpg
81 | Chicken Parcel,,55.0,side orders,https://www.dominos.co.in//files/items/150135_Aha_Non_Veg_439x307-01.jpg
82 | Veg Extravaganza,"A pizza that decidedly staggers under an overload of golden corn, exotic black olives, crunchy onions, crisp capsicum, succulent mushrooms, juicyfresh tomatoes and jalapeno - with extra cheese to go all around.",450.0,veg pizzas,https://www.dominos.co.in//files/items/Veg_Extravaganz.jpg
83 |
--------------------------------------------------------------------------------
/mysql/data/products.json:
--------------------------------------------------------------------------------
1 | {"name": "Paneer & Onion", "description": "Creamy Paneer I Onion", "price": "89", "category": "pizza mania", "image": "https://www.dominos.co.in//files/items/Paneer_Special.jpg", "crusts": ["New Hand Tossed", "New Hand Tossed"], "crustSizes": ["regular"], "prices": {}}
2 | {"name": "Pepsi Black Can", "description": "PEPSI BLACK CAN", "price": "60.00", "category": "beverages", "image": "https://www.dominos.co.in//files/items/pepsi_black.png"}
3 | {"name": "Moroccan Spice Pasta Non Veg", "description": "", "price": "165", "category": "pasta", "image": "https://www.dominos.co.in//files/items/MoroccanPastaNonVeg_N.jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
4 | {"name": "Non Veg Supreme", "description": "Bite into supreme delight of Black Olives, Onions, Grilled Mushrooms, Pepper BBQ Chicken, Peri-Peri Chicken, Grilled Chicken Rashers", "price": "609", "category": "non veg pizzas", "image": "https://www.dominos.co.in//files/items/MicrosoftTeams-image_(13).png", "crusts": ["Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "365", "Medium": "609", "Large": "935"}}
5 | {"name": "Deluxe Veggie", "description": "For a vegetarian looking for a BIG treat that goes easy on the spices, this one's got it all.. The onions, the capsicum, those delectable mushrooms - with paneer and golden corn to top it all.", "price": "385", "category": "veg pizzas", "image": "https://www.dominos.co.in//files/items/Deluxe_Veggie.jpg", "crusts": ["Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "219", "Medium": "385", "Large": "619"}}
6 | {"name": "Taco Mexicana-veg(single)", "description": "Truly irresistible! Crispy taco with a decicious veg patty & creamy sauce", "price": "85", "category": "side orders", "image": "https://www.dominos.co.in//files/items/taco.png", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
7 | {"name": "Cheese N Tomato", "description": "A delectable combination of cheese and juicy tomato", "price": "305", "category": "pizza mania", "image": "https://www.dominos.co.in//files/items/cheese_and_tomato.png", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
8 | {"name": "The 4 Cheese Pizza", "description": "Cheese Overloaded pizza with 4 different varieties of cheese and 4 times the cheese of a normal pizza, including a spicy hit of Ghost", "price": "649", "category": "veg pizzas", "image": "https://www.dominos.co.in//files/items/PIZ0171.jpg", "crusts": ["New Hand Tossed", "Fresh Pan Pizza", "New Hand Tossed", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "355", "Medium": "649", "Large": "979"}}
9 | {"name": "Keema Do Pyaza", "description": "Delicious minced chicken keema topped with crunchy onions on your favourite cheesy pizza", "price": "455", "category": "non veg pizzas", "image": "https://www.dominos.co.in//files/items/updated_keema_do_pyaza.webp", "crusts": ["New Hand Tossed", "Wheat Thin Crust", "New Hand Tossed", "Wheat Thin Crust"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "255", "Medium": "455", "Large": "679"}}
10 | {"name": "Cheese N Corn", "description": "Cheese I Golden Corn | Cheese n Corn Pizza", "price": "305", "category": "veg pizzas", "image": "https://www.dominos.co.in//files/items/Corn_&_Cheese.jpg", "crusts": ["Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "179", "Medium": "319", "Large": "519"}}
11 | {"name": "Brownie Fantasy", "description": "Sweet Temptation! Hot Chocolate Brownie drizzled with chocolate fudge sauce", "price": "59.00", "category": "side orders", "image": "https://www.dominos.co.in//files/items/brownie_fantasy.png", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
12 | {"name": "Crunchy Strips", "description": "Oven baked wheat thin crips with peri peri seasoning with a cheesy dip", "price": "75", "category": "side orders", "image": "https://www.dominos.co.in//files/items/crunchy_strips.png", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
13 | {"name": "Capsicum", "description": "Capsicum", "price": "69", "category": "pizza mania", "image": "https://www.dominos.co.in//files/items/CapsicumVeg.jpg", "crusts": ["New Hand Tossed", "New Hand Tossed"], "crustSizes": ["regular"], "prices": {}}
14 | {"name": "Double Cheese Margherita", "description": "The ever-popular Margherita - loaded with extra cheese... oodies of it!", "price": "385", "category": "veg pizzas", "image": "https://www.dominos.co.in//files/items/Double_Cheese_Margherita.jpg", "crusts": ["Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "215", "Medium": "385", "Large": "619"}}
15 | {"name": "Non Veg Loaded", "description": "Peri - Peri chicken | Pepper Barbecue | Chicken Sausage in a fresh pan crust", "price": "175", "category": "pizza mania", "image": "https://www.dominos.co.in//files/items/LoadedC.jpg", "crusts": [], "crustSizes": ["regular"], "prices": {}}
16 | {"name": "Indi Chicken Tikka", "description": "The wholesome flavour of tandoori masala with Chicken tikka I onion I red paprika I mint mayo", "price": "295", "category": "non veg pizzas", "image": "https://www.dominos.co.in//files/items/MicrosoftTeams-image_(18).png", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "339", "Medium": "599", "Large": "879"}}
17 | {"name": "New Hand Tossed", "description": "Classic Domino's crust. Fresh, hand stretched.", "price": "295", "category": "choice of crusts", "image": "https://www.dominos.co.in//files/items/Crust_272X272.jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
18 | {"name": "Chicken Sausage", "description": "Chicken Sausage & Cheese", "price": "375", "category": "pizza mania", "image": "https://www.dominos.co.in//files/items/MicrosoftTeams-image_(17).png", "crusts": ["New Hand Tossed", "New Hand Tossed"], "crustSizes": ["regular"], "prices": {"Regular": "205", "Medium": "375", "Large": "605"}}
19 | {"name": "Chicken Dominator", "description": "Treat your taste buds with Double Pepper Barbecue Chicken, Peri-Peri Chicken, Chicken Tikka & Grilled Chicken Rashers", "price": "609", "category": "non veg pizzas", "image": "https://www.dominos.co.in//files/items/MicrosoftTeams-image_(11).png", "crusts": ["Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "365", "Medium": "609", "Large": "935"}}
20 | {"name": "Burger Pizza- Classic Veg", "description": "", "price": "125", "category": "burger pizza", "image": "https://www.dominos.co.in//files/items/160790_Burger_Pizza_427X298_Pixel.jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
21 | {"name": "5 Pepper", "description": "Dominos introduces \"5 Peppers\" an exotic new Pizza. Topped with red bell pepper, yellow bell pepper, capsicum, red paprika, jalapeno &\u00a0sprinkled\u00a0with exotic herb", "price": "450", "category": "veg pizzas", "image": "https://www.dominos.co.in//files/items/5_Pepper.jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
22 | {"name": "Mirinda (500ml)", "description": "", "price": "60.00", "category": "beverages", "image": "https://www.dominos.co.in//files/items/mirinda.png"}
23 | {"name": "Stuffed Garlic Bread", "description": "Freshly Baked Garlic Bread stuffed with mozzarella cheese, sweet corns & tangy and spicy jalape\u00f1os", "price": "139", "category": "side orders", "image": "https://www.dominos.co.in//files/items/stuffed-garlic-breadstick_1346070564.webp", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
24 | {"name": "Paneer Paratha Pizza", "description": "An epic fusion of paratha and pizza with melting cheese & soft paneer fillings to satisfy all your indulgent cravings", "price": "215", "category": "paratha pizza", "image": "https://www.dominos.co.in//files/items/paneerparatha.jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
25 | {"name": "Cheese Dip", "description": "A dreamy creamy cheese dip to add that extra tang to your snack.", "price": "25", "category": "side orders", "image": "https://www.dominos.co.in//files/items/_thumb_17450.png", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
26 | {"name": "Burger Pizza- Classic Non Veg", "description": "", "price": "165", "category": "burger pizza", "image": "https://www.dominos.co.in//files/items/Burger_Pizza_Non.jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "", "Medium": ""}}
27 | {"name": "Achari Do Pyaza", "description": "Tangy & spicy achari flavours on a super cheesy onion pizza- as desi as it gets!", "price": "335", "category": "veg pizzas", "image": "https://www.dominos.co.in//files/items/updated_achari_do_pyaza.webp", "crusts": ["New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "185", "Medium": "335", "Large": "559"}}
28 | {"name": "Taco Mexicana Non Veg", "description": "A crispy flaky wrap filled with Hot and Smoky Chicken Patty rolled over a creamy Harissa Sauce.", "price": "175", "category": "side orders", "image": "https://www.dominos.co.in//files/items/Main_Menu-NVG.jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "", "Medium": ""}}
29 | {"name": "Onion", "description": "Onion", "price": "59", "category": "pizza mania", "image": "https://www.dominos.co.in//files/items/onion_veg.jpg", "crusts": ["New Hand Tossed", "New Hand Tossed"], "crustSizes": ["regular"], "prices": {}}
30 | {"name": "Chicken Pepperoni", "description": "A classic American taste! Relish the delectable flavor of Chicken Pepperoni, topped with extra cheese", "price": "365", "category": "non veg pizzas", "image": "https://www.dominos.co.in//files/items/MicrosoftTeams-image_(20).png", "crusts": ["New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "365", "Medium": "609", "Large": "935"}}
31 | {"name": "Paneer Tikka Stuffed Garlic Bread", "description": "Freshly Baked Stuffed Garlic Bread with Cheese, Onion and Paneer Tikka fillings. Comes with a dash of Basil Parsley Sprinkle", "price": "175", "category": "side orders", "image": "https://www.dominos.co.in//files/items/BRD0030.webp", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
32 | {"name": "Indo Fusion Chicken Pizza", "description": "Relish the fusion of 5 of your favorite chicken toppings - Peri Peri Chicken, Chicken Pepperoni, Chicken Tikka, Pepper Barbecue Chicken and Chicken Meatballs", "price": "709", "category": "chicken lovers pizza", "image": "https://www.dominos.co.in//files/items/ind_fus.jpg", "crusts": ["New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "405", "Medium": "709", "Large": "1049"}}
33 | {"name": "Roasted Chicken Wings Peri-peri", "description": "", "price": "175", "category": "chicken", "image": "https://www.dominos.co.in//files/items/Roasted-chicken-192x192.png", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
34 | {"name": "Creamy Tomato Pasta Veg", "description": "", "price": "145", "category": "pasta", "image": "https://www.dominos.co.in//files/items/CreamyTomatoVeg_N_(3).jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
35 | {"name": "Roasted Chicken Wings Classic Hot Sauce", "description": "", "price": "175", "category": "chicken", "image": "https://www.dominos.co.in//files/items/Roasted-chicken-192x192.png", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "", "Medium": ""}}
36 | {"name": "Cheesy", "description": "Orange Cheddar Cheese I Mozzarella", "price": "95", "category": "pizza mania", "image": "https://www.dominos.co.in//files/items/PrimeCheesyL.jpg", "crusts": ["New Hand Tossed", "New Hand Tossed"], "crustSizes": ["regular"], "prices": {}}
37 | {"name": "Crinkle Fries", "description": "Crispy wavy masala coated fries served with a spicy tomato chilli sauce", "price": "75", "category": "side orders", "image": "https://www.dominos.co.in//files/items/crinkle_fries.png", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
38 | {"name": "Margherita", "description": "A hugely popular margherita, with a deliciously tangy single cheese topping", "price": "245", "category": "veg pizzas", "image": "https://www.dominos.co.in//files/items/Margherit.jpg", "crusts": ["Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "109", "Medium": "245", "Large": "455"}}
39 | {"name": "Chicken Pepperoni Stuffed Garlic Bread", "description": "Freshly Baked Garlic Bread stuffed with Delectable Chicken Pepperoni, Cheese and sprinkled with Basil Parsley", "price": "175", "category": "side orders", "image": "https://www.dominos.co.in//files/items/BRD0031.webp", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
40 | {"name": "The 5 Chicken Feast Pizza", "description": "Loaded with 5 different Chicken toppings - grilled Chicken Rashers, Chicken Meatballs, Chicken Tikka, herby Chicken Sausage and flavorful Chicken Keema", "price": "709", "category": "chicken lovers pizza", "image": "https://www.dominos.co.in//files/items/chicken_feast.jpg", "crusts": ["New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "405", "Medium": "709", "Large": "1049"}}
41 | {"name": "Spiced Double Chicken", "description": "Delightful combination of our spicy duo- Pepper Barbecue Chicken and Peri Peri Chicken for Chicken Lovers.", "price": "569", "category": "chicken lovers pizza", "image": "https://www.dominos.co.in//files/items/spiced_doubled.jpg", "crusts": ["New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "315", "Medium": "569", "Large": "845"}}
42 | {"name": "Corn N Cheese Paratha Pizza", "description": "A crazy fusion like never before. A delicious fusion of corn stuffed paratha and cheesy pizza.", "price": "179", "category": "paratha pizza", "image": "https://www.dominos.co.in//files/items/cornncheesepp.jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
43 | {"name": "Red Velvet Lava Cake", "description": "A truly indulgent experience with sweet and rich red velvet cake on a creamy cheese flavoured base to give a burst of flavour in", "price": "145", "category": "side orders", "image": "https://www.dominos.co.in//files/items/CAKE03.jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
44 | {"name": "Chicken Meatballs Peri-peri ", "description": "", "price": "155", "category": "chicken", "image": "https://www.dominos.co.in//files/items/Chicken-Meat-balls-192x192.png", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
45 | {"name": "Boneless Chicken Wings Peri-peri", "description": "", "price": "185", "category": "chicken", "image": "https://www.dominos.co.in//files/items/Boneless-Chicken-wings-192x192.png", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
46 | {"name": "Chicken Parcel", "description": "", "price": "55", "category": "side orders", "image": "https://www.dominos.co.in//files/items/150135_Aha_Non_Veg_439x307-01.jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "", "Medium": ""}}
47 | {"name": "Taco Mexicana Veg", "description": "A crispy flaky wrap filled with Mexican Arancini Bean Patty rolled over a creamy Harissa Sauce.", "price": "145", "category": "side orders", "image": "https://www.dominos.co.in//files/items/Main_Menu-VG.jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
48 | {"name": "Veg Parcel", "description": "", "price": "45", "category": "side orders", "image": "https://www.dominos.co.in//files/items/150135_AHA_Menu_main_1.jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
49 | {"name": "Paneer Makhani", "description": "Paneer and Capsicum on Makhani Sauce", "price": "559", "category": "veg pizzas", "image": "https://www.dominos.co.in//files/items/Paneer_Makhni.jpg", "crusts": ["Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "305", "Medium": "559", "Large": "815"}}
50 | {"name": "Veggie Paradise", "description": "Goldern Corn, Black Olives, Capsicum & Red Paprika", "price": "385", "category": "veg pizzas", "image": "https://www.dominos.co.in//files/items/Digital_Veggie_Paradise_olo_266x265.jpg", "crusts": ["Classic Hand Tossed", "Cheese Burst", "Wheat Thin Crust", "Fresh Pan Pizza", "Classic Hand Tossed", "Cheese Burst", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "239", "Medium": "419", "Large": "629"}}
51 | {"name": "Moroccan Spice Pasta Pizza - Non Veg", "description": "A pizza loaded with a spicy combination of Harissa sauce, Peri Peri chicken chunks and delicious pasta.", "price": "509", "category": "non veg pizzas", "image": "https://www.dominos.co.in//files/items/MoroccanSpicePPNV_N.jpg", "crusts": ["New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium"], "prices": {"Regular": "285", "Medium": "509"}}
52 | {"name": "Potato Cheese Shots", "description": "Crisp and golden outside,flavorful burst of cheese, potato & spice inside", "price": "85", "category": "side orders", "image": "https://www.dominos.co.in//files/items/potato_cheese_shots.png", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
53 | {"name": "Moroccan Spice Pasta Veg", "description": "Instant Fusilli Pasta, Harissa Sauce, Onion, Mushroom, Olives, Parsley sprinkle", "price": "145", "category": "pasta", "image": "https://www.dominos.co.in//files/items/MoroccanPastaVeg_N_(1).jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
54 | {"name": "Mexican Green Wave", "description": "A pizza loaded with crunchy onions, crisp capsicum, juicy tomatoes and jalapeno with a liberal sprinkling of exotic Mexican herbs.", "price": "469", "category": "veg pizzas", "image": "https://www.dominos.co.in//files/items/Mexican_Green_Wave.jpg", "crusts": ["Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "265", "Medium": "469", "Large": "705"}}
55 | {"name": "Creamy Tomato Pasta Non Veg", "description": "Instant Fusilli Pasta, Creamy Culinary Dressing, Onion, Olives, BBQ Pepper Chicken, Parsley sprinkle", "price": "509", "category": "pasta", "image": "https://www.dominos.co.in//files/items/CreamyTomatoNV_N.jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "285", "Medium": "509"}}
56 | {"name": "Burger Pizza- Premium Veg", "description": "", "price": "149", "category": "burger pizza", "image": "https://www.dominos.co.in//files/items/160790_Burger_Pizza_427X298_Pixel.jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "", "Medium": ""}}
57 | {"name": "Pepper Barbecue Chicken", "description": "Pepper Barbecue Chicken I Cheese", "price": "455", "category": "non veg pizzas", "image": "https://www.dominos.co.in//files/items/MicrosoftTeams-image_(15).png", "crusts": ["Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "255", "Medium": "455", "Large": "679"}}
58 | {"name": "Butterscotch Mousse Cake", "description": "A Creamy & Chocolaty indulgence with layers of rich, fluffy Butterscotch Cream and delicious Dark Chocolate Cake, topped with crunchy Dark Chocolate morsels - for a perfect dessert treat!", "price": "109", "category": "side orders", "image": "https://www.dominos.co.in//files/items/170046_BMC_image_for_Website_272X272.jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
59 | {"name": "Fresh Veggie", "description": "Onion & Capsicum", "price": "385", "category": "veg pizzas", "image": "https://www.dominos.co.in//files/items/Fresh_Veggie.jpg", "crusts": ["Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "215", "Medium": "385", "Large": "619"}}
60 | {"name": "Cheese Jalapeno Dip", "description": "A soft creamy cheese dip spiced with jalapeno.", "price": "25", "category": "side orders", "image": "https://www.dominos.co.in//files/items/_thumb_17451.png", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
61 | {"name": "Veg Extravaganza", "description": "A pizza that decidedly staggers under an overload of golden corn, exotic black olives, crunchy onions, crisp capsicum, succulent mushrooms, juicyfresh tomatoes and jalapeno - with extra cheese to go all around.", "price": "450", "category": "veg pizzas", "image": "https://www.dominos.co.in//files/items/Veg_Extravaganz.jpg", "crusts": ["Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "279", "Medium": "499", "Large": "729"}}
62 | {"name": "Golden Corn", "description": "Golden Corn - Sweet Corn Pizza", "price": "75", "category": "pizza mania", "image": "https://www.dominos.co.in//files/items/golden_corn_veg.jpg", "crusts": ["New Hand Tossed", "New Hand Tossed"], "crustSizes": ["regular"], "prices": {}}
63 | {"name": "Farm House", "description": "A pizza that goes ballistic on veggies! Check out this mouth watering overload of crunchy, crisp capsicum, succulent mushrooms and fresh tomatoes", "price": "469", "category": "veg pizzas", "image": "https://www.dominos.co.in//files/items/Farmhouse.jpg", "crusts": ["Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "265", "Medium": "469", "Large": "705"}}
64 | {"name": "Lava Cake", "description": "Filled with delecious molten chocolate inside.", "price": "99", "category": "side orders", "image": "https://www.dominos.co.in//files/items/choco-lava-cake-771.jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
65 | {"name": "Pepper Barbecue Chicken", "description": "Pepper Barbecue Chicken", "price": "455", "category": "pizza mania", "image": "https://www.dominos.co.in//files/items/PepperBarbecueChicken.jpg", "crusts": ["New Hand Tossed", "New Hand Tossed"], "crustSizes": ["regular"], "prices": {"Regular": "255", "Medium": "455", "Large": "679"}}
66 | {"name": "7up (500ml)", "description": "", "price": "60.00", "category": "beverages", "image": "https://www.dominos.co.in//files/items/7up.png"}
67 | {"name": "Pepper Barbecue & Onion", "description": "Pepper Barbecue Chicken I Onion", "price": "385", "category": "non veg pizzas", "image": "https://www.dominos.co.in//files/items/Pepper_Barbeque_&_Onion.jpg", "crusts": ["Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "239", "Medium": "419", "Large": "629"}}
68 | {"name": "Chicken Fiesta", "description": "Grilled Chicken Rashers I Peri-Peri Chicken I Onion I Capsicum", "price": "559", "category": "non veg pizzas", "image": "https://www.dominos.co.in//files/items/MicrosoftTeams-image_(10).png", "crusts": ["Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "315", "Medium": "559", "Large": "829"}}
69 | {"name": "Chicken Golden Delight", "description": "Mmm! Barbeque chicken with a topping of golden corn loaded with extra cheese. Worth its weight in gold!", "price": "450", "category": "non veg pizzas", "image": "https://www.dominos.co.in//files/items/MicrosoftTeams-image_(14).png", "crusts": ["Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "279", "Medium": "499", "Large": "729"}}
70 | {"name": "Tikka Masala Pasta Non Veg", "description": "Instant Fusilli Pasta, Spicy Red dressing, Onion, Chicken Tikka, Parsley sprinkle", "price": "155", "category": "pasta", "image": "https://www.dominos.co.in//files/items/ChickenTikkaMasala_N.jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
71 | {"name": "Peppy Paneer", "description": "Chunky paneer with crisp capsicum and spicy red pepper - quite a mouthful!", "price": "469", "category": "veg pizzas", "image": "https://www.dominos.co.in//files/items/Peppy_Paneer.jpg", "crusts": ["Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "Classic Hand Tossed", "Cheese Burst", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "265", "Medium": "419", "Large": "705"}}
72 | {"name": "Moroccan Spice Pasta Pizza - Veg", "description": "A pizza loaded with a spicy combination of Harissa sauce and delicious pasta.", "price": "335", "category": "veg pizzas", "image": "https://www.dominos.co.in//files/items/MoroccanSpicePPVG_N.jpg", "crusts": ["New Hand Tossed", "Wheat Thin Crust", "New Hand Tossed", "Wheat Thin Crust"], "crustSizes": ["regular", "medium"], "prices": {"Regular": "185", "Medium": "335"}}
73 | {"name": "Garlic Breadsticks", "description": "The endearing tang of garlic in breadstics baked to perfection.", "price": "95", "category": "side orders", "image": "https://www.dominos.co.in//files/items/garlic-bread.webp", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
74 | {"name": "Chicken Maximus", "description": "Loaded to the Max with Chicken Tikka, Chicken Keema, Chicken Sausage and a double dose of grilled Chicken Rashers.", "price": "709", "category": "chicken lovers pizza", "image": "https://www.dominos.co.in//files/items/chi_max.jpg", "crusts": ["New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "405", "Medium": "709", "Large": "1049"}}
75 | {"name": "Creamy Tomato Pasta Pizza - Non Veg", "description": "Loaded with a delicious creamy tomato pasta topping , green capsicum, crunchy red and yellow bell peppers and black olives", "price": "509", "category": "non veg pizzas", "image": "https://www.dominos.co.in//files/items/CreamyTomatoPPVG.jpg", "crusts": ["New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza", "New Hand Tossed", "Wheat Thin Crust", "Fresh Pan Pizza"], "crustSizes": ["regular", "medium"], "prices": {"Regular": "285", "Medium": "509"}}
76 | {"name": "Tomato", "description": "Juicy tomato in a flavourful combination with cheese I tangy sauce", "price": "59", "category": "pizza mania", "image": "https://www.dominos.co.in//files/items/pizza_mania_tomato.png", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
77 | {"name": "Pepsi (500ml)", "description": "", "price": "60", "category": "beverages", "image": "https://www.dominos.co.in//files/items/pepsi.png"}
78 | {"name": "Chicken Keema Paratha Pizza", "description": "Flavourful & meaty chicken keema paratha and goodness of cheesy pizza coming together in an epic crossover!", "price": "255", "category": "paratha pizza", "image": "https://www.dominos.co.in//files/items/chickenkeemaparatha.jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
79 | {"name": "Indi Tandoori Paneer", "description": "It is hot. It is spicy. It is oh-so-Indian. Tandoori paneer with capsicum I red paprika I mint mayo", "price": "559", "category": "veg pizzas", "image": "https://www.dominos.co.in//files/items/IndianTandooriPaneer.jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {"Regular": "305", "Medium": "559", "Large": "815"}}
80 | {"name": "Tikka Masala Pasta Veg", "description": "", "price": "129", "category": "pasta", "image": "https://www.dominos.co.in//files/items/PaneerTikkaMasala_N.jpg", "crusts": [], "crustSizes": ["regular", "medium", "large"], "prices": {}}
81 | {"name": "Veg Loaded", "description": "Tomato | Grilled Mushroom |Jalapeno |Golden Corn | Beans in a fresh pan crust", "price": "119", "category": "pizza mania", "image": "https://www.dominos.co.in//files/items/PrimeLoadedL.jpg", "crusts": [], "crustSizes": ["regular"], "prices": {}}
82 | {"name": "Lipton Ice Tea (250ml)", "description": "", "price": "50.00", "category": "beverages", "image": "https://www.dominos.co.in//files/items/lipton.png"}
83 |
--------------------------------------------------------------------------------
/mysql/data/users.csv:
--------------------------------------------------------------------------------
1 | firstName,lastName,email,country
2 | Waldo,Morteo,wmorteo0@toplist.cz,Benin
3 | Anselm,Tabbernor,atabbernor1@biglobe.ne.jp,Ukraine
4 | Jane,Razoux,jrazoux2@webnode.com,Ukraine
5 | Xavier,Adamski,xadamski3@free.fr,Indonesia
6 | Adan,Griffith,agriffith4@rambler.ru,Indonesia
7 | Lea,Queenborough,lqueenborough5@toplist.cz,United States
8 | Diandra,Nadin,dnadin6@cnet.com,Kazakhstan
9 | Dareen,Connue,dconnue7@blogtalkradio.com,Indonesia
10 | Bab,Audibert,baudibert8@google.cn,Albania
11 | Issie,Hargrave,ihargrave9@ehow.com,Russia
12 | Yard,McGurn,ymcgurna@washington.edu,Czech Republic
13 | Suzy,Hercules,sherculesb@last.fm,Indonesia
14 | Allayne,Mongan,amonganc@yellowbook.com,China
15 | Chickie,Greenlies,cgreenliesd@istockphoto.com,Indonesia
16 | Marve,Paye,mpayee@wunderground.com,China
17 | Kai,Stolting,kstoltingf@tinyurl.com,Sweden
18 | Ken,MacConnal,kmacconnalg@usatoday.com,France
19 | Brittni,De Dei,bdedeih@dmoz.org,Peru
20 | Mitchel,Kilmaster,mkilmasteri@gizmodo.com,Thailand
21 | Clarance,Yegorov,cyegorovj@usnews.com,Albania
22 | Terrie,Shoemark,tshoemarkk@webmd.com,China
23 | Amye,Proswell,aproswelll@constantcontact.com,Canada
24 | Sayre,Sandall,ssandallm@webnode.com,Argentina
25 | Bryna,Eaglesham,beagleshamn@twitter.com,France
26 | Agnola,Bridson,abridsono@flavors.me,Dominican Republic
27 | Tabbie,Pisco,tpiscop@shutterfly.com,Ukraine
28 | Belle,Waddup,bwaddupq@wordpress.org,Bosnia and Herzegovina
29 | Rutter,Solano,rsolanor@disqus.com,Jordan
30 | Mildrid,Leonida,mleonidas@imgur.com,Indonesia
31 | Bibby,MacGillicuddy,bmacgillicuddyt@networkadvertising.org,Costa Rica
32 | Erhard,Wilkennson,ewilkennsonu@skype.com,Philippines
33 | Luelle,Abramski,labramskiv@youtube.com,Greece
34 | Daniela,Prazer,dprazerw@mail.ru,Belarus
35 | Boycie,Tolworthy,btolworthyx@businessweek.com,China
36 | Desiree,Spradbery,dspradberyy@dell.com,China
37 | Kain,Illesley,killesleyz@about.com,Bangladesh
38 | Lamar,Maffezzoli,lmaffezzoli10@gov.uk,China
39 | Dalt,McSpirron,dmcspirron11@biblegateway.com,Sudan
40 | Rayshell,Lyosik,rlyosik12@kickstarter.com,Benin
41 | Georgiana,Messitt,gmessitt13@sfgate.com,Mexico
42 | Thurston,Hartless,thartless14@scribd.com,Indonesia
43 | Dianne,Shearer,dshearer15@state.tx.us,Portugal
44 | Stewart,Keenan,skeenan16@bluehost.com,China
45 | Drusi,Unthank,dunthank17@npr.org,Brazil
46 | Romola,Gourlay,rgourlay18@hexun.com,Philippines
47 | Prentiss,Heersma,pheersma19@sbwire.com,China
48 | Elsinore,Cocci,ecocci1a@eventbrite.com,Brazil
49 | Misty,Balazs,mbalazs1b@tripadvisor.com,China
50 | Cole,Whimper,cwhimper1c@feedburner.com,China
51 | Juliann,Fawloe,jfawloe1d@hugedomains.com,Portugal
52 | Christos,Hansana,chansana1e@etsy.com,Sweden
53 | Merrili,McTurk,mmcturk1f@mtv.com,Belarus
54 | Evey,Dorking,edorking1g@ustream.tv,Portugal
55 | Benita,Rebeiro,brebeiro1h@dyndns.org,Argentina
56 | Karel,Braunstein,kbraunstein1i@prnewswire.com,Ukraine
57 | Bethanne,Georghiou,bgeorghiou1j@engadget.com,France
58 | Anastasia,Furneaux,afurneaux1k@yandex.ru,China
59 | Trace,Duddridge,tduddridge1l@princeton.edu,Venezuela
60 | Lorry,Dymond,ldymond1m@jiathis.com,China
61 | Diarmid,Ratchford,dratchford1n@sogou.com,Yemen
62 | Dorris,Gotcliff,dgotcliff1o@bloglovin.com,Greece
63 | Perle,Malham,pmalham1p@ucoz.com,China
64 | Joseito,Wildey,jwildey1q@wisc.edu,Nigeria
65 | Brittni,Redwall,bredwall1r@wired.com,China
66 | Mariquilla,Este,meste1s@discovery.com,Philippines
67 | Agustin,Pitson,apitson1t@github.com,Indonesia
68 | Dedra,Squier,dsquier1u@cbc.ca,China
69 | Emery,Bielfeldt,ebielfeldt1v@ustream.tv,Philippines
70 | Brandais,Messenbird,bmessenbird1w@opera.com,China
71 | Carleen,Fehely,cfehely1x@networkadvertising.org,Yemen
72 | Benjy,Huzzey,bhuzzey1y@eepurl.com,Indonesia
73 | Starlin,Haggie,shaggie1z@google.com,Czech Republic
74 | Karola,Bagnold,kbagnold20@xrea.com,Russia
75 | Lanae,Longridge,llongridge21@bloglines.com,Russia
76 | Alameda,Blackford,ablackford22@photobucket.com,Poland
77 | Terra,Beaby,tbeaby23@spiegel.de,Russia
78 | Avis,Blacker,ablacker24@soup.io,Cameroon
79 | Frederica,Gooden,fgooden25@redcross.org,Sweden
80 | Adrian,Burgher,aburgher26@mapquest.com,Albania
81 | Toddie,Lynnett,tlynnett27@pagesperso-orange.fr,Mauritania
82 | Auroora,Bucklee,abucklee28@g.co,Indonesia
83 | Milt,Cluderay,mcluderay29@oakley.com,Indonesia
84 | Dorian,Paterno,dpaterno2a@cocolog-nifty.com,Indonesia
85 | Aron,Oats,aoats2b@tripod.com,Argentina
86 | Gualterio,Tunesi,gtunesi2c@exblog.jp,Poland
87 | Lambert,Berkery,lberkery2d@paypal.com,Netherlands
88 | King,Carson,kcarson2e@multiply.com,Niger
89 | Amabelle,Schuh,aschuh2f@ebay.com,Micronesia
90 | Amitie,Ashall,aashall2g@google.de,China
91 | Francisca,McFade,fmcfade2h@g.co,Argentina
92 | Thurstan,O'Nowlan,tonowlan2i@umich.edu,Serbia
93 | Kandace,Sieve,ksieve2j@nature.com,Estonia
94 | Cloe,Berthe,cberthe2k@usa.gov,Peru
95 | Raf,Spilsted,rspilsted2l@phpbb.com,Russia
96 | Fayth,Lissimore,flissimore2m@economist.com,Benin
97 | Shepard,Forri,sforri2n@japanpost.jp,Tanzania
98 | Nickolai,McVeigh,nmcveigh2o@technorati.com,Indonesia
99 | Norby,Nicklin,nnicklin2p@issuu.com,Philippines
100 | Brianne,McKeown,bmckeown2q@netvibes.com,Haiti
101 | Dolph,Glowacz,dglowacz2r@mayoclinic.com,United Kingdom
102 | Maribeth,Wyeth,mwyeth2s@hp.com,Poland
103 | Melvyn,Larcier,mlarcier2t@ifeng.com,China
104 | Gloria,Shardlow,gshardlow2u@gizmodo.com,South Africa
105 | Bernardina,Brompton,bbrompton2v@columbia.edu,Portugal
106 | Luther,Huyche,lhuyche2w@macromedia.com,Panama
107 | Jamesy,Mazdon,jmazdon2x@wikia.com,Vietnam
108 | Lazar,Greir,lgreir2y@stumbleupon.com,Brazil
109 | Mara,Flory,mflory2z@xing.com,Yemen
110 | Sissie,Taggert,staggert30@amazonaws.com,China
111 | Muriel,Lortzing,mlortzing31@de.vu,Japan
112 | Alyse,Woolham,awoolham32@51.la,Sweden
113 | Jarrod,Dunrige,jdunrige33@sourceforge.net,South Africa
114 | Alfons,Hassett,ahassett34@java.com,Ukraine
115 | Cozmo,Schruur,cschruur35@indiegogo.com,Serbia
116 | Annis,McClure,amcclure36@topsy.com,Dominican Republic
117 | Frazier,Ayto,fayto37@youtube.com,Saint Helena
118 | Barty,Lewknor,blewknor38@issuu.com,China
119 | Dalt,Gilbank,dgilbank39@linkedin.com,China
120 | Rhodie,Lieb,rlieb3a@reddit.com,Ukraine
121 | Arnuad,Villalta,avillalta3b@microsoft.com,Russia
122 | Lawrence,Rollings,lrollings3c@mozilla.com,Poland
123 | Rollo,Jerke,rjerke3d@fda.gov,Philippines
124 | Charissa,Barke,cbarke3e@surveymonkey.com,China
125 | Eadmund,Elger,eelger3f@4shared.com,Russia
126 | Doe,Ricker,dricker3g@amazon.de,China
127 | Sol,Spurden,sspurden3h@mapquest.com,Croatia
128 | Margarethe,Scain,mscain3i@theatlantic.com,Indonesia
129 | Yul,Corrison,ycorrison3j@com.com,Mexico
130 | Minnie,Cramond,mcramond3k@soup.io,Brazil
131 | Sayre,Druce,sdruce3l@bandcamp.com,Russia
132 | Minda,Soar,msoar3m@prnewswire.com,China
133 | Gianna,Greatorex,ggreatorex3n@mozilla.com,Thailand
134 | Shell,Ponder,sponder3o@pen.io,China
135 | Archambault,Abys,aabys3p@issuu.com,Argentina
136 | Madge,Mallan,mmallan3q@wsj.com,Nigeria
137 | Wayland,Renowden,wrenowden3r@pen.io,Comoros
138 | Orella,Cuxon,ocuxon3s@intel.com,Russia
139 | Zacharie,Fury,zfury3t@youku.com,Lithuania
140 | Claudetta,Alelsandrowicz,calelsandrowicz3u@latimes.com,Colombia
141 | Gelya,Gravatt,ggravatt3v@dedecms.com,Indonesia
142 | Dorie,Rollings,drollings3w@nsw.gov.au,Poland
143 | Hanan,Caccavale,hcaccavale3x@home.pl,China
144 | Sandor,Clarkson,sclarkson3y@vimeo.com,Sweden
145 | Joell,Chilcott,jchilcott3z@4shared.com,Iran
146 | Sax,Lanceter,slanceter40@51.la,China
147 | Trenton,Cridland,tcridland41@deviantart.com,China
148 | Aime,Lehenmann,alehenmann42@posterous.com,Sweden
149 | Chuck,Killby,ckillby43@php.net,Uzbekistan
150 | Luella,Paulitschke,lpaulitschke44@sohu.com,Philippines
151 | Gabie,McCarter,gmccarter45@mysql.com,Indonesia
152 | Ebonee,Sandcroft,esandcroft46@ucla.edu,Philippines
153 | Miller,Feaviour,mfeaviour47@dropbox.com,Peru
154 | Tandy,Dowry,tdowry48@fotki.com,Russia
155 | Baron,Moulsdale,bmoulsdale49@chron.com,Russia
156 | Bucky,Bruun,bbruun4a@rambler.ru,Vietnam
157 | Ximenez,Luchetti,xluchetti4b@bloglines.com,Peru
158 | Bald,Clash,bclash4c@usda.gov,Portugal
159 | Klarrisa,Leverett,kleverett4d@nationalgeographic.com,Chile
160 | Constantia,Skunes,cskunes4e@reuters.com,Ukraine
161 | Cally,Tallach,ctallach4f@skyrock.com,Colombia
162 | Standford,Hofton,shofton4g@1und1.de,Mexico
163 | Koral,Bownes,kbownes4h@economist.com,China
164 | Orv,Formoy,oformoy4i@vk.com,Morocco
165 | Bernie,Fresson,bfresson4j@buzzfeed.com,Czech Republic
166 | Hester,Rraundl,hrraundl4k@sciencedirect.com,Tunisia
167 | Banky,Treweek,btreweek4l@live.com,Japan
168 | Marta,Nern,mnern4m@csmonitor.com,Indonesia
169 | Marcella,Franzke,mfranzke4n@cbslocal.com,United States
170 | Raoul,Achurch,rachurch4o@gizmodo.com,China
171 | Bernie,Clements,bclements4p@goo.gl,Portugal
172 | Ignace,Jameson,ijameson4q@unc.edu,Brazil
173 | Nicolais,Tyrone,ntyrone4r@ustream.tv,Portugal
174 | Vanny,Lanfere,vlanfere4s@deviantart.com,Portugal
175 | Lynnette,Pritty,lpritty4t@joomla.org,Gambia
176 | Melisa,Prinnett,mprinnett4u@myspace.com,Russia
177 | Myrtice,Mucci,mmucci4v@dagondesign.com,Indonesia
178 | Donna,Greetham,dgreetham4w@w3.org,Indonesia
179 | Duke,Huggon,dhuggon4x@studiopress.com,China
180 | Niccolo,Fomichyov,nfomichyov4y@indiatimes.com,Chile
181 | Haskell,Gather,hgather4z@mysql.com,Portugal
182 | Peterus,Irvin,pirvin50@blog.com,United States
183 | Colby,Soots,csoots51@google.it,Zimbabwe
184 | Fernandina,Lecount,flecount52@blinklist.com,China
185 | Templeton,Capitano,tcapitano53@oakley.com,North Korea
186 | De witt,Pope,dpope54@dot.gov,France
187 | Cass,Flanagan,cflanagan55@oakley.com,Azerbaijan
188 | Winnifred,Fern,wfern56@discovery.com,Ghana
189 | Dillie,Edgeller,dedgeller57@nih.gov,Namibia
190 | Mordecai,Gambie,mgambie58@jimdo.com,Brazil
191 | Evangelin,Muddimer,emuddimer59@facebook.com,Colombia
192 | Fonsie,Rawling,frawling5a@xinhuanet.com,China
193 | Timmie,Elms,telms5b@mail.ru,Portugal
194 | Kane,Leyburn,kleyburn5c@mlb.com,Indonesia
195 | Andie,Sains,asains5d@reverbnation.com,China
196 | Rosalinda,Meadowcroft,rmeadowcroft5e@blinklist.com,China
197 | Pryce,Doogood,pdoogood5f@ox.ac.uk,China
198 | Nicolai,Larenson,nlarenson5g@cbslocal.com,Brazil
199 | Babita,Stanbra,bstanbra5h@ebay.co.uk,China
200 | Kalila,Brownell,kbrownell5i@bloglovin.com,Senegal
201 | Waverly,Batte,wbatte5j@plala.or.jp,Russia
202 | Jereme,Treacher,jtreacher5k@xrea.com,Poland
203 | Ike,Berthomieu,iberthomieu5l@bandcamp.com,Poland
204 | Chloe,Ivchenko,civchenko5m@paypal.com,China
205 | Jenny,Edworthy,jedworthy5n@theglobeandmail.com,Italy
206 | Opaline,Wyrall,owyrall5o@fastcompany.com,Poland
207 | Carolyne,Krause,ckrause5p@goo.gl,Brazil
208 | Margie,Lockett,mlockett5q@creativecommons.org,Finland
209 | Katee,Berndt,kberndt5r@last.fm,China
210 | Catherine,Epp,cepp5s@histats.com,Vietnam
211 | Dana,McKie,dmckie5t@biblegateway.com,China
212 | Giulietta,Marjanovic,gmarjanovic5u@yelp.com,New Zealand
213 | Richmound,Lenz,rlenz5v@oakley.com,Brazil
214 | Celinda,Bullin,cbullin5w@rediff.com,Germany
215 | Imelda,McMonies,imcmonies5x@deviantart.com,Indonesia
216 | Jocelyne,Geill,jgeill5y@hud.gov,El Salvador
217 | Zelig,Macro,zmacro5z@sogou.com,China
218 | Cornelia,Camerati,ccamerati60@cafepress.com,Philippines
219 | Brynn,Tambling,btambling61@reuters.com,Armenia
220 | Daniella,Arnoldi,darnoldi62@home.pl,Mongolia
221 | Bee,Arnaud,barnaud63@macromedia.com,Greece
222 | Tremayne,Longcake,tlongcake64@twitter.com,Greece
223 | Binky,Dudman,bdudman65@cloudflare.com,Armenia
224 | Corbett,Challicombe,cchallicombe66@parallels.com,Nigeria
225 | Miller,Goodbur,mgoodbur67@businessweek.com,Cuba
226 | Currie,Masdon,cmasdon68@umich.edu,Iraq
227 | Reta,Croutear,rcroutear69@feedburner.com,Indonesia
228 | Bendicty,Cadore,bcadore6a@hp.com,Greece
229 | Korie,Driuzzi,kdriuzzi6b@wix.com,Philippines
230 | Upton,Gounin,ugounin6c@printfriendly.com,Jordan
231 | Rudyard,Upjohn,rupjohn6d@google.com.hk,China
232 | Margarethe,Malamore,mmalamore6e@cyberchimps.com,Poland
233 | Denys,McEvoy,dmcevoy6f@zimbio.com,Czech Republic
234 | Charlotta,Kloster,ckloster6g@mashable.com,France
235 | Efren,Shields,eshields6h@privacy.gov.au,Guatemala
236 | Clotilda,Glasman,cglasman6i@1und1.de,Indonesia
237 | Carrol,Marron,cmarron6j@google.cn,Brazil
238 | Leodora,Gainsford,lgainsford6k@eepurl.com,Brazil
239 | Caria,Elstub,celstub6l@lulu.com,France
240 | Samuele,Threadgall,sthreadgall6m@wikipedia.org,Russia
241 | Emmey,Stitcher,estitcher6n@newyorker.com,Argentina
242 | Candi,Steventon,csteventon6o@myspace.com,Sweden
243 | Derward,Zorener,dzorener6p@hhs.gov,Ukraine
244 | Mel,Burges,mburges6q@indiegogo.com,Angola
245 | Vonni,Watsham,vwatsham6r@europa.eu,Indonesia
246 | Britta,Saggs,bsaggs6s@xing.com,France
247 | Phaedra,Vase,pvase6t@google.co.jp,Indonesia
248 | Channa,Dirr,cdirr6u@state.tx.us,Russia
249 | Pavla,Fedorchenko,pfedorchenko6v@mit.edu,Brazil
250 | Robina,Sambells,rsambells6w@edublogs.org,Pakistan
251 | Flynn,Pendrey,fpendrey6x@ehow.com,China
252 | Cristal,Dureden,cdureden6y@whitehouse.gov,Sweden
253 | Nikkie,Carmen,ncarmen6z@1und1.de,China
254 | Mala,Keam,mkeam70@biglobe.ne.jp,Namibia
255 | Martha,Bole,mbole71@thetimes.co.uk,Morocco
256 | Gardiner,Fishlee,gfishlee72@pagesperso-orange.fr,China
257 | Pryce,Palleske,ppalleske73@nature.com,Cambodia
258 | Francene,Poultney,fpoultney74@hubpages.com,China
259 | Zolly,Akett,zakett75@yellowpages.com,Afghanistan
260 | Freemon,Pau,fpau76@go.com,Indonesia
261 | Phillie,Goold,pgoold77@ucla.edu,China
262 | Tallulah,Maudson,tmaudson78@chicagotribune.com,Ukraine
263 | Trevor,Petrolli,tpetrolli79@dropbox.com,China
264 | Tildy,Kalb,tkalb7a@globo.com,Indonesia
265 | Katerina,Kayley,kkayley7b@noaa.gov,Sweden
266 | April,Kingaby,akingaby7c@shutterfly.com,Poland
267 | Lulu,Hawkshaw,lhawkshaw7d@deviantart.com,Indonesia
268 | Jilly,Pointon,jpointon7e@edublogs.org,Poland
269 | Abby,Melpuss,amelpuss7f@springer.com,China
270 | Annecorinne,Riddiford,ariddiford7g@shop-pro.jp,Japan
271 | Margarette,Reisk,mreisk7h@hibu.com,France
272 | Terry,Ferrari,tferrari7i@bravesites.com,Greece
273 | Andras,Phlippi,aphlippi7j@indiegogo.com,China
274 | Mano,Hazeldene,mhazeldene7k@hc360.com,Philippines
275 | Rutherford,Scamwell,rscamwell7l@army.mil,Greece
276 | Elisabet,Byrth,ebyrth7m@nifty.com,Philippines
277 | Tiffie,Kuhnel,tkuhnel7n@digg.com,China
278 | Waylan,Matiewe,wmatiewe7o@wikimedia.org,South Korea
279 | Henri,Auchinleck,hauchinleck7p@hexun.com,Micronesia
280 | Saundra,Piers,spiers7q@icio.us,Libya
281 | Durward,Corington,dcorington7r@odnoklassniki.ru,China
282 | Tommie,Bendelow,tbendelow7s@usa.gov,China
283 | Elisabetta,Guitt,eguitt7t@independent.co.uk,Philippines
284 | Pepe,Gilffillan,pgilffillan7u@businessweek.com,Czech Republic
285 | Magdalena,Cunnow,mcunnow7v@paypal.com,China
286 | Esmeralda,McMurtyr,emcmurtyr7w@gravatar.com,Uzbekistan
287 | Travers,Meachem,tmeachem7x@bloglovin.com,China
288 | Bartholomeo,Grunwall,bgrunwall7y@clickbank.net,China
289 | Sherie,Erricker,serricker7z@constantcontact.com,Poland
290 | Caria,Lease,clease80@statcounter.com,China
291 | Germana,Hoodless,ghoodless81@instagram.com,Philippines
292 | Munmro,Pedlar,mpedlar82@columbia.edu,Venezuela
293 | Berti,Gorioli,bgorioli83@hao123.com,Netherlands
294 | Binnie,Hearsey,bhearsey84@technorati.com,Belarus
295 | Julie,Hamel,jhamel85@myspace.com,Portugal
296 | Rivalee,Gerholz,rgerholz86@xrea.com,Malaysia
297 | Arlette,Guare,aguare87@redcross.org,Tunisia
298 | Desiree,Dods,ddods88@flavors.me,Sri Lanka
299 | Rici,Olivie,rolivie89@nbcnews.com,Ukraine
300 | Darcey,Dabels,ddabels8a@answers.com,Philippines
301 | Dolley,Bax,dbax8b@hexun.com,Czech Republic
302 | Josefina,Jelks,jjelks8c@chron.com,Mexico
303 | Vernon,Sturman,vsturman8d@trellian.com,China
304 | Lawton,Raysdale,lraysdale8e@redcross.org,Saint Vincent and the Grenadines
305 | Di,Castagne,dcastagne8f@wikimedia.org,Ecuador
306 | Minne,Josovitz,mjosovitz8g@vkontakte.ru,Indonesia
307 | Tyrus,Hawkswood,thawkswood8h@squidoo.com,Iran
308 | Brandie,Magwood,bmagwood8i@patch.com,Thailand
309 | Carita,Espinel,cespinel8j@imgur.com,Russia
310 | Ellerey,Agnew,eagnew8k@unblog.fr,Indonesia
311 | Peyton,Piecha,ppiecha8l@shutterfly.com,Indonesia
312 | Shena,Moyce,smoyce8m@rakuten.co.jp,China
313 | Yolane,Antoszczyk,yantoszczyk8n@csmonitor.com,China
314 | Vachel,Cancellieri,vcancellieri8o@goodreads.com,Portugal
315 | Jorie,Dukelow,jdukelow8p@google.nl,France
316 | Gwendolin,Anthon,ganthon8q@merriam-webster.com,North Korea
317 | Johna,Clyde,jclyde8r@berkeley.edu,China
318 | Giustino,Braunstein,gbraunstein8s@furl.net,China
319 | Alfonse,McConnal,amcconnal8t@globo.com,Argentina
320 | Inness,Gilby,igilby8u@altervista.org,China
321 | Graehme,Lymbourne,glymbourne8v@is.gd,Ecuador
322 | Bibbye,MacKim,bmackim8w@edublogs.org,France
323 | Hercules,Dicker,hdicker8x@whitehouse.gov,United States
324 | Victoir,Denyagin,vdenyagin8y@nytimes.com,Mongolia
325 | Oates,Jancey,ojancey8z@mac.com,Mauritius
326 | Raddy,Galland,rgalland90@ehow.com,Philippines
327 | Donall,Collinette,dcollinette91@tinyurl.com,Japan
328 | Nanon,O'Moylan,nomoylan92@wordpress.org,Russia
329 | Renie,Dikes,rdikes93@fc2.com,China
330 | Ab,Ende,aende94@nytimes.com,Russia
331 | Misha,Ladewig,mladewig95@gmpg.org,Russia
332 | Hermina,Smiths,hsmiths96@nasa.gov,Armenia
333 | Bobbee,Andersch,bandersch97@about.com,France
334 | Amos,Colquit,acolquit98@nasa.gov,United States
335 | Cinderella,Anchor,canchor99@bloglovin.com,Kyrgyzstan
336 | Marion,Uccelli,muccelli9a@goodreads.com,Guatemala
337 | Francisca,Fance,ffance9b@symantec.com,Vietnam
338 | Theobald,Oliffe,toliffe9c@mashable.com,Moldova
339 | Dewain,Lowre,dlowre9d@wp.com,China
340 | Giordano,Rance,grance9e@booking.com,Chile
341 | Jobey,Clegg,jclegg9f@paginegialle.it,Thailand
342 | Siobhan,Sollis,ssollis9g@mtv.com,China
343 | Sammy,Meyrick,smeyrick9h@theatlantic.com,Ukraine
344 | Tamqrah,Unger,tunger9i@163.com,Tanzania
345 | Gareth,Sulland,gsulland9j@hexun.com,Indonesia
346 | Sheffield,Rein,srein9k@un.org,Tanzania
347 | Alessandra,Fry,afry9l@moonfruit.com,Poland
348 | Clerc,Gilyatt,cgilyatt9m@guardian.co.uk,United Kingdom
349 | Candice,Belsey,cbelsey9n@google.com.hk,China
350 | Tripp,Stone Fewings,tstonefewings9o@mlb.com,Brazil
351 | Michaela,Pilsbury,mpilsbury9p@hao123.com,China
352 | Carolynn,Veregan,cveregan9q@apple.com,Sri Lanka
353 | Ody,Berthelmot,oberthelmot9r@soundcloud.com,China
354 | Kennith,Merriott,kmerriott9s@walmart.com,Poland
355 | Lynnell,Neubigging,lneubigging9t@fc2.com,Poland
356 | Dacy,Cowlam,dcowlam9u@bigcartel.com,Philippines
357 | Eolande,Phaup,ephaup9v@craigslist.org,Sweden
358 | Vivian,Gaize,vgaize9w@jalbum.net,China
359 | Desdemona,Bernuzzi,dbernuzzi9x@globo.com,Suriname
360 | Ali,Allan,aallan9y@devhub.com,China
361 | Giacinta,Westphalen,gwestphalen9z@foxnews.com,Indonesia
362 | Rosetta,Fawcitt,rfawcitta0@washington.edu,China
363 | Sancho,Francois,sfrancoisa1@php.net,Palestinian Territory
364 | Neil,Schulze,nschulzea2@instagram.com,China
365 | Cynthea,Deniskevich,cdeniskevicha3@paginegialle.it,Nigeria
366 | Katlin,Pescud,kpescuda4@cdc.gov,China
367 | Rochette,Astlatt,rastlatta5@prweb.com,Japan
368 | Kipp,Szymanski,kszymanskia6@yolasite.com,Finland
369 | Linda,Chumley,lchumleya7@webs.com,Kuwait
370 | Frasquito,McCurt,fmccurta8@flickr.com,Ukraine
371 | Pammie,Russel,prussela9@github.io,Czech Republic
372 | Rosina,Melrose,rmelroseaa@reference.com,China
373 | Dougy,Burstowe,dburstoweab@t.co,Indonesia
374 | Huey,Latham,hlathamac@lulu.com,Philippines
375 | Lilli,Jotcham,ljotchamad@adobe.com,Bahamas
376 | Culver,Aizik,caizikae@bandcamp.com,Russia
377 | Merrie,Exer,mexeraf@google.ru,Madagascar
378 | Ania,Oki,aokiag@slideshare.net,Italy
379 | Natalina,Bims,nbimsah@google.co.uk,Greece
380 | Brok,Nurny,bnurnyai@vimeo.com,China
381 | Madlen,Dacke,mdackeaj@com.com,Poland
382 | Kate,Pheazey,kpheazeyak@sphinn.com,Indonesia
383 | Forbes,Bulfield,fbulfieldal@mtv.com,Afghanistan
384 | Leroy,Foulkes,lfoulkesam@apple.com,Indonesia
385 | Eachelle,Adan,eadanan@cisco.com,Netherlands
386 | Brinna,Marflitt,bmarflittao@addthis.com,China
387 | Aurlie,Pretty,aprettyap@shinystat.com,Russia
388 | Rance,Van den Broek,rvandenbroekaq@surveymonkey.com,Chile
389 | Lissie,Mannion,lmannionar@state.tx.us,Guatemala
390 | Randal,De Dantesie,rdedantesieas@stumbleupon.com,Czech Republic
391 | Merci,Petri,mpetriat@forbes.com,Brazil
392 | Lynda,Plummer,lplummerau@4shared.com,Brazil
393 | Sigfrid,McDiarmid,smcdiarmidav@last.fm,Indonesia
394 | Billy,Mountstephen,bmountstephenaw@github.io,Brazil
395 | Tom,Barclay,tbarclayax@nature.com,China
396 | Alaric,Melley,amelleyay@delicious.com,Indonesia
397 | Ursula,Francom,ufrancomaz@webmd.com,Indonesia
398 | Sarina,Lorrain,slorrainb0@flickr.com,Indonesia
399 | Pietro,Brighouse,pbrighouseb1@cisco.com,Indonesia
400 | Cammi,Hullah,chullahb2@slideshare.net,Indonesia
401 | Odilia,Shillan,oshillanb3@nyu.edu,Thailand
402 | Conn,Cankett,ccankettb4@craigslist.org,Japan
403 | Adelaida,Prestige,aprestigeb5@so-net.ne.jp,Russia
404 | Andrej,Heningham,aheninghamb6@tripod.com,Armenia
405 | Edsel,Birrane,ebirraneb7@netvibes.com,Philippines
406 | Clarance,Tatham,ctathamb8@nifty.com,Central African Republic
407 | Carly,Dashper,cdashperb9@home.pl,Portugal
408 | Noelle,Jacquemy,njacquemyba@wix.com,Botswana
409 | Odell,Laurence,olaurencebb@digg.com,Guatemala
410 | Daveen,Maciak,dmaciakbc@prweb.com,Peru
411 | Lurline,Gourdon,lgourdonbd@ehow.com,Palestinian Territory
412 | Birch,Murrison,bmurrisonbe@cbsnews.com,Philippines
413 | Kerwin,Dunnaway,kdunnawaybf@vkontakte.ru,Portugal
414 | Solly,Benditt,sbendittbg@salon.com,Uganda
415 | Dareen,Petroulis,dpetroulisbh@qq.com,Poland
416 | Marjory,Lawrenceson,mlawrencesonbi@goodreads.com,South Africa
417 | Richie,Stonestreet,rstonestreetbj@japanpost.jp,China
418 | Danila,Benninger,dbenningerbk@geocities.com,China
419 | Marlo,Chettle,mchettlebl@businessweek.com,Georgia
420 | Fleming,Ferenc,fferencbm@tmall.com,China
421 | Jeane,Metham,jmethambn@wikispaces.com,Indonesia
422 | Jecho,Burtwhistle,jburtwhistlebo@time.com,Indonesia
423 | Mallory,O'Heneghan,moheneghanbp@a8.net,Zimbabwe
424 | Grace,Bamborough,gbamboroughbq@google.com.hk,Egypt
425 | Jannelle,Standing,jstandingbr@unblog.fr,Brazil
426 | Lela,Lys,llysbs@mozilla.org,Portugal
427 | Giacinta,Malter,gmalterbt@discovery.com,China
428 | Henrie,Summerton,hsummertonbu@rediff.com,Slovenia
429 | Raimundo,Somerlie,rsomerliebv@nba.com,Russia
430 | Lynna,Muehle,lmuehlebw@t.co,Russia
431 | Emanuele,Sewter,esewterbx@yahoo.com,Indonesia
432 | Madlin,Shurville,mshurvilleby@yellowpages.com,Philippines
433 | Odella,Ommundsen,oommundsenbz@utexas.edu,Indonesia
434 | Umberto,Brien,ubrienc0@nydailynews.com,Cameroon
435 | Adriana,Arp,aarpc1@furl.net,France
436 | Fields,Labram,flabramc2@unesco.org,Argentina
437 | Fifi,McKnockiter,fmcknockiterc3@quantcast.com,Australia
438 | Tallie,Dallaway,tdallawayc4@tripod.com,Colombia
439 | Kara,Kyttor,kkyttorc5@xrea.com,Portugal
440 | Beckie,Dilgarno,bdilgarnoc6@ebay.co.uk,United States
441 | Rois,Linebarger,rlinebargerc7@naver.com,Nigeria
442 | Bernadene,Nattriss,bnattrissc8@unesco.org,Peru
443 | Tawsha,Ballintyne,tballintynec9@squarespace.com,China
444 | Osborn,Hatchell,ohatchellca@state.tx.us,Philippines
445 | Neila,Osselton,nosseltoncb@pbs.org,Serbia
446 | Araldo,Serris,aserriscc@odnoklassniki.ru,Ukraine
447 | Marketa,Divina,mdivinacd@usnews.com,Vietnam
448 | Marianna,Pierce,mpiercece@cpanel.net,Czech Republic
449 | Joanie,Stapele,jstapelecf@nymag.com,United States
450 | Orelie,Montague,omontaguecg@fotki.com,Portugal
451 | Iggy,Gumbrell,igumbrellch@bigcartel.com,Indonesia
452 | Cory,Riediger,criedigerci@pen.io,Bangladesh
453 | Renee,Stellman,rstellmancj@jimdo.com,Mongolia
454 | Allene,Lafferty,alaffertyck@aol.com,China
455 | Elise,Hartfield,ehartfieldcl@wunderground.com,Poland
456 | Lorianne,Matushevitz,lmatushevitzcm@over-blog.com,Indonesia
457 | Doralynn,Suddock,dsuddockcn@yahoo.co.jp,Sweden
458 | Tracey,Donke,tdonkeco@mtv.com,Greece
459 | Marcello,Giurio,mgiuriocp@ed.gov,China
460 | Vikki,Heinicke,vheinickecq@pcworld.com,Honduras
461 | Lyndell,Santacrole,lsantacrolecr@cnn.com,Indonesia
462 | Phillis,Tunmore,ptunmorecs@ca.gov,Tunisia
463 | Lammond,Kimberley,lkimberleyct@wikipedia.org,Canada
464 | Glenn,Dusting,gdustingcu@ehow.com,China
465 | Lorne,Crafter,lcraftercv@plala.or.jp,Russia
466 | Hersh,Djakovic,hdjakoviccw@de.vu,Brazil
467 | Orion,Hurdidge,ohurdidgecx@360.cn,China
468 | Colby,Dionisi,cdionisicy@japanpost.jp,Argentina
469 | Audre,Arsnell,aarsnellcz@census.gov,Poland
470 | Vernen,MacGraith,vmacgraithd0@infoseek.co.jp,Cuba
471 | Tobye,Moss,tmossd1@twitpic.com,China
472 | Donnamarie,Custed,dcustedd2@sohu.com,France
473 | Ruthie,Bilam,rbilamd3@amazon.co.jp,Iran
474 | Masha,Routh,mrouthd4@comsenz.com,South Korea
475 | Glenda,Rudwell,grudwelld5@last.fm,Greece
476 | Flor,Sprade,fspraded6@scientificamerican.com,China
477 | Stoddard,Eakeley,seakeleyd7@ycombinator.com,United States
478 | Colver,Mensler,cmenslerd8@imdb.com,Nigeria
479 | Kylila,Stanners,kstannersd9@epa.gov,China
480 | Coraline,Trevna,ctrevnada@columbia.edu,France
481 | Elinor,Blaschke,eblaschkedb@si.edu,China
482 | Marshall,Seiter,mseiterdc@twitpic.com,Democratic Republic of the Congo
483 | Carlee,Gilhooly,cgilhoolydd@fema.gov,Guatemala
484 | Darell,Grosier,dgrosierde@freewebs.com,Brazil
485 | Letisha,Suddell,lsuddelldf@github.io,Czech Republic
486 | Daniel,Giovanitti,dgiovanittidg@about.com,Morocco
487 | Fleur,Paradin,fparadindh@diigo.com,Japan
488 | Ruddy,Wiz,rwizdi@flavors.me,China
489 | Myer,Featherstone,mfeatherstonedj@cafepress.com,Ireland
490 | Theda,Tressler,ttresslerdk@alexa.com,Peru
491 | Ailyn,Kirman,akirmandl@wikipedia.org,Colombia
492 | Sadye,Itskovitz,sitskovitzdm@biglobe.ne.jp,Brazil
493 | Sig,Ternault,sternaultdn@mashable.com,China
494 | Guilbert,Bertomieu,gbertomieudo@hao123.com,United States
495 | Donna,Orviss,dorvissdp@360.cn,China
496 | Trenna,Baniard,tbaniarddq@hp.com,China
497 | Tami,Ertelt,terteltdr@slideshare.net,France
498 | Emlyn,Treasure,etreasureds@simplemachines.org,Russia
499 | Roderick,Flawn,rflawndt@hostgator.com,Russia
500 | Asher,Colvie,acolviedu@g.co,Philippines
501 | Riley,Meco,rmecodv@mashable.com,Philippines
502 | Kalinda,Allner,kallnerdw@dot.gov,Mexico
503 | Daren,Jullian,djulliandx@springer.com,Portugal
504 | Aleksandr,O'Loghlen,aologhlendy@google.pl,Indonesia
505 | Emilee,Damiral,edamiraldz@biglobe.ne.jp,Egypt
506 | Marshall,Lalley,mlalleye0@google.cn,China
507 | Care,Sabey,csabeye1@shareasale.com,Philippines
508 | Victor,Arger,vargere2@hugedomains.com,China
509 | Elvera,Capner,ecapnere3@mediafire.com,Kazakhstan
510 | Joe,Ollier,jolliere4@hubpages.com,Indonesia
511 | Georgina,Dabrowski,gdabrowskie5@imdb.com,Cameroon
512 | Hernando,Freake,hfreakee6@i2i.jp,Russia
513 | Samaria,Spenton,sspentone7@mysql.com,Indonesia
514 | Imogen,Willden,iwilldene8@usa.gov,Indonesia
515 | Simeon,Huton,shutone9@reddit.com,Russia
516 | Emanuele,Abbot,eabbotea@twitter.com,Ukraine
517 | Starr,Kyston,skystoneb@slideshare.net,Ukraine
518 | Hewet,Goulbourne,hgoulbourneec@admin.ch,Poland
519 | Cecilia,Cockcroft,ccockcrofted@army.mil,China
520 | Cece,Swatradge,cswatradgeee@dedecms.com,Afghanistan
521 | Ofilia,Andriveaux,oandriveauxef@storify.com,Finland
522 | Ferris,Million,fmillioneg@dell.com,Philippines
523 | Doro,Mockes,dmockeseh@yandex.ru,Malaysia
524 | Christoffer,Mannock,cmannockei@wordpress.com,Serbia
525 | Briggs,Adamovich,badamovichej@liveinternet.ru,Czech Republic
526 | Ram,Trangmar,rtrangmarek@adobe.com,Brazil
527 | Leola,Winscum,lwinscumel@springer.com,Indonesia
528 | Rurik,Rosi,rrosiem@amazon.co.jp,Colombia
529 | Tabby,Ventham,tventhamen@altervista.org,Indonesia
530 | Adelaida,Ching,achingeo@google.co.uk,Indonesia
531 | Addison,Sangster,asangsterep@moonfruit.com,Bosnia and Herzegovina
532 | Missie,Hakeworth,mhakewortheq@cyberchimps.com,Russia
533 | Basilio,Tissell,btisseller@deliciousdays.com,Samoa
534 | Shell,Adamiak,sadamiakes@smh.com.au,Sweden
535 | Benson,Dowdell,bdowdellet@dropbox.com,China
536 | Pietro,Mahy,pmahyeu@huffingtonpost.com,Mongolia
537 | Fidel,Filer,ffilerev@360.cn,Ukraine
538 | Abigail,Wisbey,awisbeyew@youtu.be,Tunisia
539 | Jessica,Beamson,jbeamsonex@blogs.com,China
540 | Carlos,Cobelli,ccobelliey@java.com,Albania
541 | Hershel,Sully,hsullyez@google.com.br,China
542 | Joete,Imason,jimasonf0@sourceforge.net,China
543 | Peri,McGeneay,pmcgeneayf1@51.la,Russia
544 | Dyana,Bagge,dbaggef2@cisco.com,China
545 | Cris,Egre,cegref3@naver.com,Pakistan
546 | Sancho,Cowp,scowpf4@spotify.com,Nigeria
547 | Alvina,Paszak,apaszakf5@tamu.edu,Russia
548 | Gabie,Slaughter,gslaughterf6@imgur.com,Canada
549 | Kipp,Carryer,kcarryerf7@ow.ly,Poland
550 | Erhard,Boice,eboicef8@cisco.com,Iran
551 | Andros,Priter,apriterf9@biblegateway.com,China
552 | Shawnee,Jessel,sjesselfa@wunderground.com,Sweden
553 | Kyle,Moff,kmofffb@redcross.org,Indonesia
554 | Duke,Paolucci,dpaoluccifc@flavors.me,Indonesia
555 | Gael,Bridgewood,gbridgewoodfd@last.fm,Australia
556 | Munroe,Brotherhed,mbrotherhedfe@seesaa.net,Sweden
557 | Jehanna,MacInnes,jmacinnesff@qq.com,China
558 | Shamus,Sherwill,ssherwillfg@discovery.com,China
559 | Keri,Twist,ktwistfh@sfgate.com,Russia
560 | Murial,Palatino,mpalatinofi@irs.gov,United States
561 | Berry,Jeary,bjearyfj@mac.com,China
562 | Siffre,Fashion,sfashionfk@ask.com,China
563 | Camile,Drayton,cdraytonfl@reuters.com,Brazil
564 | Roman,Cotterell,rcotterellfm@oakley.com,China
565 | Jammie,Gontier,jgontierfn@tamu.edu,Ukraine
566 | Ainslee,Eastment,aeastmentfo@imgur.com,Belarus
567 | Cele,Chilcotte,cchilcottefp@csmonitor.com,Japan
568 | Evvie,Gilliver,egilliverfq@netvibes.com,Croatia
569 | Gavrielle,Shawdforth,gshawdforthfr@pbs.org,China
570 | Alisa,Cameli,acamelifs@163.com,China
571 | Deloris,Parlett,dparlettft@macromedia.com,South Africa
572 | Torey,McKie,tmckiefu@domainmarket.com,China
573 | Brand,Seamon,bseamonfv@scribd.com,Thailand
574 | Hestia,Camp,hcampfw@vinaora.com,Slovenia
575 | Lisle,Piola,lpiolafx@paypal.com,China
576 | Jeremias,O'Geaney,jogeaneyfy@symantec.com,South Korea
577 | Nikolaus,Wimmers,nwimmersfz@geocities.jp,Germany
578 | Aline,Clem,aclemg0@xrea.com,Namibia
579 | Caresa,Fogt,cfogtg1@deliciousdays.com,Indonesia
580 | Rollin,Gothliff,rgothliffg2@nsw.gov.au,Finland
581 | Hewet,Armstrong,harmstrongg3@about.com,Russia
582 | Orelia,Metheringham,ometheringhamg4@e-recht24.de,China
583 | Conchita,Harrie,charrieg5@webnode.com,Argentina
584 | Paton,Tothe,ptotheg6@oaic.gov.au,Czech Republic
585 | Roch,David,rdavidg7@hud.gov,China
586 | Rafaello,Steddall,rsteddallg8@yellowbook.com,Indonesia
587 | Theodoric,Blampied,tblampiedg9@wunderground.com,France
588 | Koral,Pittson,kpittsonga@1und1.de,Turkmenistan
589 | James,Duchant,jduchantgb@phpbb.com,China
590 | Idelle,Ferenczy,iferenczygc@ft.com,Indonesia
591 | Dallis,Cockill,dcockillgd@hc360.com,Indonesia
592 | Maynord,Dargan,mdargange@blogs.com,Brazil
593 | Mace,Winterburn,mwinterburngf@360.cn,Indonesia
594 | Jillana,Meriguet,jmeriguetgg@istockphoto.com,Finland
595 | Dorri,Terran,dterrangh@nymag.com,China
596 | Wit,Shackell,wshackellgi@blinklist.com,China
597 | Averell,Timmons,atimmonsgj@cloudflare.com,Portugal
598 | Carri,Isaacs,cisaacsgk@msn.com,Brazil
599 | Noak,Morkham,nmorkhamgl@stanford.edu,Russia
600 | Berke,Santo,bsantogm@noaa.gov,Indonesia
601 | Richart,Yusupov,ryusupovgn@csmonitor.com,Slovenia
602 | Dianemarie,Gergler,dgerglergo@vistaprint.com,Libya
603 | Amalle,Pennycuick,apennycuickgp@go.com,China
604 | Katherina,Artus,kartusgq@washington.edu,Russia
605 | Mechelle,Geaney,mgeaneygr@shop-pro.jp,China
606 | Tiffi,Hatherley,thatherleygs@ebay.com,China
607 | Alvinia,Ayling,aaylinggt@icq.com,Mozambique
608 | Alexi,Peddersen,apeddersengu@reference.com,Philippines
609 | Trev,Dudek,tdudekgv@webs.com,Argentina
610 | Ursula,Date,udategw@gravatar.com,Bahamas
611 | Bellina,Rennock,brennockgx@smh.com.au,Vietnam
612 | Gunar,Delacour,gdelacourgy@icio.us,Venezuela
613 | Tam,Hackleton,thackletongz@tumblr.com,France
614 | Godard,Linge,glingeh0@imageshack.us,Poland
615 | Seumas,Shakesbye,sshakesbyeh1@goo.gl,Morocco
616 | Korey,Jolliss,kjollissh2@marketwatch.com,Indonesia
617 | Luigi,Cluet,lclueth3@wikipedia.org,Portugal
618 | Sam,Ellph,sellphh4@angelfire.com,Indonesia
619 | Drew,Eddoes,deddoesh5@booking.com,Philippines
620 | Pam,St. John,pstjohnh6@cnbc.com,Indonesia
621 | Clyve,Maghull,cmaghullh7@cmu.edu,Vietnam
622 | Jarrett,Francillo,jfrancilloh8@jigsy.com,Haiti
623 | Jeanelle,Candlin,jcandlinh9@epa.gov,Philippines
624 | Fraser,Gemelli,fgemelliha@skyrock.com,Indonesia
625 | Marlene,Roman,mromanhb@ftc.gov,Indonesia
626 | Ingram,Hundell,ihundellhc@tamu.edu,Portugal
627 | Lin,Dunbobin,ldunbobinhd@blogtalkradio.com,China
628 | Hilde,Soden,hsodenhe@blogtalkradio.com,China
629 | Jourdan,Hayer,jhayerhf@youku.com,Indonesia
630 | Trumann,Charlwood,tcharlwoodhg@globo.com,Sweden
631 | Elspeth,Harrad,eharradhh@com.com,Indonesia
632 | Oates,Callister,ocallisterhi@prnewswire.com,Madagascar
633 | Lonnard,Anwyl,lanwylhj@stumbleupon.com,Peru
634 | Gilbert,Cafe,gcafehk@addtoany.com,Philippines
635 | Woodrow,Bande,wbandehl@census.gov,France
636 | Bryon,Hayland,bhaylandhm@vimeo.com,Indonesia
637 | Evelyn,Greyes,egreyeshn@simplemachines.org,Argentina
638 | Randie,Ciottoi,rciottoiho@rakuten.co.jp,Colombia
639 | Raymond,Rigts,rrigtshp@devhub.com,China
640 | Dasie,McVrone,dmcvronehq@nasa.gov,Ukraine
641 | Abbey,Timlett,atimletthr@jiathis.com,Ukraine
642 | Brnaby,Lickorish,blickorishhs@icq.com,Serbia
643 | Thomasina,Dennett,tdennettht@ox.ac.uk,Australia
644 | Meryl,Balston,mbalstonhu@whitehouse.gov,Afghanistan
645 | Loralie,Burden,lburdenhv@over-blog.com,China
646 | Nickolas,Huws,nhuwshw@constantcontact.com,Portugal
647 | Kelley,Cove,kcovehx@yellowbook.com,China
648 | Markus,Parton,mpartonhy@ucoz.com,Croatia
649 | Humberto,Hurd,hhurdhz@intel.com,Thailand
650 | Carie,Labitt,clabitti0@nyu.edu,Albania
651 | Guendolen,McGilmartin,gmcgilmartini1@ft.com,France
652 | Neron,Matlock,nmatlocki2@epa.gov,Venezuela
653 | Neel,Kimmons,nkimmonsi3@who.int,Yemen
654 | Bernardo,Toppin,btoppini4@meetup.com,Pakistan
655 | Dorolice,Grim,dgrimi5@slideshare.net,China
656 | Giorgia,Ternent,gternenti6@ycombinator.com,Philippines
657 | Wally,Fake,wfakei7@ihg.com,Colombia
658 | Urbano,Clutheram,uclutherami8@elegantthemes.com,Japan
659 | Adolf,Mordin,amordini9@wp.com,China
660 | Dilan,Hoyles,dhoylesia@ow.ly,China
661 | Robert,Dunning,rdunningib@bbb.org,Yemen
662 | Delcine,Desvignes,ddesvignesic@upenn.edu,Germany
663 | Horatio,Keynd,hkeyndid@php.net,Portugal
664 | Magda,Antoniewski,mantoniewskiie@wufoo.com,Indonesia
665 | Rosie,Luck,rluckif@ameblo.jp,Germany
666 | Tate,Balden,tbaldenig@ovh.net,Chile
667 | Natalina,Thirlwell,nthirlwellih@skype.com,Japan
668 | Carny,Kehri,ckehriii@msu.edu,Sweden
669 | Nickie,De Winton,ndewintonij@kickstarter.com,Poland
670 | Dena,Krojn,dkrojnik@ebay.co.uk,Canada
671 | Phyllys,Goricke,pgorickeil@a8.net,China
672 | Emelda,Mellor,emellorim@qq.com,China
673 | Jeanna,Dacke,jdackein@nymag.com,Kazakhstan
674 | Grata,Spaduzza,gspaduzzaio@guardian.co.uk,China
675 | Sibylla,Stode,sstodeip@chronoengine.com,Brazil
676 | Sonny,Epsly,sepslyiq@businessweek.com,Sweden
677 | Alexi,Casewell,acasewellir@twitpic.com,Yemen
678 | Ranique,Raynes,rraynesis@soup.io,Indonesia
679 | Anjela,Starzaker,astarzakerit@seesaa.net,Palestinian Territory
680 | Hakim,Norquay,hnorquayiu@wp.com,Japan
681 | Dru,Baron,dbaroniv@domainmarket.com,Dominican Republic
682 | Donn,Fries,dfriesiw@guardian.co.uk,China
683 | Dall,Horry,dhorryix@dagondesign.com,Russia
684 | Bonnee,Smeuin,bsmeuiniy@hubpages.com,Indonesia
685 | Calida,Jentzsch,cjentzschiz@harvard.edu,Peru
686 | Alan,Stronge,astrongej0@sina.com.cn,Serbia
687 | Celine,Izacenko,cizacenkoj1@nationalgeographic.com,Brazil
688 | Heidi,Delle,hdellej2@cam.ac.uk,China
689 | Miquela,Hoodspeth,mhoodspethj3@engadget.com,Nigeria
690 | Cristin,Glander,cglanderj4@senate.gov,Serbia
691 | Rodge,Sivewright,rsivewrightj5@ebay.com,Brazil
692 | Cozmo,Jeandillou,cjeandillouj6@bing.com,Argentina
693 | Devinne,McClurg,dmcclurgj7@unesco.org,China
694 | Raffaello,Salatino,rsalatinoj8@google.es,Poland
695 | Chryste,Hardstaff,chardstaffj9@boston.com,France
696 | Thomasa,McKeller,tmckellerja@ifeng.com,Portugal
697 | Ethel,Oselton,eoseltonjb@skyrock.com,Russia
698 | Eimile,World,eworldjc@sogou.com,Russia
699 | Adolpho,Durbin,adurbinjd@lycos.com,Montenegro
700 | Celestine,Tonry,ctonryje@miitbeian.gov.cn,Portugal
701 | Bran,Crysell,bcryselljf@blogger.com,Mexico
702 | Renard,Trunks,rtrunksjg@indiegogo.com,Brazil
703 | Adda,Diego,adiegojh@nytimes.com,Indonesia
704 | Tabby,Tolson,ttolsonji@geocities.com,Poland
705 | Christiane,Padberry,cpadberryjj@themeforest.net,Indonesia
706 | Romona,Gwioneth,rgwionethjk@vkontakte.ru,China
707 | Jeffrey,Kirwood,jkirwoodjl@infoseek.co.jp,Sweden
708 | Baron,Esmead,besmeadjm@nih.gov,Russia
709 | Broderic,Duffan,bduffanjn@archive.org,Greece
710 | Falito,Volonte,fvolontejo@auda.org.au,Portugal
711 | Hermann,Gianninotti,hgianninottijp@epa.gov,Indonesia
712 | Constance,Mafham,cmafhamjq@vimeo.com,China
713 | Liane,Scramage,lscramagejr@cafepress.com,Ukraine
714 | Katha,Moodey,kmoodeyjs@abc.net.au,China
715 | Benny,Doumic,bdoumicjt@irs.gov,China
716 | Byrann,Vercruysse,bvercruysseju@harvard.edu,China
717 | Alexandro,Buckbee,abuckbeejv@bandcamp.com,Indonesia
718 | Berenice,Markushkin,bmarkushkinjw@unicef.org,Thailand
719 | Gray,Neilands,gneilandsjx@tamu.edu,Russia
720 | Frieda,Wagg,fwaggjy@icio.us,China
721 | Saundra,Boodell,sboodelljz@yahoo.co.jp,Sweden
722 | Aleen,Farden,afardenk0@reuters.com,China
723 | Ripley,Drei,rdreik1@github.io,Belarus
724 | Granny,Leggitt,gleggittk2@cisco.com,China
725 | Chicky,Block,cblockk3@hibu.com,France
726 | Nicky,Dudhill,ndudhillk4@mashable.com,China
727 | Nicky,Burchess,nburchessk5@census.gov,Portugal
728 | Quincey,Stockin,qstockink6@myspace.com,Sweden
729 | Kenna,Fells,kfellsk7@state.tx.us,Somalia
730 | Fergus,Retallick,fretallickk8@amazon.co.uk,Netherlands
731 | Hamish,Manthorpe,hmanthorpek9@multiply.com,Poland
732 | Tiertza,Auguste,taugusteka@xinhuanet.com,Japan
733 | Shalom,Flux,sfluxkb@intel.com,Russia
734 | Jodie,Randal,jrandalkc@mlb.com,Indonesia
735 | Hayes,Huckin,hhuckinkd@tinyurl.com,Indonesia
736 | Dierdre,Beaconsall,dbeaconsallke@yahoo.com,Czech Republic
737 | Adler,Doble,adoblekf@privacy.gov.au,Finland
738 | Clive,Scoffins,cscoffinskg@marriott.com,Russia
739 | Norry,Mossbee,nmossbeekh@newsvine.com,Poland
740 | Claus,Libero,cliberoki@cargocollective.com,Brazil
741 | Anett,Ingerith,aingerithkj@last.fm,Ukraine
742 | Codi,Masdon,cmasdonkk@opensource.org,Sweden
743 | Griselda,Mayger,gmaygerkl@china.com.cn,Russia
744 | Trudey,Crannell,tcrannellkm@pagesperso-orange.fr,Canada
745 | Jere,Hayth,jhaythkn@nsw.gov.au,Peru
746 | Abba,Ebertz,aebertzko@eepurl.com,Poland
747 | Jasen,Blomfield,jblomfieldkp@sogou.com,Slovenia
748 | Filberto,Clamo,fclamokq@spiegel.de,China
749 | Maighdiln,Dury,mdurykr@bbc.co.uk,Madagascar
750 | Sada,Oldrey,soldreyks@ucla.edu,Czech Republic
751 | Debora,Ketchell,dketchellkt@vinaora.com,Sweden
752 | Obadiah,Petofi,opetofiku@engadget.com,Indonesia
753 | Frederick,Aickin,faickinkv@cnn.com,China
754 | Deane,Fleckno,dflecknokw@alexa.com,Poland
755 | Sunny,Buffham,sbuffhamkx@pen.io,Sri Lanka
756 | Ravid,Meach,rmeachky@walmart.com,Indonesia
757 | Stanley,Durden,sdurdenkz@xing.com,Brazil
758 | Elinore,Troni,etronil0@usatoday.com,Panama
759 | Neely,Lindl,nlindll1@naver.com,Philippines
760 | Gayle,Bulleyn,gbulleynl2@people.com.cn,Philippines
761 | Barry,Kornilyev,bkornilyevl3@i2i.jp,Greece
762 | Clarisse,Gaskarth,cgaskarthl4@bizjournals.com,Ukraine
763 | Niki,Fullick,nfullickl5@cdbaby.com,Greece
764 | Raquel,Luscott,rluscottl6@princeton.edu,Peru
765 | Martica,Farrants,mfarrantsl7@ucsd.edu,Indonesia
766 | Bellanca,Ewin,bewinl8@barnesandnoble.com,Bosnia and Herzegovina
767 | Gerda,Jakoviljevic,gjakoviljevicl9@theatlantic.com,China
768 | Caralie,Heak,cheakla@cdc.gov,Benin
769 | Nelli,Pountain,npountainlb@dyndns.org,China
770 | Erik,Eatock,eeatocklc@delicious.com,Indonesia
771 | Michel,Pentlow,mpentlowld@digg.com,China
772 | Kelsey,Abramsky,kabramskyle@bbb.org,China
773 | Eadmund,Piniur,epiniurlf@miibeian.gov.cn,Russia
774 | Melesa,Blackmuir,mblackmuirlg@behance.net,France
775 | Aristotle,Hutchason,ahutchasonlh@vistaprint.com,Vietnam
776 | Audy,Halfacree,ahalfacreeli@instagram.com,Philippines
777 | Katy,Olenchenko,kolenchenkolj@sohu.com,Macao
778 | Ariela,Jersh,ajershlk@pbs.org,British Virgin Islands
779 | Geno,Simonazzi,gsimonazzill@techcrunch.com,Chile
780 | Fee,Terlinden,fterlindenlm@blogger.com,China
781 | Sergio,Fielder,sfielderln@state.tx.us,Russia
782 | Erasmus,Behrend,ebehrendlo@ameblo.jp,China
783 | Aloise,Demare,ademarelp@mit.edu,Mauritius
784 | Kessia,Cahalin,kcahalinlq@zimbio.com,Peru
785 | Kevon,Cumpton,kcumptonlr@ocn.ne.jp,Portugal
786 | Carma,Lehemann,clehemannls@csmonitor.com,Portugal
787 | Alie,Durrett,adurrettlt@newyorker.com,Colombia
788 | Mattie,Olyunin,molyuninlu@netvibes.com,China
789 | Tyne,Heinssen,theinssenlv@craigslist.org,Nigeria
790 | Shaina,Alexandersson,salexanderssonlw@studiopress.com,Mauritania
791 | Ronnie,Copp,rcopplx@wix.com,China
792 | Brit,Ingry,bingryly@fda.gov,Brazil
793 | Marika,Dominka,mdominkalz@businessweek.com,France
794 | Randi,Hosburn,rhosburnm0@unblog.fr,Portugal
795 | Martainn,Willetts,mwillettsm1@time.com,China
796 | Suellen,Deplacido,sdeplacidom2@who.int,Bulgaria
797 | Dena,Franzotto,dfranzottom3@cafepress.com,Macedonia
798 | Julienne,Abramovici,jabramovicim4@pcworld.com,South Korea
799 | Trent,Hurt,thurtm5@washington.edu,Ukraine
800 | Florence,Kenney,fkenneym6@baidu.com,Venezuela
801 | Bailie,Baseke,bbasekem7@wsj.com,Portugal
802 | Leeann,Inderwick,linderwickm8@pinterest.com,Nigeria
803 | Hinda,Cussins,hcussinsm9@usnews.com,Latvia
804 | Blake,Duprey,bdupreyma@oracle.com,Peru
805 | Rhonda,Cartan,rcartanmb@usda.gov,Albania
806 | Joby,Carnie,jcarniemc@myspace.com,China
807 | Duky,Kempstone,dkempstonemd@scientificamerican.com,Brazil
808 | Clarita,Khan,ckhanme@skype.com,Russia
809 | Olympie,Brunning,obrunningmf@umich.edu,Italy
810 | Rae,Aulds,rauldsmg@theatlantic.com,China
811 | Lorry,Hearnden,lhearndenmh@seattletimes.com,Russia
812 | Broddy,Coggles,bcogglesmi@vkontakte.ru,Indonesia
813 | Stanislaus,Feetham,sfeethammj@tinypic.com,China
814 | Caryl,MacConneely,cmacconneelymk@paginegialle.it,China
815 | Carie,Crigin,ccriginml@addthis.com,Brazil
816 | Abby,Lavalle,alavallemm@comsenz.com,Brazil
817 | Eryn,Gudd,eguddmn@netscape.com,Russia
818 | Jacquelynn,Focke,jfockemo@desdev.cn,France
819 | Janetta,Vertigan,jvertiganmp@moonfruit.com,Afghanistan
820 | Kandy,Swin,kswinmq@stanford.edu,China
821 | Clovis,Parram,cparrammr@mayoclinic.com,China
822 | Skippie,Viscovi,sviscovims@cisco.com,Ukraine
823 | Evita,Tue,etuemt@npr.org,Russia
824 | Lacie,Cersey,lcerseymu@cnbc.com,Philippines
825 | Joyce,Dyett,jdyettmv@prnewswire.com,China
826 | Heinrik,Hinz,hhinzmw@g.co,Poland
827 | Rosana,Dollman,rdollmanmx@house.gov,Russia
828 | Vlad,Studd,vstuddmy@sohu.com,Sweden
829 | Langsdon,Inman,linmanmz@drupal.org,Germany
830 | Reese,Sibary,rsibaryn0@ifeng.com,Mongolia
831 | Modesta,McGrady,mmcgradyn1@aol.com,Portugal
832 | Hieronymus,Georghiou,hgeorghioun2@oakley.com,Indonesia
833 | Cross,Le Noury,clenouryn3@techcrunch.com,Philippines
834 | Cybil,Grundle,cgrundlen4@blogs.com,Russia
835 | June,Goldstone,jgoldstonen5@forbes.com,Poland
836 | Jemmy,Lighton,jlightonn6@github.io,Albania
837 | Heather,Renol,hrenoln7@apache.org,Indonesia
838 | Glyn,Gowrie,ggowrien8@goo.ne.jp,China
839 | Dorothea,MacPaden,dmacpadenn9@homestead.com,Thailand
840 | Analise,Hollyland,ahollylandna@photobucket.com,France
841 | Kathe,Dominey,kdomineynb@cam.ac.uk,China
842 | Lalo,Chidlow,lchidlownc@blogger.com,Indonesia
843 | Frasco,Franke,ffrankend@1688.com,Sweden
844 | Welbie,Cleaton,wcleatonne@skyrock.com,Belarus
845 | Linnet,Pudner,lpudnernf@loc.gov,Colombia
846 | Adele,De Bruijn,adebruijnng@google.nl,China
847 | Carlye,Hymor,chymornh@nba.com,Indonesia
848 | Turner,Sandal,tsandalni@census.gov,France
849 | Harbert,Myatt,hmyattnj@biglobe.ne.jp,Iraq
850 | Gunner,Syddall,gsyddallnk@foxnews.com,Japan
851 | Tersina,Passion,tpassionnl@wix.com,Peru
852 | Willamina,Nafzger,wnafzgernm@elpais.com,Russia
853 | Hali,Ling,hlingnn@goo.ne.jp,Philippines
854 | Cully,Foulstone,cfoulstoneno@trellian.com,Japan
855 | Leonelle,Deverall,ldeverallnp@ted.com,Madagascar
856 | Lorene,Gilchrist,lgilchristnq@ning.com,China
857 | Courtney,Burrells,cburrellsnr@hostgator.com,Norway
858 | Bruce,Pasek,bpasekns@vimeo.com,Yemen
859 | Sauncho,Haibel,shaibelnt@dedecms.com,Peru
860 | Aymer,Bromhead,abromheadnu@quantcast.com,Guatemala
861 | Lombard,Yukhtin,lyukhtinnv@spotify.com,Greece
862 | Rebekah,Fleckno,rflecknonw@privacy.gov.au,China
863 | Willette,Witherdon,wwitherdonnx@g.co,Philippines
864 | Matthew,Geraldo,mgeraldony@etsy.com,Indonesia
865 | Gustavus,Simkovitz,gsimkovitznz@cdc.gov,China
866 | Izabel,Ricker,irickero0@angelfire.com,Czech Republic
867 | Correy,Standbrooke,cstandbrookeo1@pcworld.com,Indonesia
868 | Natka,Inworth,ninwortho2@imdb.com,Greece
869 | Rodrique,Filtness,rfiltnesso3@163.com,Peru
870 | Vanya,Saint,vsainto4@census.gov,Brazil
871 | Jasun,Circuitt,jcircuitto5@tmall.com,Colombia
872 | Letitia,Monroe,lmonroeo6@home.pl,Czech Republic
873 | Lisette,Crawshay,lcrawshayo7@japanpost.jp,Greece
874 | Bat,Delos,bdeloso8@hud.gov,Czech Republic
875 | Rhoda,Durrance,rdurranceo9@stanford.edu,Philippines
876 | Ollie,Dearl,odearloa@ucsd.edu,Israel
877 | Lizbeth,Comellini,lcomelliniob@live.com,Tunisia
878 | Letizia,Frossell,lfrosselloc@smh.com.au,Comoros
879 | Stacy,Grinnell,sgrinnellod@bloglovin.com,Sweden
880 | Clayson,De Dei,cdedeioe@utexas.edu,China
881 | Saul,Reedyhough,sreedyhoughof@gov.uk,China
882 | Allyson,Wegenen,awegenenog@loc.gov,Czech Republic
883 | Baxter,Gilfoyle,bgilfoyleoh@pcworld.com,France
884 | Irma,Babbs,ibabbsoi@census.gov,China
885 | Burt,Falks,bfalksoj@newsvine.com,China
886 | Agathe,MacKeogh,amackeoghok@csmonitor.com,Nigeria
887 | Florella,Hynd,fhyndol@tinypic.com,Bosnia and Herzegovina
888 | Mariya,Blanpein,mblanpeinom@slashdot.org,Russia
889 | Rodina,Bavester,rbavesteron@businessweek.com,Philippines
890 | Thacher,O' Cuolahan,tocuolahanoo@wp.com,Colombia
891 | Guinevere,Lortz,glortzop@accuweather.com,Colombia
892 | Marlo,Shurmer,mshurmeroq@shinystat.com,China
893 | Martynne,Storton,mstortonor@tinypic.com,China
894 | Ginger,Paulillo,gpaulilloos@joomla.org,China
895 | Brook,Gambie,bgambieot@discovery.com,Philippines
896 | Hebert,Muller,hmullerou@bandcamp.com,China
897 | Bradly,Castrillo,bcastrilloov@unblog.fr,Nigeria
898 | Nestor,Sturdy,nsturdyow@cargocollective.com,Ivory Coast
899 | Alyosha,Denecamp,adenecampox@ox.ac.uk,China
900 | Lief,Draye,ldrayeoy@1688.com,France
901 | Sig,Tanby,stanbyoz@tiny.cc,Ukraine
902 | Amargo,Canizares,acanizaresp0@aol.com,Ireland
903 | Vernice,Cirlos,vcirlosp1@delicious.com,New Zealand
904 | Morty,Lavers,mlaversp2@mapquest.com,Philippines
905 | Cathyleen,Sterling,csterlingp3@springer.com,South Korea
906 | Salome,Spalls,sspallsp4@businessweek.com,China
907 | Imogene,Woolacott,iwoolacottp5@woothemes.com,China
908 | Joaquin,Rieger,jriegerp6@census.gov,Colombia
909 | Brenda,Poston,bpostonp7@google.ru,Canada
910 | Juliette,Brayson,jbraysonp8@google.it,Japan
911 | Natalie,Mac,nmacp9@amazon.co.uk,Israel
912 | Elizabeth,Decroix,edecroixpa@istockphoto.com,Philippines
913 | Leon,Idney,lidneypb@kickstarter.com,China
914 | Vincent,Parsell,vparsellpc@nps.gov,Canada
915 | Rozella,Naden,rnadenpd@deliciousdays.com,Mexico
916 | Dede,Moorhead,dmoorheadpe@bravesites.com,China
917 | Nicolais,Morcombe,nmorcombepf@vinaora.com,Russia
918 | Stacee,Cullity,scullitypg@adobe.com,Croatia
919 | Sully,Village,svillageph@buzzfeed.com,Russia
920 | Ariella,Tunna,atunnapi@ifeng.com,China
921 | Adan,Trehearne,atrehearnepj@sourceforge.net,Indonesia
922 | Shannon,Steddall,ssteddallpk@mashable.com,China
923 | Marisa,Adamovitch,madamovitchpl@vinaora.com,Bulgaria
924 | Dorie,Tomankiewicz,dtomankiewiczpm@unesco.org,Croatia
925 | Bendicty,Loadwick,bloadwickpn@businessweek.com,Indonesia
926 | Cecelia,Pieroni,cpieronipo@toplist.cz,Ukraine
927 | Lewiss,Mc Ilwrick,lmcilwrickpp@reddit.com,Peru
928 | Delainey,Wisby,dwisbypq@loc.gov,Netherlands
929 | Barry,Ralestone,bralestonepr@addthis.com,Indonesia
930 | Hadley,Gerrelts,hgerreltsps@dailymotion.com,Sweden
931 | Rubia,Rosander,rrosanderpt@amazon.co.jp,China
932 | Corey,Aubrey,caubreypu@123-reg.co.uk,Brazil
933 | Renelle,O'Lagen,rolagenpv@usa.gov,Poland
934 | Haley,Braithwait,hbraithwaitpw@cocolog-nifty.com,Sweden
935 | Morley,Cottage,mcottagepx@surveymonkey.com,South Korea
936 | Emmott,Hundal,ehundalpy@mtv.com,Cameroon
937 | Laurette,Vanyukov,lvanyukovpz@aol.com,China
938 | Alisun,Studdal,astuddalq0@telegraph.co.uk,Bolivia
939 | Augusto,Durrell,adurrellq1@woothemes.com,Equatorial Guinea
940 | Jelene,Louedey,jlouedeyq2@chronoengine.com,Cameroon
941 | Ivan,Ronisch,ironischq3@scribd.com,Kyrgyzstan
942 | Sal,Gislebert,sgislebertq4@unesco.org,Honduras
943 | Lissy,Stanwix,lstanwixq5@engadget.com,China
944 | Rachel,Ubsdell,rubsdellq6@bloomberg.com,United States
945 | Yance,Retallick,yretallickq7@trellian.com,Albania
946 | Myranda,Ferdinand,mferdinandq8@mit.edu,Czech Republic
947 | Yehudit,Dorset,ydorsetq9@list-manage.com,China
948 | Lisetta,Drynan,ldrynanqa@va.gov,Poland
949 | Allene,Barajas,abarajasqb@amazon.com,Greece
950 | Lucilia,Costellow,lcostellowqc@scribd.com,South Africa
951 | Jamie,MacCook,jmaccookqd@bandcamp.com,China
952 | Dorine,Chadband,dchadbandqe@csmonitor.com,China
953 | Jocko,Brehault,jbrehaultqf@last.fm,China
954 | Grazia,Eyton,geytonqg@ycombinator.com,Argentina
955 | Zaria,Kemme,zkemmeqh@shutterfly.com,Panama
956 | Hastie,Fernant,hfernantqi@fda.gov,Argentina
957 | Edyth,Zywicki,ezywickiqj@japanpost.jp,Estonia
958 | Reuben,Croote,rcrooteqk@mysql.com,Dominican Republic
959 | Linea,Durtnall,ldurtnallql@apple.com,Japan
960 | Catherine,Jacomb,cjacombqm@xing.com,China
961 | Domenico,Westnedge,dwestnedgeqn@columbia.edu,Argentina
962 | Morly,Linfoot,mlinfootqo@oakley.com,Ukraine
963 | Iolanthe,Fenich,ifenichqp@godaddy.com,China
964 | Kiah,Piburn,kpiburnqq@blogs.com,Russia
965 | Tish,Phinnis,tphinnisqr@elpais.com,Poland
966 | Chelsey,Toffanelli,ctoffanelliqs@uol.com.br,Russia
967 | Celka,Paradis,cparadisqt@xinhuanet.com,China
968 | Kellie,Doghartie,kdoghartiequ@stumbleupon.com,Indonesia
969 | Salvador,Doggerell,sdoggerellqv@abc.net.au,Portugal
970 | Vaughan,Curnnok,vcurnnokqw@mozilla.com,Sweden
971 | Hallie,Ginn,hginnqx@mozilla.com,Sweden
972 | Arabella,Visick,avisickqy@jigsy.com,China
973 | Emmit,Svanini,esvaniniqz@tripadvisor.com,China
974 | Cordie,Ladewig,cladewigr0@surveymonkey.com,Finland
975 | Ninon,Stennet,nstennetr1@jimdo.com,Honduras
976 | Pamela,Element,pelementr2@i2i.jp,China
977 | Marijn,Jaynes,mjaynesr3@mtv.com,Indonesia
978 | Cindee,Sisse,csisser4@deviantart.com,Morocco
979 | Mollie,Charters,mchartersr5@woothemes.com,Peru
980 | Junette,Senechell,jsenechellr6@disqus.com,Indonesia
981 | Zulema,Exall,zexallr7@posterous.com,Indonesia
982 | Trudie,Machans,tmachansr8@hud.gov,Vietnam
983 | Marcel,Draysey,mdrayseyr9@list-manage.com,Peru
984 | Alvy,Sivyour,asivyourra@boston.com,Russia
985 | Tam,Kerrey,tkerreyrb@freewebs.com,Peru
986 | Izaak,Ditzel,iditzelrc@prlog.org,China
987 | Gisele,Swain,gswainrd@creativecommons.org,Greece
988 | Anne-marie,Corneliussen,acorneliussenre@shareasale.com,Seychelles
989 | Jodi,Airdrie,jairdrierf@delicious.com,Sri Lanka
990 | Benyamin,Clutterham,bclutterhamrg@bluehost.com,Indonesia
991 | Karie,Yeates,kyeatesrh@guardian.co.uk,Ireland
992 | Brady,Brennen,bbrennenri@senate.gov,Indonesia
993 | Riannon,Congrave,rcongraverj@marriott.com,Djibouti
994 | Vilhelmina,Liversedge,vliversedgerk@ft.com,France
995 | Rolland,Ledner,rlednerrl@uol.com.br,Philippines
996 | Farrell,Urch,furchrm@cyberchimps.com,Russia
997 | Ximenez,Mate,xmatern@buzzfeed.com,Brazil
998 | Martelle,Beswick,mbeswickro@blog.com,China
999 | Clea,Railton,crailtonrp@nydailynews.com,Indonesia
1000 | Yolande,Tansley,ytansleyrq@csmonitor.com,Indonesia
1001 | Dode,Wear,dwearrr@newyorker.com,Russia
1002 |
--------------------------------------------------------------------------------
/mysql/mysql.cnf:
--------------------------------------------------------------------------------
1 | [mysqld]
2 | server-id = 223344
3 | log_bin = mysql-bin
4 | expire_logs_days = 1
5 | binlog_format = row
--------------------------------------------------------------------------------
/mysql/mysql_bootstrap.sql:
--------------------------------------------------------------------------------
1 | CREATE DATABASE IF NOT EXISTS pizzashop;
2 | USE pizzashop;
3 |
4 | GRANT ALL PRIVILEGES ON pizzashop.* TO 'mysqluser';
5 | GRANT FILE on *.* to 'mysqluser';
6 |
7 | CREATE USER 'debezium' IDENTIFIED WITH mysql_native_password BY 'dbz';
8 |
9 | GRANT SELECT, RELOAD, SHOW DATABASES, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'debezium';
10 |
11 | FLUSH PRIVILEGES;
12 |
13 | CREATE TABLE IF NOT EXISTS pizzashop.users
14 | (
15 | id SERIAL PRIMARY KEY,
16 | first_name VARCHAR(255),
17 | last_name VARCHAR(255),
18 | email VARCHAR(255),
19 | country VARCHAR(255),
20 | created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
21 | updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
22 | );
23 |
24 | CREATE TABLE IF NOT EXISTS pizzashop.products
25 | (
26 | id SERIAL PRIMARY KEY,
27 | name VARCHAR(100),
28 | description VARCHAR(500),
29 | category VARCHAR(100),
30 | price FLOAT,
31 | image VARCHAR(200),
32 | created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
33 | updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
34 | );
35 |
36 | LOAD DATA INFILE '/var/lib/mysql-files/data/products.csv'
37 | INTO TABLE pizzashop.products
38 | FIELDS TERMINATED BY ','
39 | OPTIONALLY ENCLOSED BY '"'
40 | IGNORE 1 LINES
41 | (name,description,price,category,image);
42 |
43 | LOAD DATA INFILE '/var/lib/mysql-files/data/users.csv'
44 | INTO TABLE pizzashop.users
45 | FIELDS TERMINATED BY ','
46 | OPTIONALLY ENCLOSED BY '"'
47 | IGNORE 1 LINES
48 | (first_name,last_name,email,country);
--------------------------------------------------------------------------------
/orders-service/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.9.9-bullseye
2 |
3 | WORKDIR /workdir
4 |
5 | COPY requirements.txt .
6 |
7 | ENV VIRTUAL_ENV=/opt/venv
8 | RUN python3 -m venv $VIRTUAL_ENV
9 | ENV PATH="$VIRTUAL_ENV/bin:$PATH"
10 |
11 | RUN pip install --no-cache-dir -r requirements.txt
12 | RUN pip install --upgrade pip
13 |
14 | COPY . .
15 |
16 | ENTRYPOINT ["python", "multiseeder.py"]
--------------------------------------------------------------------------------
/orders-service/multiseeder.py:
--------------------------------------------------------------------------------
1 | import random, time
2 | from mysql.connector import connect, Error
3 | from faker import Faker
4 | from faker.providers import company
5 | import json
6 | from kafka import KafkaProducer
7 | import datetime
8 | import uuid
9 | import math
10 | import os
11 |
12 | # CONFIG
13 | usersLimit = 1000
14 | orderInterval = 100
15 | mysqlHost = os.environ.get("MYSQL_SERVER", "localhost")
16 | mysqlPort = '3306'
17 | mysqlUser = 'mysqluser'
18 | mysqlPass = 'mysqlpw'
19 | debeziumHostPort = 'debezium:8083'
20 | kafkaHostPort = f"{os.environ.get('KAFKA_BROKER_HOSTNAME', 'localhost')}:{os.environ.get('KAFKA_BROKER_PORT', '29092')}"
21 |
22 | print(f"Kafka broker: {kafkaHostPort}")
23 |
24 | producer = KafkaProducer(bootstrap_servers=kafkaHostPort, api_version=(7, 1, 0),
25 | value_serializer=lambda m: json.dumps(m).encode('utf-8'))
26 |
27 |
28 | events_processed = 0
29 | try:
30 | with connect(
31 | host=mysqlHost,
32 | user=mysqlUser,
33 | password=mysqlPass,
34 | ) as connection:
35 | with connection.cursor() as cursor:
36 | print("Getting products for the products topic")
37 | cursor.execute("SELECT id, name, description, category, price, image FROM pizzashop.products")
38 | products = [{
39 | "id": str(row[0]),
40 | "name": row[1],
41 | "description": row[2],
42 | "category": row[3],
43 | "price": row[4],
44 | "image": row[5]
45 | }
46 | for row in cursor
47 | ]
48 |
49 | for product in products:
50 | print(product["id"])
51 | producer.send('products', product, product["id"].encode("UTF-8"))
52 | producer.flush()
53 |
54 | cursor.execute("SELECT id FROM pizzashop.users")
55 | users = [row[0] for row in cursor]
56 |
57 | print("Getting product ID and PRICE as tuples...")
58 | cursor.execute("SELECT id, price FROM pizzashop.products")
59 | product_prices = [(row[0], row[1]) for row in cursor]
60 | print(product_prices)
61 |
62 | while True:
63 | # Get a random a user and a product to order
64 |
65 | number_of_items = random.randint(1,10)
66 |
67 | items = []
68 | for _ in range(0, number_of_items):
69 | product = random.choice(product_prices)
70 | user = random.choice(users)
71 | purchase_quantity = random.randint(1,5)
72 | items.append({
73 | "productId": str(product[0]),
74 | "quantity": purchase_quantity,
75 | "price": product[1]
76 | })
77 |
78 | prices = [item["quantity"] * item["price"] for item in items]
79 | total_price = round(math.fsum(prices), 2)
80 |
81 | event = {
82 | "id": str(uuid.uuid4()),
83 | "createdAt": datetime.datetime.now().isoformat(),
84 | "userId": user,
85 | "status": "PLACED_ORDER",
86 | "price": total_price,
87 | "items": items
88 | }
89 |
90 | producer.send('orders', event, bytes(event["id"].encode("UTF-8")))
91 |
92 | events_processed += 1
93 | if events_processed % 100 == 0:
94 | print(f"{str(datetime.datetime.now())} Flushing after {events_processed} events")
95 | producer.flush()
96 |
97 | time.sleep(random.randint(orderInterval/5, orderInterval)/1000)
98 |
99 | connection.close()
100 |
101 | except Error as e:
102 | print(e)
--------------------------------------------------------------------------------
/orders-service/requirements.txt:
--------------------------------------------------------------------------------
1 | Faker==13.15.0
2 | kafka-python==2.0.2
3 | mysql-connector-python==8.0.27
4 | requests==2.28.1
--------------------------------------------------------------------------------
/orders-service/seeder.py:
--------------------------------------------------------------------------------
1 | import random, time
2 | from mysql.connector import connect, Error
3 | from faker import Faker
4 | from faker.providers import company
5 | import json
6 | from kafka import KafkaProducer
7 | import datetime
8 | import uuid
9 |
10 | # CONFIG
11 | usersLimit = 1000
12 | orderInterval = 100
13 | mysqlHost = 'mysql'
14 | mysqlPort = '3306'
15 | mysqlUser = 'mysqluser'
16 | mysqlPass = 'mysqlpw'
17 | debeziumHostPort = 'debezium:8083'
18 | kafkaHostPort = 'kafka:9092'
19 |
20 | producer = KafkaProducer(bootstrap_servers=kafkaHostPort, api_version=(7, 1, 0),
21 | value_serializer=lambda m: json.dumps(m).encode('utf-8'))
22 |
23 |
24 | events_processed = 0
25 | try:
26 | with connect(
27 | host=mysqlHost,
28 | user=mysqlUser,
29 | password=mysqlPass,
30 | ) as connection:
31 | with connection.cursor() as cursor:
32 | print("Getting products for the products topic")
33 | cursor.execute("SELECT id, name, description, category, price, image FROM pizzashop.products")
34 | products = [{
35 | "id": row[0],
36 | "name": row[1],
37 | "description": row[2],
38 | "category": row[3],
39 | "price": row[4],
40 | "image": row[5]
41 | }
42 | for row in cursor
43 | ]
44 |
45 | for product in products:
46 | producer.send('products', product, bytes(product["id"]))
47 | producer.flush()
48 |
49 | print("Getting product ID and PRICE as tuples...")
50 | cursor.execute("SELECT id, price FROM pizzashop.products")
51 | product_prices = [(row[0], row[1]) for row in cursor]
52 | print(product_prices)
53 |
54 | while True:
55 | # Get a random a user and a product to order
56 | product = random.choice(product_prices)
57 | user = random.randint(0,usersLimit-1)
58 | purchase_quantity = random.randint(1,5)
59 |
60 | event = {
61 | "id": str(uuid.uuid4()),
62 | "createdAt": datetime.datetime.now().isoformat(),
63 | "userId": user,
64 | "productId": product[0],
65 | "quantity": purchase_quantity,
66 | "total": product[1] * purchase_quantity,
67 | "status": "PLACED_ORDER"
68 | }
69 |
70 | producer.send('orders', event, bytes(event["productId"]))
71 |
72 | events_processed += 1
73 | if events_processed % 100 == 0:
74 | print(f"{str(datetime.datetime.now())} Flushing after {events_processed} events")
75 | producer.flush()
76 |
77 | time.sleep(random.randint(orderInterval/5, orderInterval)/1000)
78 |
79 | connection.close()
80 |
81 | except Error as e:
82 | print(e)
--------------------------------------------------------------------------------
/pinot/config/order_items_enriched/schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "schemaName": "order_items_enriched",
3 | "dimensionFieldSpecs": [
4 | {
5 | "name": "orderId",
6 | "dataType": "STRING"
7 | },
8 | {
9 | "name": "product.id",
10 | "dataType": "STRING"
11 | },
12 | {
13 | "name": "product.name",
14 | "dataType": "STRING"
15 | },
16 | {
17 | "name": "product.category",
18 | "dataType": "STRING"
19 | },
20 | {
21 | "name": "product.image",
22 | "dataType": "STRING"
23 | }
24 | ],
25 | "metricFieldSpecs": [
26 | {
27 | "name": "product.price",
28 | "dataType": "DOUBLE"
29 | },
30 | {
31 | "name": "orderItem.quantity",
32 | "dataType": "INT"
33 | }
34 | ],
35 | "dateTimeFieldSpecs": [
36 | {
37 | "name": "ts",
38 | "dataType": "TIMESTAMP",
39 | "format": "1:MILLISECONDS:EPOCH",
40 | "granularity": "1:MILLISECONDS"
41 | }
42 | ]
43 | }
--------------------------------------------------------------------------------
/pinot/config/order_items_enriched/table.json:
--------------------------------------------------------------------------------
1 | {
2 | "tableName": "order_items_enriched",
3 | "tableType": "REALTIME",
4 | "segmentsConfig": {
5 | "timeColumnName": "ts",
6 | "timeType": "MILLISECONDS",
7 | "retentionTimeUnit": "DAYS",
8 | "retentionTimeValue": "1",
9 | "schemaName": "order_items_enriched",
10 | "replicasPerPartition": "1"
11 | },
12 | "tenants": {},
13 | "tableIndexConfig": {
14 | "loadMode": "MMAP",
15 | "streamConfigs": {
16 | "streamType": "kafka",
17 | "stream.kafka.consumer.type": "lowLevel",
18 | "stream.kafka.topic.name": "enriched-order-items",
19 | "stream.kafka.decoder.class.name": "org.apache.pinot.plugin.stream.kafka.KafkaJSONMessageDecoder",
20 | "stream.kafka.consumer.factory.class.name": "org.apache.pinot.plugin.stream.kafka20.KafkaConsumerFactory",
21 | "stream.kafka.broker.list": "kafka:9092",
22 | "stream.kafka.consumer.prop.auto.offset.reset": "smallest"
23 | }
24 | },
25 | "ingestionConfig": {
26 | "complexTypeConfig": {
27 | "delimeter": ".",
28 | "fieldsToUnnest": [
29 | "items"
30 | ]
31 | },
32 | "transformConfigs": [
33 | {
34 | "columnName": "ts",
35 | "transformFunction": "FromDateTime(\"createdAt\", 'yyyy-MM-dd''T''HH:mm:ss.SSSSSS')"
36 | }
37 | ]
38 | },
39 | "metadata": {
40 | "customConfigs": {}
41 | },
42 | "routing": {
43 | "instanceSelectorType": "strictReplicaGroup"
44 | }
45 | }
--------------------------------------------------------------------------------
/pinot/config/orders/schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "schemaName": "orders",
3 | "dimensionFieldSpecs": [
4 | {"name": "id", "dataType": "STRING"},
5 | {"name": "userId", "dataType": "INT"},
6 | {"name": "status", "dataType": "STRING"},
7 | {"name": "items", "dataType": "JSON"}
8 | ],
9 | "metricFieldSpecs": [
10 | {"name": "productsOrdered", "dataType": "INT"},
11 | {"name": "totalQuantity", "dataType": "INT"},
12 | {"name": "price", "dataType": "DOUBLE"}
13 | ],
14 | "dateTimeFieldSpecs": [
15 | {
16 | "name": "ts",
17 | "dataType": "TIMESTAMP",
18 | "format": "1:MILLISECONDS:EPOCH",
19 | "granularity": "1:MILLISECONDS"
20 | }
21 | ]
22 | }
23 |
--------------------------------------------------------------------------------
/pinot/config/orders/table.json:
--------------------------------------------------------------------------------
1 | {
2 | "tableName": "orders",
3 | "tableType": "REALTIME",
4 | "segmentsConfig": {
5 | "timeColumnName": "ts",
6 | "timeType": "MILLISECONDS",
7 | "retentionTimeUnit": "DAYS",
8 | "retentionTimeValue": "1",
9 | "schemaName": "orders",
10 | "replicasPerPartition": "1"
11 | },
12 | "tenants": {},
13 | "tableIndexConfig": {
14 | "loadMode": "MMAP",
15 | "streamConfigs": {
16 | "streamType": "kafka",
17 | "stream.kafka.consumer.type": "lowLevel",
18 | "stream.kafka.topic.name": "orders",
19 | "stream.kafka.decoder.class.name": "org.apache.pinot.plugin.stream.kafka.KafkaJSONMessageDecoder",
20 | "stream.kafka.consumer.factory.class.name": "org.apache.pinot.plugin.stream.kafka20.KafkaConsumerFactory",
21 | "stream.kafka.broker.list": "kafka:9092",
22 | "stream.kafka.consumer.prop.auto.offset.reset": "smallest"
23 | }
24 | },
25 | "ingestionConfig": {
26 | "complexTypeConfig": {
27 | "delimeter": "."
28 | },
29 | "transformConfigs": [
30 | {
31 | "columnName": "ts",
32 | "transformFunction": "FromDateTime(createdAt, 'yyyy-MM-dd''T''HH:mm:ss.SSSSSS')"
33 | },
34 | {
35 | "columnName": "totalQuantity",
36 | "transformFunction": "JSONPATHLONG(items, '$.sum($.[*].quantity)')"
37 | },
38 | {
39 | "columnName": "productsOrdered",
40 | "transformFunction": "JSONPATHARRAY(items, '$.length()')"
41 | }
42 | ]
43 | },
44 | "metadata": {
45 | "customConfigs": {}
46 | },
47 | "routing": {
48 | "instanceSelectorType": "strictReplicaGroup"
49 | }
50 | }
--------------------------------------------------------------------------------
/pinot/config/orders_enriched/schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "schemaName": "orders_enriched",
3 | "dimensionFieldSpecs": [
4 | {
5 | "name": "id",
6 | "dataType": "STRING"
7 | },
8 | {
9 | "name": "userId",
10 | "dataType": "INT"
11 | },
12 | {
13 | "name": "status",
14 | "dataType": "STRING"
15 | },
16 | {
17 | "name": "items",
18 | "dataType": "JSON"
19 | }
20 | ],
21 | "metricFieldSpecs": [
22 | {
23 | "name": "price",
24 | "dataType": "DOUBLE"
25 | }
26 | ],
27 | "dateTimeFieldSpecs": [
28 | {
29 | "name": "ts",
30 | "dataType": "TIMESTAMP",
31 | "format": "1:MILLISECONDS:EPOCH",
32 | "granularity": "1:MILLISECONDS"
33 | }
34 | ]
35 | }
--------------------------------------------------------------------------------
/pinot/config/orders_enriched/table.json:
--------------------------------------------------------------------------------
1 | {
2 | "tableName": "orders_enriched",
3 | "tableType": "REALTIME",
4 | "segmentsConfig": {
5 | "timeColumnName": "ts",
6 | "timeType": "MILLISECONDS",
7 | "retentionTimeUnit": "DAYS",
8 | "retentionTimeValue": "1",
9 | "schemaName": "orders_enriched",
10 | "replicasPerPartition": "1"
11 | },
12 | "tenants": {},
13 | "tableIndexConfig": {
14 | "loadMode": "MMAP",
15 | "streamConfigs": {
16 | "streamType": "kafka",
17 | "stream.kafka.consumer.type": "lowLevel",
18 | "stream.kafka.topic.name": "enriched-orders",
19 | "stream.kafka.decoder.class.name": "org.apache.pinot.plugin.stream.kafka.KafkaJSONMessageDecoder",
20 | "stream.kafka.consumer.factory.class.name": "org.apache.pinot.plugin.stream.kafka20.KafkaConsumerFactory",
21 | "stream.kafka.broker.list": "kafka:9092",
22 | "stream.kafka.consumer.prop.auto.offset.reset": "smallest"
23 | }
24 | },
25 | "ingestionConfig": {
26 | "complexTypeConfig": {
27 | "delimeter": "."
28 | },
29 | "transformConfigs": [
30 | {
31 | "columnName": "ts",
32 | "transformFunction": "FromDateTime(\"createdAt\", 'yyyy-MM-dd''T''HH:mm:ss.SSSSSS')"
33 | }
34 | ]
35 | },
36 | "metadata": {
37 | "customConfigs": {}
38 | },
39 | "routing": {
40 | "instanceSelectorType": "strictReplicaGroup"
41 | }
42 | }
--------------------------------------------------------------------------------
/pinot/config/schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "schemaName": "orders",
3 | "dimensionFieldSpecs": [
4 | {
5 | "name": "id",
6 | "dataType": "STRING"
7 | },
8 | {
9 | "name": "userId",
10 | "dataType": "INT"
11 | },
12 | {
13 | "name": "productId",
14 | "dataType": "INT"
15 | },
16 | {
17 | "name": "status",
18 | "dataType": "STRING"
19 | }
20 | ],
21 | "metricFieldSpecs": [
22 | {
23 | "name": "quantity",
24 | "dataType": "INT"
25 | },
26 | {
27 | "name": "total",
28 | "dataType": "DOUBLE"
29 | }
30 | ],
31 | "dateTimeFieldSpecs": [
32 | {
33 | "name": "ts",
34 | "dataType": "TIMESTAMP",
35 | "format": "1:MILLISECONDS:EPOCH",
36 | "granularity": "1:MILLISECONDS"
37 | }
38 | ]
39 | }
--------------------------------------------------------------------------------
/pinot/config/table.json:
--------------------------------------------------------------------------------
1 | {
2 | "tableName": "orders",
3 | "tableType": "REALTIME",
4 | "segmentsConfig": {
5 | "timeColumnName": "ts",
6 | "timeType": "MILLISECONDS",
7 | "retentionTimeUnit": "DAYS",
8 | "retentionTimeValue": "1",
9 | "schemaName": "orders",
10 | "replicasPerPartition": "1"
11 | },
12 | "tenants": {},
13 | "tableIndexConfig": {
14 | "loadMode": "MMAP",
15 | "streamConfigs": {
16 | "streamType": "kafka",
17 | "stream.kafka.consumer.type": "lowLevel",
18 | "stream.kafka.topic.name": "orders",
19 | "stream.kafka.decoder.class.name": "org.apache.pinot.plugin.stream.kafka.KafkaJSONMessageDecoder",
20 | "stream.kafka.consumer.factory.class.name": "org.apache.pinot.plugin.stream.kafka20.KafkaConsumerFactory",
21 | "stream.kafka.broker.list": "kafka:9092",
22 | "realtime.segment.flush.threshold.size": 30,
23 | "realtime.segment.flush.threshold.rows": 30,
24 | "stream.kafka.consumer.prop.auto.offset.reset": "smallest"
25 | }
26 | },
27 | "ingestionConfig": {
28 | "complexTypeConfig": {
29 | "delimeter": "."
30 | },
31 | "transformConfigs": [
32 | {
33 | "columnName": "ts",
34 | "transformFunction": "FromDateTime(createdAt, 'yyyy-MM-dd''T''HH:mm:ss.SSSSSS')"
35 | }
36 | ]
37 | },
38 | "metadata": {
39 | "customConfigs": {}
40 | },
41 | "routing": {
42 | "instanceSelectorType": "strictReplicaGroup"
43 | }
44 | }
--------------------------------------------------------------------------------
/raw_data/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/startreedata/pizza-shop-demo/b054ac85925e0033604499caabbe7aed87ed0827/raw_data/.gitkeep
--------------------------------------------------------------------------------
/scripts/add_tables.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | ./bin/pinot-admin.sh AddTable -schemaFile /config/orders/schema.json -tableConfigFile /config/orders/table.json -controllerHost pinot-controller -exec
4 | status1=$?
5 |
6 | if [ "$status1" = "255" ] || [ "$status1" = "0" ]
7 | then
8 | ./bin/pinot-admin.sh AddTable -schemaFile /config/order_items_enriched/schema.json -tableConfigFile /config/order_items_enriched/table.json -controllerHost pinot-controller -exec
9 | status2=$?
10 |
11 | if [ "$status2" = "255" ] || [ "$status2" = "0" ]
12 | then
13 | exit 0
14 | else
15 | exit $status2
16 | fi
17 | else
18 | exit $status1
19 | fi
--------------------------------------------------------------------------------
/scripts/download_products.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | import requests
4 | from bs4 import BeautifulSoup
5 |
6 | response = requests.get("https://www.dominos.co.in/product-item-pages.xml")
7 |
8 | soup = BeautifulSoup(response.text, 'xml')
9 |
10 | urls = [item.text for item in soup.select("url loc")]
11 |
12 | for url in urls:
13 | print(url)
14 | file_name = f"raw_data/{url.split('/')[-1]}"
15 |
16 | if not os.path.isfile(file_name):
17 | product_response = requests.get(url)
18 | with requests.get(url, stream=True) as r:
19 | with open(file_name, 'wb') as f:
20 | for chunk in r.iter_content(chunk_size=8192):
21 | f.write(chunk)
22 |
--------------------------------------------------------------------------------
/scripts/requirements.txt:
--------------------------------------------------------------------------------
1 | beautifulsoup4==4.11.1
2 | lxml==4.9.1
3 | requests==2.28.1
4 |
--------------------------------------------------------------------------------
/scripts/scrape_products.py:
--------------------------------------------------------------------------------
1 | import csv
2 | import glob
3 | import json
4 |
5 | from bs4 import BeautifulSoup
6 |
7 | with open("mysql/data/products.csv", "w") as products_file:
8 | writer = csv.writer(products_file, delimiter=",")
9 |
10 | writer.writerow(["name", "description", "price", "category", "image"])
11 |
12 | for file_name in glob.glob("raw_data/*"):
13 | # print(file_name)
14 |
15 | with open(file_name, "r") as file:
16 | soup = BeautifulSoup(file.read(), 'html.parser')
17 |
18 | name_element = soup.select("h1 span")
19 |
20 | if len(name_element) > 0:
21 | name = soup.select("h1 span")[0].text
22 |
23 | description_element = soup.select("section#main-section-mobile div.p-text-description.lead p")
24 | description = description_element[0].text if len(description_element) > 0 else ""
25 |
26 | category = [item.text for item in soup.select("ul.breadcrumb li a span")][-2]
27 | image = soup.select("div.col-md-6 img.element-left-40")[0]["src"]
28 | crusts = [item.text.strip() for item in soup.select("ul.ul-list.features-list.element-top-1 li")]
29 |
30 | crust_sizes_element = soup.select("div.col-md-12.col-xs-12 p.sub-description.lead")
31 | crust_sizes = [item.strip() for item in crust_sizes_element[0].text.strip().split("|")] if len(crust_sizes_element) > 0 else ["regular", "medium", "large"]
32 |
33 | prices_table = [[col.text.strip() for col in item.select("th")] for item in soup.select("section#main-section table tr")]
34 | prices = {item[0]: item[1] for item in prices_table}
35 |
36 | price = soup.select("section#main-section span.price.text-left")[0].text.strip()
37 |
38 | if price == "":
39 | continue
40 |
41 | item = {
42 | "name": " ".join([word.capitalize() for word in name.split(" ")]),
43 | "description": description,
44 | "price": price,
45 | "category": category,
46 | "image": image
47 | }
48 |
49 | if category != "beverages":
50 | item = {**item,
51 | "crusts": crusts,
52 | "crustSizes": crust_sizes,
53 | "prices": prices
54 | }
55 |
56 | writer.writerow([item["name"], item["description"], float(item["price"]), item["category"], item["image"]])
57 |
58 | print(json.dumps(item))
59 |
--------------------------------------------------------------------------------
/streamlit/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.9.9-bullseye
2 |
3 | WORKDIR /workdir
4 |
5 | COPY requirements.txt .
6 |
7 | ENV VIRTUAL_ENV=/opt/venv
8 | RUN python3 -m venv $VIRTUAL_ENV
9 | ENV PATH="$VIRTUAL_ENV/bin:$PATH"
10 |
11 | RUN pip install --no-cache-dir -r requirements.txt
12 | RUN pip install --upgrade pip
13 |
14 | COPY app.py .
15 |
16 | ENTRYPOINT ["streamlit", "run", "app.py"]
--------------------------------------------------------------------------------
/streamlit/app.py:
--------------------------------------------------------------------------------
1 | from turtle import width
2 | import streamlit as st
3 | import pandas as pd
4 | from pinotdb import connect
5 | from datetime import datetime
6 | import time
7 | import plotly.express as px
8 | import plotly.graph_objects as go
9 | import os
10 |
11 | pinot_host=os.environ.get("PINOT_SERVER", "pinot-broker")
12 | pinot_port=os.environ.get("PINOT_PORT", 8099)
13 | conn = connect(pinot_host, pinot_port)
14 |
15 | st.set_page_config(layout="wide")
16 | st.title("All About That Dough Dashboard 🍕")
17 |
18 | now = datetime.now()
19 | dt_string = now.strftime("%d %B %Y %H:%M:%S")
20 | st.write(f"Last update: {dt_string}")
21 |
22 | # Use session state to keep track of whether we need to auto refresh the page and the refresh frequency
23 |
24 | if not "sleep_time" in st.session_state:
25 | st.session_state.sleep_time = 2
26 |
27 | if not "auto_refresh" in st.session_state:
28 | st.session_state.auto_refresh = True
29 |
30 | auto_refresh = st.checkbox('Auto Refresh?', st.session_state.auto_refresh)
31 |
32 | if auto_refresh:
33 | number = st.number_input('Refresh rate in seconds', value=st.session_state.sleep_time)
34 | st.session_state.sleep_time = number
35 |
36 | curs = conn.cursor()
37 |
38 | pinot_available = False
39 | try:
40 | curs.execute("select * FROM orders where ts > ago('PT2M')")
41 | if not curs.description:
42 | st.warning("Connected to Pinot, but no orders imported",icon="⚠️")
43 |
44 | pinot_available = curs.description is not None
45 | except Exception as e:
46 | st.warning(f"""Unable to connect to or query Apache Pinot [{pinot_host}:{pinot_port}]
47 |
48 | Exception: {e}""",icon="⚠️")
49 |
50 | if pinot_available:
51 | query = """
52 | select count(*) FILTER(WHERE ts > ago('PT1M')) AS events1Min,
53 | count(*) FILTER(WHERE ts <= ago('PT1M') AND ts > ago('PT2M')) AS events1Min2Min,
54 | sum(price) FILTER(WHERE ts > ago('PT1M')) AS total1Min,
55 | sum(price) FILTER(WHERE ts <= ago('PT1M') AND ts > ago('PT2M')) AS total1Min2Min
56 | from orders
57 | where ts > ago('PT2M')
58 | limit 1
59 | """
60 | curs.execute(query)
61 |
62 | df = pd.DataFrame(curs, columns=[item[0] for item in curs.description])
63 | st.subheader("Orders in the last minute")
64 |
65 | metric1, metric2, metric3 = st.columns(3)
66 |
67 |
68 | metric1.metric(
69 | label="# of Orders",
70 | value="{:,}".format(int(df['events1Min'].values[0])),
71 | delta="{:,}".format(int(df['events1Min'].values[0] - df['events1Min2Min'].values[0]))
72 | if df['events1Min2Min'].values[0] > 0 else None
73 | )
74 |
75 |
76 | metric2.metric(
77 | label="Revenue in ₹",
78 | value="{:,.2f}".format(df['total1Min'].values[0]),
79 | delta="{:,.2f}".format(df['total1Min'].values[0] - df['total1Min2Min'].values[0])
80 | if df['total1Min2Min'].values[0] > 0 else None
81 | )
82 |
83 | average_order_value_1min = df['total1Min'].values[0] / int(df['events1Min'].values[0])
84 | average_order_value_1min_2min = (df['total1Min2Min'].values[0] / int(df['events1Min2Min'].values[0])
85 | if int(df['events1Min2Min'].values[0]) > 0
86 | else 0)
87 |
88 | metric3.metric(
89 | label="Average order value in ₹",
90 | value="{:,.2f}".format(average_order_value_1min),
91 | delta="{:,.2f}".format(average_order_value_1min - average_order_value_1min_2min)
92 | if average_order_value_1min_2min > 0 else None
93 | )
94 |
95 | query = """
96 | select ToDateTime(DATETRUNC('minute', ts), 'yyyy-MM-dd HH:mm:ss') AS dateMin,
97 | count(*) AS orders,
98 | sum(price) AS revenue
99 | from orders
100 | where ts > ago('PT1H')
101 | group by dateMin
102 | order by dateMin desc
103 | LIMIT 10000
104 | """
105 |
106 | curs.execute(query)
107 |
108 | df_ts = pd.DataFrame(curs, columns=[item[0] for item in curs.description])
109 |
110 | if df_ts.shape[0] > 1:
111 | df_ts_melt = pd.melt(df_ts, id_vars=['dateMin'], value_vars=['revenue', 'orders'])
112 |
113 | col1, col2 = st.columns(2)
114 | with col1:
115 | orders = df_ts_melt[df_ts_melt.variable == "orders"]
116 | latest_date = orders.dateMin.max()
117 | latest_date_but_one = (orders.sort_values(by=["dateMin"], ascending=False)
118 | .iloc[[1]].dateMin.values[0])
119 |
120 | revenue_complete = orders[orders.dateMin < latest_date]
121 | revenue_incomplete = orders[orders.dateMin >= latest_date_but_one]
122 |
123 | fig = go.FigureWidget(data=[
124 | go.Scatter(x=revenue_complete.dateMin,
125 | y=revenue_complete.value, mode='lines',
126 | line={'dash': 'solid', 'color': 'green'}),
127 | go.Scatter(x=revenue_incomplete.dateMin,
128 | y=revenue_incomplete.value, mode='lines',
129 | line={'dash': 'dash', 'color': 'green'}),
130 | ])
131 | fig.update_layout(showlegend=False, title="Orders per minute",
132 | margin=dict(l=0, r=0, t=40, b=0),)
133 | fig.update_yaxes(range=[0, df_ts["orders"].max() * 1.1])
134 | st.plotly_chart(fig, use_container_width=True)
135 |
136 | with col2:
137 | revenue = df_ts_melt[df_ts_melt.variable == "revenue"]
138 | latest_date = revenue.dateMin.max()
139 | latest_date_but_one = (revenue.sort_values(by=["dateMin"], ascending=False)
140 | .iloc[[1]].dateMin.values[0])
141 |
142 | revenue_complete = revenue[revenue.dateMin < latest_date]
143 | revenue_incomplete = revenue[revenue.dateMin >=
144 | latest_date_but_one]
145 |
146 | fig = go.FigureWidget(data=[
147 | go.Scatter(x=revenue_complete.dateMin,
148 | y=revenue_complete.value, mode='lines',
149 | line={'dash': 'solid', 'color': 'blue'}),
150 | go.Scatter(x=revenue_incomplete.dateMin,
151 | y=revenue_incomplete.value, mode='lines',
152 | line={'dash': 'dash', 'color': 'blue'}),
153 | ])
154 | fig.update_layout(showlegend=False, title="Revenue per minute",
155 | margin=dict(l=0, r=0, t=40, b=0),)
156 | fig.update_yaxes(range=[0, df_ts["revenue"].max() * 1.1])
157 | st.plotly_chart(fig, use_container_width=True)
158 |
159 | curs.execute("""
160 | SELECT ToDateTime(ts, 'HH:mm:ss:SSS') AS dateTime, status, price, userId, productsOrdered, totalQuantity
161 | FROM orders
162 | ORDER BY ts DESC
163 | LIMIT 10
164 | """)
165 |
166 | df = pd.DataFrame(curs, columns=[item[0] for item in curs.description])
167 |
168 | st.subheader("Latest Orders")
169 |
170 | # CSS to inject contained in a string
171 | hide_table_row_index = """
172 |
176 | """
177 |
178 | # Inject CSS with Markdown
179 | st.markdown(hide_table_row_index, unsafe_allow_html=True)
180 |
181 | st.markdown(
182 | df.to_html(),
183 | unsafe_allow_html=True
184 | )
185 |
186 | curs.close()
187 |
188 | if auto_refresh:
189 | time.sleep(number)
190 | st.experimental_rerun()
--------------------------------------------------------------------------------
/streamlit/app_enriched.py:
--------------------------------------------------------------------------------
1 | import streamlit as st
2 | import pandas as pd
3 | from pinotdb import connect
4 | from datetime import datetime
5 | import time
6 | import plotly.graph_objects as go
7 | import os
8 |
9 | pinot_host = os.environ.get("PINOT_SERVER", "pinot-broker")
10 | pinot_port = os.environ.get("PINOT_PORT", 8099)
11 | conn = connect(pinot_host, pinot_port)
12 |
13 | st.set_page_config(layout="wide")
14 | st.title("All About That Dough Dashboard 🍕")
15 |
16 | now = datetime.now()
17 | dt_string = now.strftime("%B %-d, %Y at %-I:%M:%S %p")
18 | st.info(f"**Last update:** {dt_string}", icon="ℹ️")
19 |
20 | # Use session state to keep track of whether we need to auto refresh the page and the refresh frequency
21 | if not "sleep_time" in st.session_state:
22 | st.session_state.sleep_time = 5
23 |
24 | if not "auto_refresh" in st.session_state:
25 | st.session_state.auto_refresh = True
26 |
27 | mapping2 = {
28 | "1 hour": {"period": "PT60M", "previousPeriod": "PT120M", "granularity": "minute"},
29 | "30 minutes": {"period": "PT30M", "previousPeriod": "PT60M", "granularity": "minute"},
30 | "10 minutes": {"period": "PT10M", "previousPeriod": "PT20M", "granularity": "second"},
31 | "5 minutes": {"period": "PT5M", "previousPeriod": "PT10M", "granularity": "second"},
32 | "1 minute": {"period": "PT1M", "previousPeriod": "PT2M", "granularity": "second"}
33 | }
34 |
35 | with st.expander("Dashboard settings", expanded=True):
36 | if st.session_state.auto_refresh:
37 | left, right = st.columns(2)
38 |
39 | with left:
40 | auto_refresh = st.toggle('Auto-refresh', value=st.session_state.auto_refresh)
41 |
42 | if auto_refresh:
43 | number = st.number_input('Refresh rate in seconds', value=st.session_state.sleep_time)
44 | st.session_state.sleep_time = number
45 |
46 | with right:
47 | time_ago = st.radio("Display data from the last", mapping2.keys(), horizontal=True, key="time_ago", index=len(mapping2.keys()) - 1)
48 |
49 | curs = conn.cursor()
50 |
51 | pinot_available = False
52 | try:
53 | curs.execute("select * FROM orders where ts > ago('PT2M')")
54 | if not curs.description:
55 | st.warning("Connected to Pinot, but no orders imported", icon="⚠️")
56 |
57 | pinot_available = curs.description is not None
58 | except Exception as e:
59 | st.warning(f"""Unable to connect to or query Apache Pinot [{pinot_host}:{pinot_port}] Exception: {e}""", icon="⚠️")
60 |
61 | if pinot_available:
62 | query = """
63 | select count(*) FILTER(WHERE ts > ago(%(nearTimeAgo)s)) AS events1Min,
64 | count(*) FILTER(WHERE ts <= ago(%(nearTimeAgo)s) AND ts > ago(%(timeAgo)s)) AS events1Min2Min,
65 | sum("price") FILTER(WHERE ts > ago(%(nearTimeAgo)s)) AS total1Min,
66 | sum("price") FILTER(WHERE ts <= ago(%(nearTimeAgo)s) AND ts > ago(%(timeAgo)s)) AS total1Min2Min
67 | from orders
68 | where ts > ago(%(timeAgo)s)
69 | limit 1
70 | """
71 |
72 | curs.execute(query, {
73 | "timeAgo": mapping2[time_ago]["previousPeriod"],
74 | "nearTimeAgo": mapping2[time_ago]["period"]
75 | })
76 |
77 | df = pd.DataFrame(curs, columns=[item[0] for item in curs.description])
78 | metrics_container = st.container(border=True)
79 | metrics_container.subheader(f"Orders in the last {time_ago}")
80 |
81 | num_orders, rev, order_val = metrics_container.columns(3)
82 | num_orders.metric(
83 | label="Number of orders",
84 | value="{:,}".format(int(df['events1Min'].values[0])),
85 | delta="{:,}".format(int(df['events1Min'].values[0] - df['events1Min2Min'].values[0])) if df['events1Min2Min'].values[0] > 0 else None
86 | )
87 |
88 | rev.metric(
89 | label="Revenue in ₹",
90 | value="{:,.2f}".format(df['total1Min'].values[0]),
91 | delta="{:,.2f}".format(df['total1Min'].values[0] - df['total1Min2Min'].values[0]) if df['total1Min2Min'].values[0] > 0 else None
92 | )
93 |
94 | average_order_value_1min = df['total1Min'].values[0] / int(df['events1Min'].values[0])
95 | average_order_value_1min_2min = df['total1Min2Min'].values[0] / int(df['events1Min2Min'].values[0]) if int(df['events1Min2Min'].values[0]) > 0 else 0
96 |
97 | order_val.metric(
98 | label="Average order value in ₹",
99 | value="{:,.2f}".format(average_order_value_1min),
100 | delta="{:,.2f}".format(average_order_value_1min - average_order_value_1min_2min) if average_order_value_1min_2min > 0 else None
101 | )
102 |
103 | query = """
104 | select ToDateTime(DATETRUNC(%(granularity)s, ts), 'yyyy-MM-dd HH:mm:ss') AS dateMin,
105 | count(*) AS orders,
106 | sum(price) AS revenue
107 | from orders
108 | where ts > ago(%(timeAgo)s)
109 | group by dateMin
110 | order by dateMin desc
111 | LIMIT 10000
112 | """
113 |
114 | curs.execute(query, {"timeAgo": mapping2[time_ago]["period"], "granularity": mapping2[time_ago]["granularity"]})
115 |
116 | df_ts = pd.DataFrame(curs, columns=[item[0] for item in curs.description])
117 |
118 | if df_ts.shape[0] > 1:
119 | df_ts_melt = pd.melt(df_ts, id_vars=['dateMin'], value_vars=['revenue', 'orders'])
120 |
121 | col1, col2 = st.columns(2)
122 | with col1:
123 | orders = df_ts_melt[df_ts_melt.variable == "orders"]
124 | latest_date = orders.dateMin.max()
125 | latest_date_but_one = orders.sort_values(by=["dateMin"], ascending=False).iloc[[1]].dateMin.values[0]
126 |
127 | revenue_complete = orders[orders.dateMin < latest_date]
128 | revenue_incomplete = orders[orders.dateMin >= latest_date_but_one]
129 |
130 | fig = go.FigureWidget(data=[
131 | go.Scatter(x=revenue_complete.dateMin, y=revenue_complete.value, mode='lines', line={'dash': 'solid', 'color': 'green'}),
132 | go.Scatter(x=revenue_incomplete.dateMin, y=revenue_incomplete.value, mode='lines', line={'dash': 'dash', 'color': 'green'}),
133 | ])
134 | fig.update_layout(showlegend=False, title=f"Orders per {mapping2[time_ago]['granularity']}", margin=dict(l=0, r=0, t=40, b=0), )
135 | fig.update_yaxes(range=[0, df_ts["orders"].max() * 1.1])
136 | with st.container(border=True):
137 | st.plotly_chart(fig, use_container_width=True)
138 |
139 | with col2:
140 | revenue = df_ts_melt[df_ts_melt.variable == "revenue"]
141 | latest_date = revenue.dateMin.max()
142 | latest_date_but_one = revenue.sort_values(by=["dateMin"], ascending=False).iloc[[1]].dateMin.values[0]
143 |
144 | revenue_complete = revenue[revenue.dateMin < latest_date]
145 | revenue_incomplete = revenue[revenue.dateMin >= latest_date_but_one]
146 |
147 | fig = go.FigureWidget(data=[
148 | go.Scatter(x=revenue_complete.dateMin, y=revenue_complete.value, mode='lines', line={'dash': 'solid', 'color': 'blue'}),
149 | go.Scatter(x=revenue_incomplete.dateMin, y=revenue_incomplete.value, mode='lines', line={'dash': 'dash', 'color': 'blue'}),
150 | ])
151 | fig.update_layout(showlegend=False, title=f"Revenue per {mapping2[time_ago]['granularity']}", margin=dict(l=0, r=0, t=40, b=0), )
152 | fig.update_yaxes(range=[0, df_ts["revenue"].max() * 1.1])
153 | with st.container(border=True):
154 | st.plotly_chart(fig, use_container_width=True)
155 |
156 | left, right = st.columns(2)
157 |
158 | with left:
159 | curs.execute("""
160 | SELECT ToDateTime(ts, 'HH:mm:ss:SSS') AS dateTime, status, price, userId, productsOrdered, totalQuantity
161 | FROM orders
162 | ORDER BY ts DESC
163 | LIMIT 10
164 | """)
165 |
166 | df = pd.DataFrame(curs, columns=[item[0] for item in curs.description])
167 | # Potential todo: convert time to datetime for better formatting in data_editor
168 | with st.container(border=True):
169 | st.subheader("Latest orders")
170 | st.data_editor(
171 | df,
172 | column_config={
173 | "dateTime": "Time",
174 | "status": "Status",
175 | "price": st.column_config.NumberColumn("Price", format="₹%.2f"),
176 | "userId": st.column_config.NumberColumn("User ID", format="%d"),
177 | "productsOrdered": st.column_config.NumberColumn("Quantity", help="Quantity of distinct products ordered", format="%d"),
178 | "totalQuantity": st.column_config.NumberColumn("Total quantity", help="Total quantity ordered", format="%d"),
179 | },
180 | disabled=True
181 | )
182 |
183 | with right:
184 | with st.container(border=True):
185 | st.subheader("Most popular categories")
186 |
187 | curs.execute("""
188 | SELECT "product.category" AS category,
189 | distinctcount(orderId) AS orders,
190 | sum("orderItem.quantity") AS quantity
191 | FROM order_items_enriched
192 | where ts > ago(%(timeAgo)s)
193 | group by category
194 | ORDER BY count(*) DESC
195 | LIMIT 5
196 | """, {"timeAgo": mapping2[time_ago]["period"]})
197 |
198 | df = pd.DataFrame(curs, columns=[item[0] for item in curs.description])
199 | df["quantityPerOrder"] = df["quantity"] / df["orders"]
200 |
201 | st.data_editor(
202 | df,
203 | column_config={
204 | "category": "Category",
205 | "orders": st.column_config.NumberColumn("Number of orders", format="%d"),
206 | "quantity": st.column_config.NumberColumn("Total quantity ordered", format="$%d"),
207 | "quantityPerOrder": st.column_config.NumberColumn("Average quantity per order", format="%d"),
208 | },
209 | disabled=True
210 | )
211 |
212 | curs.execute("""
213 | SELECT "product.name" AS product,
214 | "product.image" AS image,
215 | distinctcount(orderId) AS orders,
216 | sum("orderItem.quantity") AS quantity
217 | FROM order_items_enriched
218 | where ts > ago(%(timeAgo)s)
219 | group by product, image
220 | ORDER BY count(*) DESC
221 | LIMIT 5
222 | """, {"timeAgo": mapping2[time_ago]["period"]})
223 |
224 | df = pd.DataFrame(curs, columns=[item[0] for item in curs.description])
225 | df["quantityPerOrder"] = df["quantity"] / df["orders"]
226 |
227 | with st.container(border=True):
228 | st.subheader("Most popular items")
229 | st.data_editor(
230 | df,
231 | use_container_width=True,
232 | column_config={
233 | "product": "Product",
234 | "image": st.column_config.ImageColumn(label="Image", width="medium"),
235 | "orders": st.column_config.NumberColumn("Number of orders", format="%d"),
236 | "quantity": st.column_config.NumberColumn("Total quantity ordered", format="$%d"),
237 | "quantityPerOrder": st.column_config.NumberColumn("Average quantity per order", format="%d"),
238 | },
239 | disabled=True
240 | )
241 |
242 | curs.close()
243 |
244 | if auto_refresh:
245 | time.sleep(number)
246 | st.experimental_rerun()
247 |
--------------------------------------------------------------------------------
/streamlit/app_v1.py:
--------------------------------------------------------------------------------
1 | import pandas as pd
2 | import streamlit as st
3 | from pinotdb import connect
4 |
5 | import plotly.graph_objects as go
6 | import time
7 | from datetime import datetime
8 |
9 | st.set_page_config(layout="wide")
10 | st.header("Pizza App Dashboard ")
11 |
12 | now = datetime.now()
13 | dt_string = now.strftime("%d %B %Y %H:%M:%S")
14 | st.write(f"Last update: {dt_string}")
15 |
16 | if not "sleep_time" in st.session_state:
17 | st.session_state.sleep_time = 2 # <1>
18 |
19 | if not "auto_refresh" in st.session_state:
20 | st.session_state.auto_refresh = True # <2>
21 |
22 | auto_refresh = st.checkbox('Auto Refresh?', st.session_state.auto_refresh)
23 |
24 | if auto_refresh:
25 | number = st.number_input('Refresh rate in seconds', value=st.session_state.sleep_time) # <3>
26 | st.session_state.sleep_time = number
27 |
28 | conn = connect(host='localhost', port=9000, path='/sql', scheme='http')
29 |
30 | query = """
31 | select count(*) FILTER(WHERE ts > ago('PT1M')) AS events1Min,
32 | count(*) FILTER(WHERE ts <= ago('PT1M') AND ts > ago('PT2M')) AS events1Min2Min,
33 | sum(total) FILTER(WHERE ts > ago('PT1M')) AS total1Min,
34 | sum(total) FILTER(WHERE ts <= ago('PT1M') AND ts > ago('PT2M')) AS total1Min2Min
35 | from orders
36 | where ts > ago('PT2M')
37 | limit 1
38 | """
39 | curs = conn.cursor()
40 | curs.execute(query)
41 | df_summary = pd.DataFrame(curs, columns=[item[0] for item in curs.description])
42 | # st.write(df_summary)
43 |
44 | metric1, metric2, metric3 = st.columns(3)
45 |
46 | metric1.metric(
47 | label="# of Orders",
48 | value="{:,}".format(int(df_summary['events1Min'].values[0])),
49 | delta="{:,}".format(int(df_summary['events1Min'].values[0] - df_summary['events1Min2Min'].values[0]))
50 | )
51 |
52 | metric2.metric(
53 | label="Revenue in ₹",
54 | value="{:,.2f}".format(df_summary['total1Min'].values[0]),
55 | delta="{:,.2f}".format(df_summary['total1Min'].values[0] - df_summary['total1Min2Min'].values[0])
56 | )
57 |
58 | average_order_value_1min = df_summary['total1Min'].values[0] / int(df_summary['events1Min'].values[0])
59 | average_order_value_1min_2min = df_summary['total1Min2Min'].values[0] / int(df_summary['events1Min2Min'].values[0])
60 |
61 | metric3.metric(
62 | label="Average order value in ₹",
63 | value="{:,.2f}".format(average_order_value_1min),
64 | delta="{:,.2f}".format(average_order_value_1min - average_order_value_1min_2min)
65 | )
66 |
67 | query = """
68 | select ToDateTime(DATETRUNC('minute', ts), 'yyyy-MM-dd hh:mm:ss') AS dateMin,
69 | count(*) AS orders,
70 | sum(total) AS revenue
71 | from orders
72 | where ts > ago('PT1H')
73 | group by dateMin
74 | order by dateMin desc
75 | LIMIT 10000
76 | """
77 |
78 | curs.execute(query)
79 |
80 | df_ts = pd.DataFrame(curs, columns=[item[0] for item in curs.description])
81 |
82 | df_ts_melt = pd.melt(df_ts, id_vars=['dateMin'], value_vars=['revenue', 'orders'])
83 |
84 | col1, col2 = st.columns(2)
85 | with col1:
86 | orders = df_ts_melt[df_ts_melt.variable == "orders"]
87 | latest_date = orders.dateMin.max()
88 | latest_date_but_one = orders.sort_values(by=["dateMin"], ascending=False).iloc[[1]].dateMin.values[0]
89 |
90 | revenue_complete = orders[orders.dateMin < latest_date]
91 | revenue_incomplete = orders[orders.dateMin >= latest_date_but_one]
92 |
93 | fig = go.FigureWidget(data=[
94 | go.Scatter(x=revenue_complete.dateMin, y=revenue_complete.value, mode='lines', line={'dash': 'solid', 'color': 'green'}),
95 | go.Scatter(x=revenue_incomplete.dateMin, y=revenue_incomplete.value, mode='lines', line={'dash': 'dash', 'color': 'green'}),
96 | ])
97 | fig.update_layout(showlegend=False, title="Orders per minute", margin=dict(l=0, r=0, t=40, b=0),)
98 | fig.update_yaxes(range=[0, df_ts["orders"].max() * 1.1])
99 | st.plotly_chart(fig, use_container_width=True)
100 |
101 | with col2:
102 | revenue = df_ts_melt[df_ts_melt.variable == "revenue"]
103 | latest_date = revenue.dateMin.max()
104 | latest_date_but_one = revenue.sort_values(by=["dateMin"], ascending=False).iloc[[1]].dateMin.values[0]
105 |
106 | revenue_complete = revenue[revenue.dateMin < latest_date]
107 | revenue_incomplete = revenue[revenue.dateMin >= latest_date_but_one]
108 |
109 | fig = go.FigureWidget(data=[
110 | go.Scatter(x=revenue_complete.dateMin, y=revenue_complete.value, mode='lines', line={'dash': 'solid', 'color': 'blue'}),
111 | go.Scatter(x=revenue_incomplete.dateMin, y=revenue_incomplete.value, mode='lines', line={'dash': 'dash', 'color': 'blue'}),
112 | ])
113 | fig.update_layout(showlegend=False, title="Revenue per minute", margin=dict(l=0, r=0, t=40, b=0),)
114 | fig.update_yaxes(range=[0, df_ts["revenue"].max() * 1.1])
115 | st.plotly_chart(fig, use_container_width=True)
116 |
117 | if auto_refresh:
118 | time.sleep(number)
119 | st.experimental_rerun()
--------------------------------------------------------------------------------
/streamlit/requirements.txt:
--------------------------------------------------------------------------------
1 | streamlit==1.31.0
2 | plotly==5.10.0
3 | pinotdb==0.4.5
4 | ipywidgets==8.0.2
5 | altair<5
6 |
--------------------------------------------------------------------------------
/streamlit/schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "schemaName": "orders",
3 | "dimensionFieldSpecs": [
4 | {
5 | "name": "id",
6 | "dataType": "STRING"
7 | },
8 | {
9 | "name": "userId",
10 | "dataType": "INT"
11 | },
12 | {
13 | "name": "status",
14 | "dataType": "STRING"
15 | },
16 | {
17 | "name": "items",
18 | "dataType": "JSON"
19 | }
20 | ],
21 | "metricFieldSpecs": [
22 | {
23 | "name": "productsOrdered",
24 | "dataType": "INT"
25 | },
26 | {
27 | "name": "totalQuantity",
28 | "dataType": "INT"
29 | },
30 | {
31 | "name": "price",
32 | "dataType": "DOUBLE"
33 | }
34 | ],
35 | "dateTimeFieldSpecs": [
36 | {
37 | "name": "ts",
38 | "dataType": "TIMESTAMP",
39 | "format": "1:MILLISECONDS:EPOCH",
40 | "granularity": "1:MILLISECONDS"
41 | }
42 | ]
43 | }
--------------------------------------------------------------------------------