├── .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 | ![Architecture Diagram](images/architecture.png) 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 | } --------------------------------------------------------------------------------