Skip to content

Commit

Permalink
Big event storm
Browse files Browse the repository at this point in the history
  • Loading branch information
seanchatmangpt committed Feb 17, 2024
1 parent 0396ff4 commit 0997275
Show file tree
Hide file tree
Showing 104 changed files with 2,300 additions and 243 deletions.
39 changes: 38 additions & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ jinja2-time = "^0.2.0"
jinja2-ext = "^0.1"
faker = "^22.5.1"
pytest-asyncio = "^0.23.4"
playwright = "^1.41.2"

[tool.poetry.group.test.dependencies] # https://python-poetry.org/docs/master/managing-dependencies/
coverage = { extras = ["toml"], version = ">=7.2.5" }
Expand Down
File renamed without changes.
56 changes: 56 additions & 0 deletions src/autospider/actors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
from rdddy.actor import Actor
from rdddy.actor_system import ActorSystem
from autospider.messages import (
StartScrapingCommand,
EvaluateScrapingPreconditionQuery,
ScrapingPreconditionEvaluatedEvent,
ExecuteScrapingCommand,
ScrapingErrorEvent,
EvaluateScrapingPostconditionQuery,
ScrapingPostconditionEvaluatedEvent,
ScrapingCompletedEvent,
)


class InitiationActor(Actor):
async def handle_start_scraping_command(self, message: StartScrapingCommand):
print(f"Received StartScrapingCommand: Starting scraping for URL {message.url}")
# Example: Trigger precondition evaluation
await self.publish(EvaluateScrapingPreconditionQuery(url=message.url))


class PreconditionActor(Actor):
async def handle_evaluate_scraping_precondition_query(self, message: EvaluateScrapingPreconditionQuery):
print(f"Evaluating scraping precondition for URL {message.url}")
# Example: Pretend the precondition is always met
await self.publish(ScrapingPreconditionEvaluatedEvent(url=message.url, result=True))


class ProcessingActor(Actor):
async def handle_scraping_precondition_evaluated_event(self, message: ScrapingPreconditionEvaluatedEvent):
if message.result:
print(f"Precondition met for URL {message.url}, executing scraping...")
await self.publish(ExecuteScrapingCommand(url=message.url))
else:
print(f"Precondition not met for URL {message.url}, aborting...")
await self.publish(ScrapingErrorEvent(url=message.url, error_message="Precondition failed"))


class ExecutionActor(Actor):
async def handle_execute_scraping_command(self, message: ExecuteScrapingCommand):
print(f"Executing scraping for URL {message.url}")
# Example: After execution, evaluate postconditions
await self.publish(EvaluateScrapingPostconditionQuery(url=message.url))

async def handle_evaluate_scraping_post_condition_query(self, message:EvaluateScrapingPostconditionQuery):
await self.publish(ScrapingPostconditionEvaluatedEvent(url=message.url, result=True))


class CompletionActor(Actor):
async def handle_scraping_postcondition_evaluated_event(self, message: ScrapingPostconditionEvaluatedEvent):
if message.result:
print(f"Scraping completed successfully for URL {message.url}.")
await self.publish(ScrapingCompletedEvent(url=message.url, scraped_data={"hello": "world"}))
else:
print(f"Postconditions not met for URL {message.url}.")
await self.publish(ScrapingErrorEvent(url=message.url, error_message="Postcondition failed"))
37 changes: 37 additions & 0 deletions src/autospider/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import asyncio

from autospider.messages import StartScrapingCommand
from rdddy.actor_system import ActorSystem

# Assuming the actor classes are defined in a module named `autospider_actors`
from autospider.actors import (
InitiationActor,
PreconditionActor,
ProcessingActor,
ExecutionActor,
CompletionActor,
)


async def setup_and_run():
# Create the Actor System
actor_system = ActorSystem()

# Initialize actors
initiation_actor = await actor_system.actor_of(InitiationActor)
precondition_actor = await actor_system.actor_of(PreconditionActor)
processing_actor = await actor_system.actor_of(ProcessingActor)
execution_actor = await actor_system.actor_of(ExecutionActor)
completion_actor = await actor_system.actor_of(CompletionActor)

# Start the scraping process by sending a StartScrapingCommand
# Replace 'http://example.com' with the actual URL you want to scrape
await actor_system.publish(StartScrapingCommand(url="http://example.com"))
await asyncio.sleep(60)

async def main():
await setup_and_run()


if __name__ == "__main__":
asyncio.run(main())
41 changes: 41 additions & 0 deletions src/autospider/messages.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from rdddy.messages import *

class StartScrapingCommand(Command):
"""Command to initiate scraping for a given URL."""
url: str

class EvaluateScrapingPreconditionQuery(Query):
"""Query to evaluate if the preconditions for scraping a URL are met."""
url: str

class ScrapingPreconditionEvaluatedEvent(Event):
"""Event indicating the result of scraping preconditions evaluation."""
phase_name: str = "Scraping Precondition Evaluation"
url: str
result: bool

class ExecuteScrapingCommand(Command):
"""Command to execute the scraping process for a given URL."""
url: str

class ScrapingErrorEvent(Event):
"""Event indicating an error occurred during the scraping process."""
phase_name: str
url: str
error_message: str

class EvaluateScrapingPostconditionQuery(Query):
"""Query to evaluate if the postconditions after scraping a URL are met."""
url: str

class ScrapingPostconditionEvaluatedEvent(Event):
"""Event indicating the result of scraping postconditions evaluation."""
phase_name: str = "Scraping Postcondition Evaluation"
url: str
result: bool

class ScrapingCompletedEvent(Event):
"""Event indicating the completion of the scraping process."""
phase_name: str = "Scraping Completed"
url: str
scraped_data: dict # Assuming scraped data is stored as a dictionary
4 changes: 4 additions & 0 deletions src/elixir/ping_pong/.formatter.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Used by "mix format"
[
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]
26 changes: 26 additions & 0 deletions src/elixir/ping_pong/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# The directory Mix will write compiled artifacts to.
/_build/

# If you run "mix test --cover", coverage assets end up here.
/cover/

# The directory Mix downloads your dependencies sources to.
/deps/

# Where third-party dependencies like ExDoc output generated docs.
/doc/

# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch

# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump

# Also ignore archive artifacts (built via "mix archive.build").
*.ez

# Ignore package tarball (built via "mix hex.build").
ping_pong-*.tar

# Temporary files, for example, from tests.
/tmp/
21 changes: 21 additions & 0 deletions src/elixir/ping_pong/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# PingPong

**TODO: Add description**

## Installation

If [available in Hex](https://hex.pm/docs/publish), the package can be installed
by adding `ping_pong` to your list of dependencies in `mix.exs`:

```elixir
def deps do
[
{:ping_pong, "~> 0.1.0"}
]
end
```

Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
be found at <https://hexdocs.pm/ping_pong>.

18 changes: 18 additions & 0 deletions src/elixir/ping_pong/lib/ping_pong.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
defmodule PingPong do
@moduledoc """
Documentation for `PingPong`.
"""

@doc """
Hello world.
## Examples
iex> PingPong.hello()
:world
"""
def hello do
:world
end
end
24 changes: 24 additions & 0 deletions src/elixir/ping_pong/lib/ping_pong/ping_pong_elixir.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
defmodule PingPong.Elixir do
use GenServer

def start_link do
GenServer.start_link(__MODULE__, [], name: :ping_pong)
end

def init([]) do
port = Port.open({:spawn, 'python/python_side.py'}, [:binary])
{:ok, port}
end

def handle_call(:ping, _from, port) do
json_msg = Jason.encode!(%{action: "ping"})
send(port, {self(), json_msg})
{:noreply, port}
end

def handle_info({:pong, json_msg}, port) do
data = Jason.decode!(json_msg)
IO.puts("Elixir: Received pong - Data: #{inspect(data)}")
{:noreply, port}
end
end
34 changes: 34 additions & 0 deletions src/elixir/ping_pong/mix.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
defmodule PingPong.MixProject do
use Mix.Project

def project do
[
app: :ping_pong,
version: "0.1.0",
elixir: "~> 1.15",
start_permanent: Mix.env() == :prod,
deps: deps()
]
end

# Run "mix help compile.app" to learn about applications.
def application do
[
extra_applications: [:logger]
]
end

# Run "mix help deps" to learn about dependencies.
defp deps do
[
# {:dep_from_hexpm, "~> 0.3.0"},
# {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
]
end
end

# ... Existing content in mix.exs ..

defp deps do
[ {:jason, "~> 1.2"} ]
end
8 changes: 8 additions & 0 deletions src/elixir/ping_pong/test/ping_pong_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
defmodule PingPongTest do
use ExUnit.Case
doctest PingPong

test "greets the world" do
assert PingPong.hello() == :world
end
end
1 change: 1 addition & 0 deletions src/elixir/ping_pong/test/test_helper.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ExUnit.start()
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading

0 comments on commit 0997275

Please sign in to comment.